Android 在现有视图上绘制形状

Android 在现有视图上绘制形状,android,view,drawing,android-canvas,Android,View,Drawing,Android Canvas,我有一个视图,我想在单击后在其上绘制一个形状(例如圆形)。 我试过这么做,但有两个问题- 从来没有人叫过昂德劳 不确定setLayoutParams(v.getLayoutParams)是否会给出我想要的结果 @Override public void onClick(View v) { CircleView circle = new CircleView(GameXoActivity.this, v.getWidth(), v.getHeight());

我有一个视图,我想在单击后在其上绘制一个形状(例如圆形)。

我试过这么做,但有两个问题-

  • 从来没有人叫过昂德劳
  • 不确定setLayoutParams(v.getLayoutParams)是否会给出我想要的结果

        @Override
        public void onClick(View v) {
            CircleView circle = new CircleView(GameXoActivity.this, v.getWidth(), v.getHeight());
            circle.setLayoutParams(v.getLayoutParams());
            circle.startDrawing();
        }
    
  • CircleView:

        public CircleView(Context context, int width, int height) {
            super(context);
            this.width = width;
            this.height = height;
        }
    
        protected void startDrawing() {
            this.postInvalidate(); 
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            Log.d("TAG", "onDraw");
            // draw circle
            }
        }
    
    }
    
    更新:

    这个形状不是一个图像,我想用动画来画它(我没有写完整的代码)。 此外,形状并不总是圆,因此使用可绘制状态不是选项。
    因为这里不仅有一个视图,还有9个视图,我不认为在它们上面再增加9个视图是正确的。

    如果你想搞乱对象的绘制,你应该覆盖
    公共void draw(画布)
    而不是
    受保护的void onDraw(画布)
    编辑:请阅读评论,我回答的第一句话可能是错误的

    但我会使用框架布局或相对布局,将图像一个接一个地放在一起。 然后,您可以使用覆盖图像的可见性来隐藏/显示它

    编辑:
    如果您的圆不是图像,需要绘制,请创建您自己的圆类扩展视图,并将其用作FrameLayout或RelativeLayout中的组件,就像您在图像中所做的那样。我建议,创建两个尺寸相同的imageView,设置要在图像视图上显示的图像,然后使第二个图像不可见。 例如:

    circleimage.setVisibility(View.INVISIBLE);//now its hidden(do it OnCreate)
    
    然后在单击第一个图像时显示第二个图像(在单击第一个图像时执行此操作)


    我确信您需要对其进行大量定制,因此我将其保留为通用的。以下示例将在单击视图时,在视图内容的顶部,从东(0度)开始,以顺时针方向绘制一个蓝色圆圈

    public class CircleView extends View
    {
        private static final int MARGIN = 50;
    
        Handler handler = new Handler();
        Paint paint = new Paint();
        RectF rect = new RectF();
    
        boolean drawing = false;
        float sweep = 0;
    
        public CircleView(Context context)
        {
            this(context, null);
        }
    
        public CircleView(Context context, AttributeSet attrs)
        {
            super(context, attrs);
    
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(15);
            paint.setColor(Color.BLUE);
        }
    
        @Override
        protected void onDraw(Canvas canvas)
        {
            super.onDraw(canvas);
            canvas.drawArc(rect, 0, sweep, false, paint);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh)
        {
            super.onSizeChanged(w, h, oldw, oldh);
            rect.set(MARGIN, MARGIN, w - MARGIN, h - MARGIN);
        }
    
        public void startAnimation()
        {
            drawing = true;
            handler.post(runnable);
        }
    
        Runnable runnable = new Runnable()
        {
            @Override
            public void run()
            {
                sweep += 10;
                if (!(sweep > 360))
                {
                    invalidate();
                    handler.postDelayed(this, 20);
                }
                else
                {
                    drawing = false;
                    sweep = 0;
                }
            }   
        };
    }
    
    在这个活动示例中,我使用了一个大多数开发人员已经在他们的项目中使用的映像,但它显然可以更改为您的自定义映像。此外,为了简单和简洁,CircleView被设置为活动的全部内容,但也可以很容易地在xml布局中列出

    public class MainActivity extends Activity
    {
        CircleView circle;
    
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
    
            circle = new CircleView(this);
            circle.setBackgroundResource(R.drawable.ic_launcher);
            circle.setOnClickListener(new OnClickListener()
                {
                    @Override
                    public void onClick(View v)
                    {
                        circle.startAnimation();
                    }
                }
            );      
    
            setContentView(circle);
        }
    }
    

    您应该使用选择器。您应该只使用
    invalidate()
    @FrankN.Stein。如果您的答案是正确的,那么它可以帮助其他人。所以很遗憾,你删除了它,否决了我的问题,只是因为我不想删除你的答案。不,不是。毕竟,它不能满足你不断变化的规格。只有一种方法可以画一个圆。你发明了另一个。对不起,我没有解释清楚。祝你好运。你的第一句话不正确。
    draw()
    方法用于将视图渲染到传递给它的画布上
    onDraw()
    在视图呈现自身时被调用,并根据需要将画布交给您进行更改。Mike M我并没有实际测试它。谢谢你纠正我。这不是一个图像,我想用动画画它(我没有写完整的代码)。这就是我使用onDraw()的原因。因为不只是一个视图,而是9,我认为在它们上面再加9是不对的。然后你可以使用AnimationDrawable类并将其设置为叠加视图的背景,然后你必须开始()才能播放动画。我将CircleView添加到布局中(在xml中),现在调用onDraw,但还是什么也没有画出来。但我想这是另一个问题。。我很快会调查的。ThanksIt不仅仅是一个圆形图像,还有其他可以在那里绘制的形状。我想用动画来画它,所以我不能使用可见性。但是如果你在第二张图像上使用帧动画,它看起来像是在画。如果我遗漏了什么,请告诉我。太好了!正是我需要的。谢谢
    public class MainActivity extends Activity
    {
        CircleView circle;
    
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
    
            circle = new CircleView(this);
            circle.setBackgroundResource(R.drawable.ic_launcher);
            circle.setOnClickListener(new OnClickListener()
                {
                    @Override
                    public void onClick(View v)
                    {
                        circle.startAnimation();
                    }
                }
            );      
    
            setContentView(circle);
        }
    }