0

我正在开发一个测试来尝试理解视图和视图组的行为。我创建了一个非常简单的自定义视图组(以下称为 viewgroup1),我已经正确实现了所有重要的方法(onLayout、onMeasure、onSizeChanged)。然后,我创建了一个简单的视图,并将视图从 onclick 事件添加到 viewgroup1。正确显示视图并调用其方法(onSizeChanged、onLayout、onDraw)。

在成功的测试之后,我创建了另一个自定义视图组(以下称为 viewgroup2),这次我将 viewgroup2 添加到了 viewgroup1。然后我将自定义视图从 onclick 事件添加到 viewgroup2。我希望一切都会像第一次测试一样发生,但是当我单击 viewgroup2 时,视图被添加到这个视图中,但是只调用了 viewgroup1 方法(onMeasure,onLayout)。调用不会沿继承树传播。

结果是树结构是正确的,但是尽管我为每个对象调用了 requestLayout、forcelayout 等,但视图没有显示。

树形结构为:viewgroup1---viewgroup2---view。

清单代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yoredevelopment.tests"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="11" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AndroidTestsActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

布局代码(main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.yoredevelopment.tests"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ff000000"
    android:orientation="vertical" >
        <com.yoredevelopment.tests.TestViewGroup
                android:id="@+id/TestViewGroup"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:background="#ff00cccc"
                />
</LinearLayout>

活动代码:

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

public class AndroidTestsActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

视图和视图组代码:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class TestViewGroup extends ViewGroup {
    public TestViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
        TestViewChild tvc = new TestViewChild(context);
        tvc.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        tvc.setBackgroundColor(Color.WHITE);
        this.addView(tvc);
    }

    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if(this.getChildCount() > 0) {
            View child = this.getChildAt(0);
            View p = (View)this.getParent();
            child.layout(20, 20, p.getWidth() - 40, p.getHeight() - 40);
        }
    }

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

    class TestViewChild extends ViewGroup {
        public TestViewChild(Context context) {
            super(context);
            this.setOnClickListener(new TestClickListener());
        }

        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            if(this.getChildCount() > 0) {
                View child = this.getChildAt(0);
                child.layout(10, 10, 40, 40);
            }
        }

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

    class TestView extends View {
        private Paint p;
        public TestView(Context context) {
            super(context);
            p = new Paint();
            p.setColor(Color.RED);
            p.setStyle(Style.FILL);
        }

        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int centerX = this.getWidth() / 2;
            int centerY = this.getHeight() / 2;
            canvas.drawCircle(centerX, centerY, 5, this.p);
        }

        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);
        }

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

    class TestClickListener implements OnClickListener {
        public void onClick(View v) {
            ViewGroup vg = (ViewGroup)v;
            TestView tv = new TestView(vg.getContext());
            tv.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            tv.setBackgroundColor(Color.GREEN);
            vg.addView(tv);
            tv.bringToFront();
        }
    }
}

如果我在 ViewGroup2 构造函数中创建视图,则会显示视图,但在从 onclick 事件创建视图时不会发生。

提前致谢,祝您假期愉快。

4

1 回答 1

0

Two things spring to mind from the source code:

1/ You've not provided LayoutParams for any of the Views - you should use them when adding a View as a child.

2/ Your onMeasure code is incorrect in all three cases. You're using super to do the measurement, then getting the size from the spec (which may be 0) and overriding what super measured. Remove them all to let super handle them.

于 2012-12-30T10:40:54.837 回答