动态添加 TableRow 与 getMeasuredHeight/getHeight 的问题

发布于 2024-08-23 06:20:03 字数 2881 浏览 2 评论 0原文

我有一个问题。

我希望将行动态添加到 TableLayout 中。添加这些行时,我需要能够获取视图的大小,因此我尝试在 onSizeChanged() 期间执行此操作,但新行不会显示。因此,我尝试了 onFinishInflate(),但随后我无法访问尺寸(getMeasuredHeight 返回 0)

以下代码的输出显示两行initial row + onFinishInflate getMeasuredHeight=0。但是,如果我使用 sdk 中的 HierarchyViewer 并按加载视图层次结构,那么我突然在模拟器中看到 3 行初始行 + onFinishInflate getMeasuredHeight=0 + onSizeChanged getMeasuredHeight=270

注意:这是使用模拟器 2.1 hvga 景观,代码构建于 最新的sdk,针对android1.5。


<?xml version="1.0" encoding="utf-8"?>
<com.steelbytes.android.TableHeightTest.TestLinLay 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TableLayout
        android:id="@+id/table1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        <TableRow
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                >
                <TextView
                    android:text="initial row"
                />
            </TableRow>
        </TableLayout>
</com.steelbytes.android.TableHeightTest.TestLinLay>

package com.steelbytes.android.TableHeightTest;

import android.app.Activity;
import android.os.Bundle;

public class TableHeightTest extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

package com.steelbytes.android.TableHeightTest;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class TestLinLay extends LinearLayout
{
 Context mContext;

 public TestLinLay(Context context, AttributeSet attrs)
 {
  super(context, attrs);
  mContext = context;
 }

    private void addRow(String funcName)
    {
        TableLayout tl = (TableLayout)findViewById(R.id.table1);
        TableRow tr = new TableRow(mContext);
        TextView tv = new TextView(mContext);
        tv.setText(funcName+" getMeasuredHeight="+tl.getMeasuredHeight());
        tr.addView(tv);
        tl.addView(tr);
    }

    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();
        addRow("onFinishInflate");
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w,h,oldw,oldh);
        addRow("onSizeChanged");
    }
}

I've got a problem.

I wish to add rows dynamically to a TableLayout. When adding these rows I need to be able to get the size of the View, so I attempt to perform this during onSizeChanged() but the new rows don't display. So I tried onFinishInflate(), but then I don't have access to the size (getMeasuredHeight returns 0).

Output of the following codes shows two rows initial row + onFinishInflate getMeasuredHeight=0. But if i use hierarchyviewer from the sdk and press load view hierarchy then i suddenly see 3 rows in the emulator initial row + onFinishInflate getMeasuredHeight=0 + onSizeChanged getMeasuredHeight=270!.

Note: This is using emulator 2.1 hvga landscape, code built with
latest sdk, targeting android1.5.


<?xml version="1.0" encoding="utf-8"?>
<com.steelbytes.android.TableHeightTest.TestLinLay 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TableLayout
        android:id="@+id/table1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        <TableRow
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                >
                <TextView
                    android:text="initial row"
                />
            </TableRow>
        </TableLayout>
</com.steelbytes.android.TableHeightTest.TestLinLay>

package com.steelbytes.android.TableHeightTest;

import android.app.Activity;
import android.os.Bundle;

public class TableHeightTest extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

package com.steelbytes.android.TableHeightTest;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class TestLinLay extends LinearLayout
{
 Context mContext;

 public TestLinLay(Context context, AttributeSet attrs)
 {
  super(context, attrs);
  mContext = context;
 }

    private void addRow(String funcName)
    {
        TableLayout tl = (TableLayout)findViewById(R.id.table1);
        TableRow tr = new TableRow(mContext);
        TextView tv = new TextView(mContext);
        tv.setText(funcName+" getMeasuredHeight="+tl.getMeasuredHeight());
        tr.addView(tv);
        tl.addView(tr);
    }

    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();
        addRow("onFinishInflate");
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w,h,oldw,oldh);
        addRow("onSizeChanged");
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉城凉梦凉人心 2024-08-30 06:20:03

您可以通过调用 View.measure(int widthMeasureSpec, int heightMeasureSpec)( http://developer.android.com/reference/android/view/View.html#measure%28int,%20int%29 ) 在调用 getMeasuredWidth/getMeasuredHeight 之前。

You would get measured height well by calling View.measure(int widthMeasureSpec, int heightMeasureSpec)( http://developer.android.com/reference/android/view/View.html#measure%28int,%20int%29 ) before calling getMeasuredWidth/getMeasuredHeight.

最初的梦 2024-08-30 06:20:03

我也有同样的问题。最终我偶然发现了以下“规则”:
您不能/不应该在“布局传递”(onSizeChanged())期间 requestLayout(),正确的方法是“发布一个 Runnable”稍后再执行。这是我在 onSizeChanged() 覆盖完成时使用的代码(我已经调整了所有按钮的大小)

// Note: 'posting a Runnable' is required to call requestLayout(),
// not supposed to call requestLayout() during a 
// layout pass (onSizeChanged())
private Handler handler;        // for posting request(s)

(In constructor code)
{
    handler = new Handler();
}

/*
 * Post request to run a loop requesting button layout so
 * the buttons will be drawn using their new size.
 */
private void postLayoutRequest() {
handler.post(new Runnable() {
    @Override public void run() {
    for(int i = BTN_BASE_ID; i <= TOP_BUTTON_ID; ++i) {
            ButtonEx btn = (ButtonEx)findViewById(i);
            btn.requestLayout();
        }
    }
});
}

I had the same problem. Eventually I stumbled on the following "rule":
You cannot/shouldn't requestLayout() during a "layout pass" (onSizeChanged()), the correct way to do it is to 'post a Runnable' to do it a little later. Here's my code I use when my onSizeChanged() override finishes(I've resized all my buttons)

// Note: 'posting a Runnable' is required to call requestLayout(),
// not supposed to call requestLayout() during a 
// layout pass (onSizeChanged())
private Handler handler;        // for posting request(s)

(In constructor code)
{
    handler = new Handler();
}

/*
 * Post request to run a loop requesting button layout so
 * the buttons will be drawn using their new size.
 */
private void postLayoutRequest() {
handler.post(new Runnable() {
    @Override public void run() {
    for(int i = BTN_BASE_ID; i <= TOP_BUTTON_ID; ++i) {
            ButtonEx btn = (ButtonEx)findViewById(i);
            btn.requestLayout();
        }
    }
});
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文