Android Path进阶之Path路径实现QQ拖拽气泡效果

先上效果图

先将这个过程分状态(阶段):

    1.静止状态,小球的默认状态,由红色的气泡和中间的文本组成;

    2.连接状态(拖拽半径短),拖拽过程中由随着手指一定的气泡和中间不断缩小的小气泡组成;

    3.分离状态(拖拽半径长),中间的小气泡消失,连接的中间线也消失;

    4.回弹或隐藏状态,当从连接状态松手,移动的气泡会回弹到中心,从分离状态松手,移动的气泡爆炸,整个页面隐藏。

1.实现思路

自定义一个DragBubbleView继承View,静止、连接和分离状态都是需要绘制一个大的可动气泡,只是坐标不同,连接状态时,首先随着手指的移动,改变可动气泡的坐标,同时在中心绘制固定气泡,固定气泡的圆心随拖拽半径的变大二变小,大气泡和小气泡中间连接处是两条二阶贝赛尔曲线,贝塞尔曲线可以参考上一小节总结 Android Path进阶之Path常用API,第一条二阶贝塞尔曲线的两个数据点分别是A和B,第二条二阶贝塞尔曲线的两个数据点分别是C和D,两条贝塞尔曲线的控制点都是大气泡和小气泡的圆心连线的中点G,然后两条贝塞尔曲线和两条直线BC和DA闭和,外加大圆和小圆的部分,3部分刚好形成连接状态时的图形绘制,分离状态只需要绘制大气泡,爆炸时使用5张连续的图片顺序播放形成爆炸效果。

2.初始化

对过程进行了分解之后开始实现,首先确定需要使用到的变量,并会其初始化。一只画笔绘制可动气泡中心文本,一只画笔绘制两个气泡和中心不规则图形,一只画笔绘制爆炸时效果,一个路径(Path)用来记录两个气泡中间连接不规则的图形,然后在构造方法中对画笔和路径进行初始化,在onSizeChange中对坐标点初始化。

public class DragBubbleView extends View {

    private static final int BUBBLE_STATE_DEFAULT = 0;//气泡默认状态--静止
    private static final int BUBBLE_STATE_CONNECT = 1;//气泡相连
    private final int BUBBLE_STATE_APART = 2;//气泡分离
    private final int BUBBLE_STATE_DISMISS = 3;//气泡消失
    private float mBubbleRadius = 60;//气泡半径
    private int mBubbleColor = Color.RED;//气泡颜色
    private String mTextStr = "99+";//气泡消息文字
    private int mTextColor = Color.WHITE;//气泡消息文字颜色
    private float mTextSize = 60;//气泡消息文字大小
    private float mBubFixedRadius = mBubbleRadius;//不动气泡的半径
    private float mBubMovableRadius = mBubbleRadius;//可动气泡的半径
    private PointF mBubFixedCenter;//不动气泡的圆心
    private PointF mBubMovableCenter;//可动气泡的圆心
    private Paint mBubblePaint;//气泡的画笔
    private Path mBezierPath;//贝塞尔曲线path
    private Paint mTextPaint;//文本绘制画笔
    private Rect mTextRect;//文本绘制区域
    private Paint mBurstPaint;//气泡爆炸消失画笔
    private Rect mBurstRect;//爆炸绘制区域
    private int mBubbleState = BUBBLE_STATE_DEFAULT;//气泡状态标志
    private float mDist;//两气泡圆心距离
    private float mMaxDist = 4 * mBubbleRadius;//气泡相连状态最大圆心距离
    private float MOVE_OFFSET = 2 * mBubbleRadius;//手指触摸偏移量
    private Bitmap[] mBurstBitmapsArray;//气泡爆炸的bitmap数组
    private boolean mIsBurstAnimStart = false;//是否在执行气泡爆炸动画
    private int mCurDrawableIndex;//当前气泡爆炸图片index

    //气泡爆炸的图片id数组
    private int[] mBurstDrawablesArray = {
            R.drawable.burst_1,
            R.drawable.burst_2,
            R.drawable.burst_3,
            R.drawable.burst_4,
            R.drawable.burst_5
    };

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

    public DragBubbleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DragBubbleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        //初始化气泡画笔
        mBubblePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBubblePaint.setColor(mBubbleColor);
        mBubblePaint.setStyle(Paint.Style.FILL);

        //初始化文本绘制画笔
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(mTextSize);
        mTextRect = new Rect();

        //初始化爆炸画笔
        mBurstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBurstPaint.setFilterBitmap(true);

        //初始化贝赛尔曲线path
        mBezierPath = new Path();

        mBurstRect = new Rect();

        //将气泡爆炸的drawable转为bitmap
        mBurstBitmapsArray = new Bitmap[mBurstDrawablesArray.length];
        for (int i = 0; i < mBurstDrawablesArray.length; i++) {
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), mBurstDrawablesArray[i]);
            mBurstBitmapsArray[i] = bitmap;
        }

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        //不动气泡圆心
        if (mBubFixedCenter == null) {
            mBubFixedCenter = ne
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值