鹅厂系列三 : 仿QQ消息拖动小球

本文介绍了如何在Android中模仿QQ消息拖动小球的功能。通过自定义View,利用onDraw方法绘制圆和贝塞尔曲线,实现小球的拖动效果。同时讨论了在ListView中添加此组件的实现方式,以及处理触摸事件和回弹动画的逻辑。文章提供源码下载链接供读者参考。
摘要由CSDN通过智能技术生成

未来会怎样,我不知道,我只是想为了比今天好

老规矩,看看效果
效果1效果2效果3

嗯,前面自定义了两个视图容器,今天这个是自定义View,开始自定义前,我们应该理清自己的思路,怎么来做这个东西.用我们的QQ,我们会发现,它可以拖动,有两个圆,中间像个橡皮泥连着,所以我是这么想的,我们可以在它初始状态下,画两个圆,一个固定不动,一个可以拖动,且上面还要画个数字.嗯,我们先来完成这个.

public class DragBall extends View {
   

    private Paint mPaint;
    private PointF mCicleCenterPoint;
    private PointF mDragCicleCenter;
    private float mRadius;
    private float mDragRadius;
    private Paint mTextPaint;
    private int mStatusBarHeight;

    private int mRang;
    private float saveRdius = 0;
    private int mNumber = 0;

    public DragBall(Context context) {
        this(context, null);
    }

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

    public DragBall(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setAntiAlias(true);  //抗锯齿
        mPaint.setStyle(Paint.Style.FILL);  //填充
        mPaint.setDither(true);             //防抖动

        mRadius = dp2px(context, 9);        //半径9dp
        mDragRadius = mRadius;

        saveRdius = mRadius;

        mTextPaint = new Paint();
        mTextPaint.setTextAlign(Paint.Align.CENTER);        //字居中对齐
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setTextSize(mRadius * 1.2f);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setDither(true);


        mStatusBarHeight = getStatusBarHeight();

        Log.d("DragBall", "mStatusBarHeight:" + mStatusBarHeight);

    }


    public void setCenterPoint(float x, float y) {


        mCicleCenterPoint = new PointF(x, y);

        mDragCicleCenter = new PointF(x, y);
    }


    public void setDragRang(int rang) {  //拖动范围
        mRang = rang;
    }

    public void setNumber(int number) {
        mNumber = number;

    }

    public int getStatusBarHeight() {
  //获取状态栏高度
        int result = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    public int dp2px(Context context, int dp) {

        return (int) (context.getResources().getDisplayMetrics().density * dp);
    }

    @Override
    protected void onDraw(Canvas canvas) {


        canvas.drawCircle(mCicleCenterPoint.x, mCicleCenterPoint.y, mRadius, mPaint); //画固定圆

        canvas.drawCircle(mDragCicleCenter.x, mDragCicleCenter.y, mDragRadius, mPaint);//画拖动圆

        canvas.drawText("" + mNumber, mDragCicleCenter.x, mDragCicleCenter.y + mDragRadius / 2, mTextPaint); //画文字

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        float delX;
        float dely;
        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:

                break;

            case MotionEvent.ACTION_MOVE:

                mDragCicleCenter.x = event.getRawX();         //手机坐标
                mDragCicleCenter.y = event.getRawY();

                break;

            case MotionEvent.ACTION_UP:

                mDragCicleCenter.x = mCicleCenterPoint.x;
                mDragCicleCenter.y = mCicleCenterPoint.y;              //回到初始位置,固定圆不动

                break;
        }

        invalidate();           //刷新界面 调onDraw
        return true;
    }
}

效果
继承view都要我们重写onDraw方法,里面画板canvas可以画许多东西,这里就不细讲了,我也细讲不了.自我感觉还没理解到那个程度,但基本的我们还是会用的,我们通过触摸事件不断更新拖动圆的圆心坐标和不断重绘invalidate(),达到拖动的效果,但是,发现了吧,这感觉圆心不在我们点的那个位置啊,这是因为画板画的时候,算了状态栏高度,而我们的点是没有算状态栏高度的,即我们本来画(100,100)这个点,画板给我们画到了(100,100+状态栏高度),所以我们要把我们的画板上移状态栏高度再进行绘画.

  @Override
    protected void onDraw(Canvas canvas) {

        canvas.save();
        canvas.translate(0,-mStatusBarHeight);

        canvas.drawCircle(mCicleCenterPoint.x, mCicleCenterPoint.y, mRadius, mPaint)
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值