Android以编程方式添加两个带有画布的视图

时间:2016-09-05 20:03:48

标签: android android-custom-view

我一直在尝试以编程方式将两个带有画布的视图添加到我的活动中,但看起来只有第一个被添加(我可以通过查看控制台输出来判断)。我做错了什么?

这是我的代码:

package app.com.example.android.drawtwoviews;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {
    DrawView drawView;
    DrawView2 drawView2;
    private LinearLayout root;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        root = new LinearLayout(this);
        root.setOrientation(LinearLayout.VERTICAL);

        drawView = new DrawView(this);
        drawView.setBackgroundColor(Color.WHITE);
        root.addView(drawView);

        drawView2 = new DrawView2(this);
        drawView2.setBackgroundColor(Color.WHITE);
        root.addView(drawView2);

        setContentView(root);
    }

    public class DrawView extends View {
        Paint paint = new Paint();

        public DrawView(Context context) {
            super(context);
        }

        @Override
        public void onDraw(Canvas canvas) {
            System.out.println("DrawView1");
            paint.setColor(Color.BLACK);
            //paint.setStrokeWidth(3);
            canvas.drawRect(30, 30, 80, 80, paint);


        }

    }


    public class DrawView2 extends View {
        Paint paint = new Paint();

        public DrawView2(Context context) {
            super(context);
        }

        @Override
        public void onDraw(Canvas canvas) {
            System.out.println("DrawView2");
            paint.setColor(Color.BLUE);
            paint.setStrokeWidth(3);
            canvas.drawRect(300, 300, 400, 400, paint);


        }

    }
}

2 个答案:

答案 0 :(得分:2)

您正在将视图添加到root,而不指定布局参数。这意味着他们都得到了default layout parameters of LinearLayout,对于垂直布局,它是(MATCH_PARENT, WRAP_CONTENT)

您的自定义视图都不会覆盖onMeasure(),这意味着measure的默认建议最小尺寸为0×0。

这意味着您的LinearLayout正在布局两个视图,请求的大小为0×0,布局规范为(MATCH_PARENT, WRAP_CONTENT)。这个问题的解决方法是a bit tricky,但是你的第一个孩子占据了整个屏幕的高度而你的第二个孩子的身高是0px。两个孩子都是全屏宽度。您可以在Hierarchy Viewer

中轻松查看

要解决此问题,您需要指定布局参数:

// in onCreate()
int width = LinearLayout.LayoutParams.MATCH_PARENT;
int height = 0;
int weight = 1;
LinearLayout.LayoutParams params = 
    new LinearLayout.LayoutParams(width, height, weight);

drawView = new DrawView(this);
drawView.setBackgroundColor(Color.WHITE);
root.addView(drawView, params); // note the extra argument

drawView2 = new DrawView2(this);
drawView2.setBackgroundColor(Color.WHITE);
root.addView(drawView2, params); // note the extra argument

或者您可以修改DrawView以便它们测量到某个最小尺寸:

public class DrawView extends View {
    // paint
    // constructor
    // onDraw

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        setMeasuredDimension(80, 80);
    }
}


public class DrawView2 extends View {
    // paint
    // constructor
    // onDraw

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        setMeasuredDimension(400, 400);
    }
}

答案 1 :(得分:0)

尝试在视图的构造函数中设置此标志:

 public DrawView(Context context) {
        super(context);
        setWillNotDraw(false);
}

这是必要的,因为您的视图并不知道您想要进行自定义绘制,并且onDraw()永远不会被调用,因为没有任何东西可以绘制。