Andoid-----抽奖转盘----12宫格----实用性商业化

简述:

差不多一年半没有更新文章了,这段时间发生很多事情,一直在处理。博客还是正常在维护,有技术咨询和毕设或者商业可私信我。我基本每天都会看。

这篇文章的内容适用于安卓常用的抽奖效果,参照网络上九宫格抽奖特效进行了修改。

效果图:

实际效果:

点击盲盒领取,奖品上增加一个蒙层,开始转动,当倒计时结束(自己设定时长),抽奖成功,蒙层停到你指定的坐标下。

使用步骤:

1.自定义控件:

/**
 * ================================================
 * <p>
 * 作    者:Vip 版    本:V 1.0.0
 * 创建日期:2018/6/29
 * 描    述:盲盒抽奖
 * 修订历史:
 * ================================================
 */
public class NineLuckPan extends View {
    private Paint mPaint;
    private ArrayList<RectF> mRects;//存储矩形的集合
    private float mStrokWidth = 5;//矩形的描边宽度
    private int[] mItemColor = {Color.GREEN, Color.YELLOW};//矩形的颜色
    private int mRectSize;//矩形的宽和高(矩形为正方形)
    private boolean mClickStartFlag = false;//是否点击中间矩形的标记
    private int mRepeatCount = 3;//转的圈数
    private int mLuckNum = 3;//最终中奖位置
    private int mPosition = -1;//抽奖块的位置
    private int mStartLuckPosition = 0;//开始抽奖的位置
    private int[] mImgs = {
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon,
            R.drawable.icon};
    private String[] mLuckStr = {"子鼠", "丑牛", "萝卜", "刺猬", "北极虾", "糖葫芦", "钝角", "香肠", "南瓜", "IP地址", "安装", "土狗"};
    private OnLuckPanAnimEndListener onLuckPanAnimEndListener;

    private int mOuterCircleWidth;  // 最外边圆环
    private Paint mOuterCirclePaint;
    private int mOuterCircleBackgroundColor;

    private int mSmallCircleRadius;  // 小圆圈半径
    private Paint mSmallCirclePaint;
    private int mSmallCircleBlueColor;
    private int mSmallCircleYellowColor;

    private Paint mInnerPaint;
    /**
     * 转盘背景底色
     **/
    private int mInnerCircleBackgroundColor;

    private List<Bitmap> bitmaps;
    private List<String> titles;
    private int padding;
    private float left;
    private float top;

    public OnLuckPanAnimEndListener getOnLuckPanAnimEndListener() {
        return onLuckPanAnimEndListener;
    }

    public void setOnLuckPanAnimEndListener(OnLuckPanAnimEndListener onLuckPanAnimEndListener) {
        this.onLuckPanAnimEndListener = onLuckPanAnimEndListener;
    }

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

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

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

    public int getmLuckNum() {
        return mLuckNum;
    }

    public void setmLuckNum(int mLuckNum) {
        this.mLuckNum = mLuckNum;
    }

    public int[] getmImgs() {
        return mImgs;
    }

    public void setmImgs(int[] mImgs) {
        this.mImgs = mImgs;
        invalidate();
    }

    public String[] getmLuckStr() {
        return mLuckStr;
    }

    public void setmLuckStr(String[] mLuckStr) {
        this.mLuckStr = mLuckStr;
        invalidate();
    }

    public List<Bitmap> getBitmaps() {
        return bitmaps;
    }

    public void setBitmaps(List<Bitmap> bitmaps) {
        this.bitmaps = bitmaps;
        invalidate();
    }

    public List<String> getTitles() {
        return titles;
    }

    public void setTitles(List<String> titles) {
        this.titles = titles;
    }

    /**
     * 初始化数据
     */
    private void init(Context context) {

        mOuterCircleWidth = (int) context.getResources().getDimension(R.dimen.dp_10);
        mOuterCircleBackgroundColor = context.getResources().getColor(R.color.load_red);
        mOuterCirclePaint = new Paint();
        mOuterCirclePaint.setColor(mOuterCircleBackgroundColor);
        mOuterCirclePaint.setAntiAlias(true);
        mOuterCirclePaint.setStrokeWidth(mOuterCircleWidth);
        mOuterCirclePaint.setStyle(Paint.Style.FILL);

        mSmallCircleRadius = (int) context.getResources().getDimension(R.dimen.dp_10);
        mSmallCircleBlueColor = mSmallCircleBlueColor != 0 ? mSmallCircleBlueColor : context.getResources().getColor(R.color.load_blue);
        mSmallCircleYellowColor = mSmallCircleYellowColor != 0 ? mSmallCircleYellowColor : context.getResources().getColor(R.color.load_yellow);
        mSmallCirclePaint = new Paint();
        mSmallCirclePaint.setColor(mSmallCircleBlueColor);
        mSmallCirclePaint.setAntiAlias(true);

        mInnerCircleBackgroundColor = context.getResources().getColor(R.color.cs_b61320);
        mInnerPaint = new Paint();
        mInnerPaint.setAntiAlias(true);
        mInnerPaint.setColor(mInnerCircleBackgroundColor);
        mInnerPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(mStrokWidth);

        mRects = new ArrayList<>();

        padding = dp2px(getContext(), 10);
    }

    /**
     * 外层带圆角矩形圆环
     */
    private void drawOuterRoundCircle(Canvas canvas) {
        canvas.save();
        canvas.clipRect(
                mOuterCircleWidth + getPaddingLeft(),
                mOuterCircleWidth + getPaddingTop(),
                getWidth() - mOuterCircleWidth - getPaddingRight(),
                getWidth() - mOuterCircleWidth - getPaddingBottom(),
                Region.Op.DIFFERENCE);

        canvas.drawRoundRect(
                getPaddingLeft(),
                getPaddingTop(),
                getWidth() - getPaddingRight(),
                getWidth() - getPaddingBottom(),
                18, 18, mOuterCirclePaint);
        canvas.restore();
    }

    private void drawOuterDecorateSmallCircle(Canvas canvas) {
        int result = 0;

        // top
        int x = 0, y = 0;
        int sideSize = getWidth() - mOuterCircleWidth * 2 - getPaddingLeft() - getPaddingRight(); // 除去最外边圆环后的边长
        for (int i = 0; i < 10; i++) {
            mSmallCirclePaint.setColor(i % 2 == result ? mSmallCircleYellowColor : mSmallCircleBlueColor);
            x = mOuterCircleWidth + (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i + mSmallCircleRadius * 2 * i + getPaddingLeft();
            y = (mOuterCircleWidth - mSmallCircleRadius * 2) / 2 + mSmallCircleRadius + getPaddingTop();
            canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);
        }

        // bottom
        for (int i = 0; i < 10; i++) {
            mSmallCirclePaint.setColor(i % 2 == result ? mSmallCircleYellowColor : mSmallCircleBlueColor);
            x = mOuterCircleWidth + (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i + mSmallCircleRadius * 2 * i + getPaddingLeft();
            y = getWidth() - mOuterCircleWidth + (mOuterCircleWidth - mSmallCircleRadius * 2) / 2 + mSmallCircleRadius - getPaddingBottom();
            canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);
        }

        // left
        for (int i = 0; i < 9; i++) {
            mSmallCirclePaint.setColor(i % 2 == (result == 0 ? 1 : 0) ? mSmallCircleYellowColor : mSmallCircleBlueColor);
            x = mOuterCircleWidth / 2 + getPaddingLeft();
            y = mOuterCircleWidth * 2 + (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i + mSmallCircleRadius * 2 * i + getPaddingTop();
            canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);
        }

        // right
        for (int i = 0; i < 9; i++) {
            mSmallCirclePaint.setColor(i % 2 == result ? mSmallCircleYellowColor : mSmallCircleBlueColor);
            x = getWidth() - mOuterCircleWidth / 2 - getPaddingRight();
            y = mOuterCircleWidth * 2 + (sideSize - mSmallCircleRadius * 2 * 9) / 9 * i + mSmallCircleRadius * 2 * i + getPaddingTop();
            canvas.drawCircle(x, y, mSmallCircleRadius, mSmallCirclePaint);
        }
    }

    private void drawInnerBackground(Canvas canvas) {
        canvas.drawRect(mOuterCircleWidth + getPaddingLeft(), mOuterCircleWidth + getPaddingTop(),
                getWidth() - mOuterCircleWidth - getPaddingRight(),
                getWidth() - mOuterCircleWidth - getPaddingBottom(), mInnerPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mRectSize = (Math.min(w, h) - mOuterCircleWidth * 2 - padding * 5) / 4;//获取矩形的宽和高
        mRects.clear();//当控件大小改变的时候清空数据
        initRect();//重新加载矩形数据
    }

    /**
     * 加载矩形数据
     */
    private void initRect() {


        //加载前三个矩形

        int itemWidth = getWidth() - mOuterCircleWidth * 2;

        //加载第1个
        mRects.add(new RectF(0 + mOuterCircleWidth + padding, mOuterCircleWidth + padding, mRectSize + mOuterCircleWidth + padding, mRectSize + mOuterCircleWidth + padding));
        //加载第2个
        mRects.add(new RectF(mRectSize + mOuterCircleWidth + padding * 2, mOuterCircleWidth + padding, mRectSize * 2 + mOuterCircleWidth + padding * 2, mRectSize + mOuterCircleWidth + padding));
        //加载第3个
        mRects.add(new RectF(mRectSize * 2 + mOuterCircleWidth + padding * 3, mOuterCircleWidth + padding, mRectSize * 3 + mOuterCircleWidth + padding * 3, mRectSize + mOuterCircleWidth + padding));
        //加载第4个
        mRects.add(new RectF(mRectSize * 3 + mOuterCircleWidth + padding * 4, mOuterCircleWidth + padding, mRectSize * 4 + mOuterCircleWidth + padding * 4, mRectSize + mOuterCircleWidth + padding));
        //加载第5个
        mRects.add(new RectF(mRectSize * 3 + mOuterCircleWidth + padding * 4, mRectSize + mOuterCircleWidth + padding * 2, mRectSize * 4 + mOuterCircleWidth + padding * 4, mRectSize * 2 + mOuterCircleWidth + padding * 2));
        //加载第6个
        mRects.add(new RectF(mRectSize * 3 + mOuterCircleWidth + padding * 4, mRectSize * 2 + mOuterCircleWidth + padding * 3, mRectSize * 4 + mOuterCircleWidth + padding * 4, mRectSize * 3 + mOuterCircleWidth + padding * 3));
        //加载第7个
        mRects.add(new RectF(mRectSize * 3 + mOuterCircleWidth + padding * 4, mRectSize * 3 + mOuterCircleWidth + padding * 4, mRectSize * 4 + mOuterCircleWidth + padding * 4, mRectSize * 4 + mOuterCircleWidth + padding * 4));
        //加载第8个
        mRects.add(new RectF(mRectSize * 2 + mOuterCircleWidth + padding * 3, mRectSize * 3 + mOuterCircleWidth + padding * 4, mRectSize * 3 + mOuterCircleWidth + padding * 3, mRectSize * 4 + mOuterCircleWidth + padding * 4));
        //加载第9个
        mRects.add(new RectF(mRectSize + mOuterCircleWidth + padding * 2, mRectSize * 3 + mOuterCircleWidth + padding * 4, mRectSize * 2 + mOuterCircleWidth + padding * 2, mRectSize * 4 + mOuterCircleWidth + padding * 4));
        //加载第10个
        mRects.add(new RectF(0 + mOuterCircleWidth + padding, mRectSize * 3 + mOuterCircleWidth + padding * 4, mRectSize + mOuterCircleWidth + padding, mRectSize * 4 + mOuterCircleWidth + padding * 4));
        //加载第11个
        mRects.add(new RectF(0 + mOuterCircleWidth + padding, mRectSize * 2 + mOuterCircleWidth + padding * 3, mRectSize + mOuterCircleWidth + padding, mRectSize * 3 + mOuterCircleWidth + padding * 3));
        //加载第12个
        mRects.add(new RectF(0 + mOuterCircleWidth + padding, mRectSize + mOuterCircleWidth + padding * 2, mRectSize + mOuterCircleWidth + padding, mRectSize * 2 + mOuterCircleWidth + padding * 2));

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //下列三个方法去掉,内容为外框,不符合UI设计,不用调用。
//        drawOuterRoundCircle(canvas);
//        drawOuterDecorateSmallCircle(canvas);
//        drawInnerBackground(canvas);
        drawRects(canvas);
        drawImages(canvas);
    }

    /**
     * 画图片
     *
     * @param canvas
     */
    private void drawImages(Canvas canvas) {
        for (int x = 0; x < mRects.size(); x++) {
            RectF rectF = mRects.get(x);
            float left = rectF.centerX() - mRectSize / 4;
            float top = rectF.centerY() - mRectSize / 4;
            if (bitmaps != null && bitmaps.size() > 0) {
                canvas.drawBitmap(Bitmap.createScaledBitmap(bitmaps.get(x), mRectSize / 2, mRectSize / 2, false), left, top - mRectSize / 8, null);

            }
            if (titles != null && titles.size() > 0) {
                mInnerPaint.setTextSize(getContext().getResources().getDimension(R.dimen.ds_9sp));
                //文字加粗
                mInnerPaint.setStrokeWidth(1);
                String title = titles.get(x);
                if (title.length() > 5) {
                    title = title.substring(0, 5);
                    title = title + "...";
                }
                canvas.drawText(title, left - mRectSize/30 , top + mRectSize * 3 / 4 - 20, mInnerPaint);
            }
        }
    }

    private int getTextWidth(Paint paint, String text) {
        int iRet = 0;
        if (text != null && text.length() > 0) {
            int len = text.length();
            float[] widths = new float[len];
            paint.getTextWidths(text, widths);
            for (int j = 0; j < len; j++) {
                iRet += (int) Math.ceil(widths[j]);
            }
        }
        return iRet;
    }

    /**
     * 画矩形
     *
     * @param canvas
     */
    private void drawRects(Canvas canvas) {
        for (int x = 0; x < mRects.size(); x++) {
            RectF rectF = mRects.get(x);

            mPaint.setColor(getContext().getResources().getColor(R.color.cs_ffe9c6));
            if (mPosition == x) {
                //动画的转动框
                mPaint.setColor(getContext().getResources().getColor(R.color.cs_f8de9b));
            }
            canvas.drawRoundRect(rectF, 10, 10, mPaint);
            if (mPosition == x) {
                //转动框底色
                mPaint.setColor(getContext().getResources().getColor(R.color.load_purple));
                RectF rectF1 = new RectF();
                rectF1.left = rectF.left + 10;
                rectF1.top = rectF.top + 10;
                rectF1.right = rectF.right - 10;
                rectF1.bottom = rectF.bottom - 10;
                canvas.drawRect(rectF1, mPaint);
            }
        }
    }

    public void setPosition(int position) {
        mPosition = position;
        invalidate();
    }
    ValueAnimator valueAnimator = ValueAnimator.ofInt(mStartLuckPosition, mRepeatCount * 12 + mLuckNum).setDuration(5000);
    /**
     * 开始动画
     */
    public void startAnim() {


        if (!mClickStartFlag) {
            mClickStartFlag = true;

            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int position = (int) animation.getAnimatedValue();
                    setPosition(position % 12);
                }
            });
            valueAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mClickStartFlag = false;
                    mStartLuckPosition = mLuckNum;
                    if (onLuckPanAnimEndListener != null) {
                        onLuckPanAnimEndListener.onAnimEnd(mPosition, mLuckStr[mPosition]);
                    }
                }
            });
            valueAnimator.start();
        }

    }
    /**结束动画**/

    public void endAnim(int mEndPosition){
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mClickStartFlag = false;
                mStartLuckPosition = mLuckNum;
                if (onLuckPanAnimEndListener != null) {
                    onLuckPanAnimEndListener.onAnimEnd(mEndPosition, mLuckStr[mEndPosition]);
                }
            }
        });
    }

    public interface OnLuckPanAnimEndListener {
        void onAnimEnd(int position, String msg);
    }

    public int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


}

2.对应布局:

              <!--十二宫格-->
                    <com.android.lingtu.view.NineLuckPan
                        android:id="@+id/luck_view"
                        android:layout_width="320dp"
                        android:layout_height="320dp"
                        android:layout_centerInParent="true"
                        android:layout_centerHorizontal="true" />

3.Java代码调用:

1.在对应Activity内进行FindViewById
    @BindView(R.id.luck_view)
    NineLuckPan luckView;

2.获取奖品数据源,进行赋值,这里模拟是从服务器获取的数据
    
   if(StringUtils.stringThreeNotEmpty(response.body())){
        BoxLIstBean bean = JSON.parseObject(response.body(), BoxLIstBean.class);
        if (NumberConstant.TWO_HUNDRED.equals(StringUtils.NullToStr(bean.getCode()))) {
            if (bean.getRows() != null && bean.getRows().size() > 0) {
                //盲盒奖品
                new Thread() {
                    public void run() {
                        List<Bitmap> bitmaps = new ArrayList<>();
                        List<String> list = new ArrayList<>();
                        try {
                            for (int i = 0; i < bean.getRows().get(0).getGoodsList().size(); i++) {
                                happyList.clear();
                                happyList.addAll(bean.getRows().get(0).getGoodsList());
                                Bitmap myBitmap = Glide.with(mContext).asBitmap().load(RequestApi.ROOT_URL + bean.getRows().get(0).getGoodsList().get(i).getImage()).submit(100, 100).get();
                                Bitmap bitmap = Bitmap.createBitmap(myBitmap, 0, 0, myBitmap.getWidth(), myBitmap.getHeight());
                                bitmaps.add(bitmap);
                                list.add(bean.getRows().get(0).getGoodsList().get(i).getName());
                            }
                            luckView.setTitles(list);
                            luckView.setBitmaps(bitmaps);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                }.start();


            }
        } else {
            Tt.showShort(mContext, StringUtils.NullToStr(bean.getMsg()));
        }
    }
3.获取抽奖结果,然后开启转盘动画,进行延迟操作显示中奖记录,并重置。

   if (StringUtils.stringThreeNotEmpty(response.body())) {
                            BoxRandomBean bean = JSON.parseObject(response.body(), BoxRandomBean.class);
                            if (NumberConstant.TWO_HUNDRED.equals(StringUtils.NullToStr(bean.getCode()))) {
                                luckView.startAnim();
                                if (bean.getData() != null) {
                                    new Handler().postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            if (StringUtils.stringThreeNotEmpty(bean.getData().getGoodsIds())) {
                                                // 抽中
                                                for (int i = 0; i < happyList.size(); i++) {
                                                    if ((happyList.get(i).getId() + "").equals(bean.getData().getGoodsIds())) {
                                                        showBoxYes(happyList.get(i).getName());
                                                        luckView.endAnim(i);
                                                    }
                                                }
                                              }
                                            } else {
                                                //未抽中
                                                showBoxNo();
                                            }
                                        }
                                    }, 6000);
                                } else {
                                    //未抽中
                                    new Handler().postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            //回零
                                            luckView.setPosition(0);
                                            showBoxNo();

                                        }
                                    }, 8000);

                                }


                            } else {
                                //没积分或者请求失败
                                Tt.showShort(mContext, StringUtils.NullToStr(bean.getMsg()));
                            }

                        }
  

总结:

通过以上方式,即可实现。

应广大粉丝需求,附上demo链接,只要5积分!

https://download.csdn.net/download/qq_35874340/87675862?spm=1001.2014.3001.5503

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

土狗的想法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值