自定义View 之 Rect与RectF

public class RectView extends View {

    private Paint mPaint;
    private RectF mRect;
    private float mX;
    private float mY;


    public RectView(Context context) {
        super(context);
        init();
    }


    public RectView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }


    public RectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
private void init() {
    mPaint = new Paint();
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    mPaint.setStrokeWidth(5);
    mRect = new RectF(100, 10, 300, 100);
}


@Override
public boolean onTouchEvent(MotionEvent event) {
    mX = event.getX();
    mY = event.getY();
    Log.d("onTouchEvent", "onTouchEvent:--mX== " + mX + "---mY==" + mY);
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        invalidate();
        return true;
    } else if (event.getAction() == MotionEvent.ACTION_UP) {
        mX = -1;
        mY = -1;
    }
    postInvalidate();
    return super.onTouchEvent(event);
}
   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //case1:圆角矩形
        //Paint paint = new Paint();
        //paint.setColor(Color.RED);
        //paint.setStyle(Paint.Style.FILL_AND_STROKE);
        //paint.setStrokeWidth(5);
        //RectF rect = new RectF(100, 10, 300, 100);
        // RectF rect:要绘制的矩形。
        // float rx:生成圆角的椭圆的 X 轴半径。
        //  float ry:生成圆角的椭圆的 Y 轴半径。
        //canvas.drawRoundRect(rect, 50, 50, paint);

        //case2:圆  半径=StrokeWidth/2+剩下的空白
        //canvas.drawCircle(100,100,50,paint);

        //case3:椭圆是由矩形生成的;一个矩形,决定一个椭圆
        //canvas.drawRect(rect,paint);
        //paint.setColor(Color.GREEN);
        //canvas.drawOval(rect,paint);
        //case4 弧是椭圆的一部分,而椭圆是根据矩形来生成的,所以弧也是根据矩形来生成的。
        //带两边 连接圆心
        //canvas.drawArc(rect,0,90, true,paint);
        //不带两边 ,只有圆弧
        //canvas.drawArc(rect,0,90, false,paint);
        //canvas.drawArc(rect,0,90, false,paint);
        //case5  判断是否包含某个点
        //该函数用于判断某个点是否在当前矩形中。
        // 如果在,则返回 true;如果不在,则返回 false。 参数(x,y)就是当前要判断的点的坐标
        if (mRect.contains(mX,mY)){
            mPaint.setColor(Color.RED);
        }else {
            mPaint.setColor(Color.GREEN);
        }
        canvas.drawRect(mRect,mPaint);
    }
}

值得注意的是,在 MotionEvent.ACTION_DOWN 中返回 true,因为当 MotionEvent. ACTION_DOWN 消息到来时,系统会判断返回值,当返回 true 时,表示当前控件已经在拦截 (消费)这个消息了,所以后续的 ACTION_MOVE、ACTION_UP 消息仍然继续传过来。如 果返回 false(系统默认返回 false),就表示当前控件不需要这个消息,那么后续的

ACTION_MOVE、ACTION_UP 消息就不会再传到这个控件。 当用户手指弹起时,我们需要还原矩形的颜色(绿色),所以将 mX,mY 全部设置为负值。

由于我们构造的矩形不包含坐标为负的点,所以也就还原了矩形的颜色。

最后,调用 postInvalidate()函数刷新控件屏幕,让控件重绘。

细心的读者会发现,在 ACTION_DOWN 消息到来时,我们调用了 invalidate()函数重绘控 件。其实,postInvalidate()和 invalidate()函数都是用来重绘控件的,区别是 invalidate()函数一 定要在主线程中执行,否则就会报错;而 postInvalidate()函数则没有那么多讲究,它可以在任何线程中执行,而不必一定是主线程。因为在 postInvalidate()函数中就是利用 handler 给主线 程发送刷新界面的消息来实现的,所以它可以在任何线程中执行而不会出错。而正因为它是 通过发送消息来实现的,所以它的界面刷新速度可能没有直接调用 invalidate()函数那么快。 因此,在确定当前线程是主线程的情况下,还是以 invalidate()函数为主。当我们不确定当前 要刷新界面的位置所处的线程是不是主线程的时候,还是调用 postInvalidate()函数为好;这里 笔者故意调用的是 postInvalidate()函数,因为 onTouchEvent()函数本来就是在主线程中的,所 以使用 invalidate()函数更合适。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值