Android-无法访问onDraw()

时间:2018-10-24 06:00:18

标签: android xml drawing

我必须显示一个可调整大小的矩形。

我的xml文件:

 <RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".exampleActivity">

<ImageView
android:id="@+id/office"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/office"
android:src="@raw/office" />

<com.lambdahash.sonic.example.draw.DrawView
android:id="@+id/drawView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>

显示此活动矩形的代码:

public class DrawView extends View {

    Point point1, point3;
    Point point2, point4;

    /**
     * point1 and point 3 are of same group and same as point 2 and point4
     */
    int groupId = -1;
    private ArrayList<ColorBall> colorballs = new ArrayList<ColorBall>();
    // array that holds the balls
    private int balID = 0;
    // variable to know what ball is being dragged
    Paint paint;
    Canvas canvas;

    public DrawView(Context context) {

        super(context);
        paint = new Paint();
        setFocusable(true); // necessary for getting the touch events
        canvas = new Canvas();

       // this.setWillNotDraw(false); //?

        Log.d("TEST:","DrawView() being called.");

        // setting the start point for the balls
        point1 = new Point();
        point1.x = 50;
        point1.y = 20;

        point2 = new Point();
        point2.x = 150;
        point2.y = 20;

        point3 = new Point();
        point3.x = 150;
        point3.y = 120;

        point4 = new Point();
        point4.x = 50;
        point4.y = 120;

        // declare each ball with the ColorBall class
        colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
        colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
        colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
        colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));

    }

    public DrawView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public DrawView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        setFocusable(true); // necessary for getting the touch events
        canvas = new Canvas();
        // setting the start point for the balls
        point1 = new Point();
        point1.x = 50;
        point1.y = 20;

        point2 = new Point();
        point2.x = 150;
        point2.y = 20;

        point3 = new Point();
        point3.x = 150;
        point3.y = 120;

        point4 = new Point();
        point4.x = 50;
        point4.y = 120;



        // declare each ball with the ColorBall class
        colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
        colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
        colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
        colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));

    }

    // the method that draws the balls
    @Override
    protected void onDraw(Canvas canvas) {

        Log.d("TEST:","onDraw() being called.");

        // canvas.drawColor(0xFFCCCCCC); //if you want another background color

        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setColor(Color.parseColor("#55000000"));
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeJoin(Paint.Join.ROUND);
        // mPaint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(5);

        canvas.drawPaint(paint);
        paint.setColor(Color.parseColor("#55FFFFFF"));

        if (groupId == 1) {
            canvas.drawRect(point1.x + colorballs.get(0).getWidthOfBall() / 2,
                    point3.y + colorballs.get(2).getWidthOfBall() / 2, point3.x
                            + colorballs.get(2).getWidthOfBall() / 2, point1.y
                            + colorballs.get(0).getWidthOfBall() / 2, paint);
        } else {
            canvas.drawRect(point2.x + colorballs.get(1).getWidthOfBall() / 2,
                    point4.y + colorballs.get(3).getWidthOfBall() / 2, point4.x
                            + colorballs.get(3).getWidthOfBall() / 2, point2.y
                            + colorballs.get(1).getWidthOfBall() / 2, paint);
        }
        BitmapDrawable mBitmap;
        mBitmap = new BitmapDrawable();

        // draw the balls on the canvas
        for (ColorBall ball : colorballs) {
            canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(),
                    new Paint());
        }
    }

    //??????????????????
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {


        Log.d("TEST2:","onMeasure() being called.");

        Log.v("Chart onMeasure w", MeasureSpec.toString(widthMeasureSpec));
        Log.v("Chart onMeasure h", MeasureSpec.toString(heightMeasureSpec));

        int desiredWidth = getSuggestedMinimumWidth() + getPaddingLeft() + getPaddingRight();
        int desiredHeight = getSuggestedMinimumHeight() + getPaddingTop() + getPaddingBottom();

        setMeasuredDimension(measureDimension(desiredWidth, widthMeasureSpec),
                measureDimension(desiredHeight, heightMeasureSpec));
    }

    private int measureDimension(int desiredSize, int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = desiredSize;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }

        if (result < desiredSize){
            Log.e("ChartView", "The view is too small, the content might get cut");
        }
        return result;
    }




    // events when touching the screen
    public boolean onTouchEvent(MotionEvent event) {
        int eventaction = event.getAction();

        int X = (int) event.getX();
        int Y = (int) event.getY();

        switch (eventaction) {

            case MotionEvent.ACTION_DOWN: // touch down so check if the finger is on
                // a ball
                balID = -1;
                groupId = -1;
                for (ColorBall ball : colorballs) {
                    // check if inside the bounds of the ball (circle)
                    // get the center for the ball
                    //Utils.logd("Id : " + ball.getID());
                    //Utils.logd("getX : " + ball.getX() + " getY() : " + ball.getY());
                    int centerX = ball.getX() + ball.getWidthOfBall();
                    int centerY = ball.getY() + ball.getHeightOfBall();
                    paint.setColor(Color.CYAN);
                    // calculate the radius from the touch to the center of the ball
                    double radCircle = Math
                            .sqrt((double) (((centerX - X) * (centerX - X)) + (centerY - Y)
                                    * (centerY - Y)));

                    //Utils.logd("X : " + X + " Y : " + Y + " centerX : " + centerX + " CenterY : " + centerY + " radCircle : " + radCircle);

                    if (radCircle < ball.getWidthOfBall()) {

                        balID = ball.getID();
                        //Utils.logd("Selected ball : " + balID);
                        if (balID == 1 || balID == 3) {
                            groupId = 2;
                            canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
                                    paint);
                        } else {
                            groupId = 1;
                            canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
                                    paint);
                        }
                        invalidate();
                        break;
                    }
                    invalidate();
                }

                break;

            case MotionEvent.ACTION_MOVE: // touch drag with the ball
                // move the balls the same as the finger
                if (balID > -1) {
                    //Utils.logd("Moving Ball : " + balID);


                    Log.d("Moving Ball : " ,"" + balID);

                    colorballs.get(balID).setX(X);
                    colorballs.get(balID).setY(Y);

                    paint.setColor(Color.CYAN);

                    if (groupId == 1) {
                        colorballs.get(1).setX(colorballs.get(0).getX());
                        colorballs.get(1).setY(colorballs.get(2).getY());
                        colorballs.get(3).setX(colorballs.get(2).getX());
                        colorballs.get(3).setY(colorballs.get(0).getY());
                        canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
                                paint);
                    } else {
                        colorballs.get(0).setX(colorballs.get(1).getX());
                        colorballs.get(0).setY(colorballs.get(3).getY());
                        colorballs.get(2).setX(colorballs.get(3).getX());
                        colorballs.get(2).setY(colorballs.get(1).getY());
                        canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
                                paint);
                    }

                    invalidate();
                }

                break;

            case MotionEvent.ACTION_UP:
                // touch drop - just do things here after dropping

                break;
        }
        // redraw the canvas
        invalidate();
        return true;

    }

    public void shade_region_between_points() {
        canvas.drawRect(point1.x, point3.y, point3.x, point1.y, paint);
    }
}

最后,使用以下命令在activity.xml上调用它:

public class exampleActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);


       DrawView dv = new DrawView(getApplicationContext());


    }

因此,当我在活动中在onCreate()中调用myDrawView时,我会得到

TEST: myDrawView() constructor called.。但是,在那之后,我没有得到 TEST: onDraw() method called. onDraw()方法由于某种原因未被调用。该怎么办?

3 个答案:

答案 0 :(得分:1)

实际上没有将MyDrawView添加到您的UI的任何操作。它不在您发布的布局中。它不是以编程方式添加到布局中的。仅创建视图不会显示它。

答案 1 :(得分:1)

看起来您既没有在布局文件中也没有在活动代码中添加自定义视图。 尝试像这样添加它。

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".exampleActivity"
>

    <ImageView
        android:id="@+id/office"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/office"
        android:src="@raw/office" 
    />

    <your.package.name.MyDrawView
        android:id="@+id/myAwesomeDrawView"
        android:layout_width="match_parent"
        android:layout_height="200dp" 
    />
</RelativeLayout>

然后它应该显示在您的应用中。

请注意,作为@GabeSechan said,某些容器在测量其宽度和高度为0时不会对视图进行布局。您必须在xml布局文件中指定视图的尺寸,或者提供correct onMeasure()

如果您仍然想以编程方式添加它,则可以使用onCreate()方法,例如:

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

    final RelativeLayout myAwesomeLayout = findViewById(R.id.your_container_id);
    final View myAwesomeView = new View(this);
    someViewsetLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    myAwesomeLayout.addView(myAwesomeView);
}

请注意,约定是在Java中类名以大写字母开头。

一些其他要点:

  • 似乎您在onDraw()中分配了很多对象 方法,可能会导致内存消耗增加和性能下降 性能,最好避免这种情况并尝试重用对象 而不是创建新的。
  • 您的自定义视图构造函数的行为有所不同,并且包含重复的代码,最好移动通用的初始化代码以避免代码重复,您可以尝试这样做
    public class MyDrawView extends View {

        // for example only
        @ColorInt final int fillColor;

        public MyDrawView(final Context context) {
            this(context, null);
        }

        public MyDrawView(final Context context, final AttributeSet attrs) {
            this(context, attrs, 0);
        }

        public MyDrawView(final Context context, final AttributeSet attrs, final int defStyle) {
            super(context, attrs, defStyle);

            // initialize here, like
            fillColor = Color.parseInt("something");
        }
    }

答案 2 :(得分:0)

<ImageView android:id="@+id/office"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/office" android:src="@raw/office" />

这可能是拼写错误吗?那应该是@ draw / office吗?