10

回答済み

ユーザーが垂直または水平にスクロールすると、ビューを動的に追加する RelativeLayout があります。スクロールできるもの全体を構成できる数千のビューが存在する可能性があるため、独自の ViewRecycler をロールバックしましたが、常に 30 程度しか表示しません。カレンダーの拡大表示を考えてみてください。

表示しようとしているビューを追加すると、パフォーマンスの問題が発生します。RelativeLayout で onMeasure が呼び出され、すべての子ビューで onMeasure が呼び出されます。私はすでに RelativeLayout の大きさを計算しており、それを LayoutParameters に設定しているので、ViewGroup を測定する必要はありません。追加されたビューは、それらのビューには関係ありません。

問題を示す簡単な例は、RelativeLayout にビューを追加/削除し、RelativeLayout のサイズや他のビューの位置に影響を与えないにもかかわらず、onMeasure が呼び出されるのを確認することです。

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/shell"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
</LinearLayout>

MyActivity.java

public class MyActivity extends Activity
{

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ViewGroup shell = (ViewGroup) findViewById(R.id.shell);

        final RelativeLayout container = new RelativeLayout(this) {
            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                Log.d("MyActvity", "onMeasure called on map");
            }
        };
        container.setBackgroundColor(Color.rgb(255, 0, 0));
        ViewGroup.LayoutParams containerParams = new ViewGroup.LayoutParams(300, 300);

        final TextView childView = new TextView(this);
        childView.setBackgroundColor(Color.rgb(0, 255, 0));
        childView.setText("Child View");

        Button viewToggle = (Button) findViewById(R.id.button);
        viewToggle.setText("Add/Remove Child View");

        viewToggle.setOnClickListener(new View.OnClickListener() {

            public void onClick(View view) {
                if (childView.getParent() == null) {
                    container.addView(childView, 400, 30);
                } else {
                   container.removeView(childView);
                }
            }
        });

        shell.addView(container, containerParams);
    }
}

これを実行すると、onMeasure への最初の (予想される) 呼び出しが 2 回表示され、次にボタンをクリックしてビューを追加/削除するたびに 1 回表示されます。これは明らかに問題なく実行されますが、ネストされたビューの複雑なレイアウトがある場合に onMeasure を常に呼び出すと問題が発生する可能性があることがわかります。

これらの onMeasure 呼び出しまたは少なくとも onMeasure 呼び出し measureChildren をバイパスする推奨される方法はありますか?

4

3 に答える 3

0

同様の問題が発生しましたが、私の解決策は、寸法が変更されたかどうかを確認することでした:

int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(parentWidth, parentHeight);
if ( mClientWidth == parentWidth && mClientHeight == parentHeight ) {
    return;
}

mClientWidth = parentWidth;
mClientHeight = parentHeight;

したがって、親の次元が実際に変化しない場合、子にカスケードされません。

于 2011-11-08T23:34:37.633 に答える
0

独自の Layout Manager (今後も行う可能性があります) をローリングする代わりに、onMeasure を次のように変更しました。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int count = getChildCount();
    for (int i = 0; count > i; i++) {
        View v = getChildAt(i);

        if (v.getVisibility() != GONE) {
            if (v.getMeasuredWidth() <= 0 || v.getMeasuredHeight() <= 0) {
                measureChild(v,
                    MeasureSpec.makeMeasureSpec(v.getLayoutParams().width,
                        MeasureSpec.AT_MOST),
                    MeasureSpec.makeMeasureSpec(v.getLayoutParams().height,
                        MeasureSpec.AT_MOST));
            }
        }
    }

    setMeasuredDimension(resolveSize(staticContainerWidth, widthMeasureSpec),
        resolveSize(staticContainerHeight, heightMeasureSpec));
}

...そして、コンテナのsudoハードコーディングされた高さと幅を変数として追加しました。これらを期待どおりに設定することは、このソリューションの範囲外です。

int staticContainerHeight = 300;
int staticContainerWidth = 300;
于 2011-08-05T18:43:05.677 に答える