Naci
Naci

Reputation: 231

Android add two views with canvases programmatically

I have been trying to add two views with canvases to my activity programmatically, but it looks like only the first one is being added (I can tell by looking at the console output). What am I doing wrong?

Here is my code:

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);


        }

    }
}

Upvotes: 1

Views: 1672

Answers (2)

breakline
breakline

Reputation: 6073

Try setting this flag in your view's contructor:

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

This is needed because your view doesn't know that you wanna do custom drawing and onDraw() never gets called since there's nothing to draw.

Upvotes: 0

Barend
Barend

Reputation: 17444

You are adding your views to the root without specifying layout parameters. That means they both get the default layout parameters of LinearLayout, which, for a vertical layout, is (MATCH_PARENT, WRAP_CONTENT).

Neither of your custom views overrides onMeasure(), which means both measure to their default suggested minimum size of 0×0.

This means that your LinearLayout is layouting two views with a requested size of 0×0 and a layout spec of (MATCH_PARENT, WRAP_CONTENT). The way this works out is a bit tricky, but your first child takes up the full screen height and your second child is 0px tall. Both children are full screen width. You can easily see this in the Hierarchy Viewer.

To fix the problem, you need to either specify layout params:

// 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

Or you can modify the DrawViews so that they measure to some minimum size:

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);
    }
}

Upvotes: 2

Related Questions