故事的开始

最近有个需求,支付成功的时候加个抽奖轮盘。类似问卷星提交后的那种东西,翻了一下gayhub,下面给出自己的实现思路.

写在题前

这东西是在github上一个项目是拓展的。但是实现时间和下载项目时间隔了有一阵。所以找不到原链没法挂上,还请见谅。若有知道原链的可以在评论区留一下,我后续加上。

效果图

照例先给最后的实现效果gif图(转gif图的时候应该是抽帧了。实际效果比图片好一点)

实现思路

1,绘制可以切换背景的奖品View
2,将其排列成九宫格
3,通过前后两个view的变换,营造出旋转的感觉
4,状态标识控制加/减速,直至停止,并发送回调

代码

  1. PrizeItemView(奖品View)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/shape_white"><Viewandroid:id="@+id/overlay"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/shape_pink"android:visibility="invisible" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_prize"android:layout_width="60dp"android:layout_height="45dp"android:src="@drawable/png_prize" /><TextViewandroid:id="@+id/tv_prize_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="9dp"android:text="一个奖品"android:textColor="#98520E"android:textSize="22sp" /></LinearLayout>
</FrameLayout>

/*** Created by huahen on 2021/10/25* ClassDescription : 抽奖转盘-奖品子view*/
public class PrizeItemView extends FrameLayout implements PrizeItemApi {private Context mContext;private View mOverlay;private ImageView ivPrize;private TextView tvPrize;public PrizeItemView(@NonNull Context context) {this(context, null);}public PrizeItemView(@NonNull Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public PrizeItemView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);inflate(context, R.layout.item_prize, this);mOverlay = findViewById(R.id.overlay);ivPrize = findViewById(R.id.iv_prize);tvPrize = findViewById(R.id.tv_prize_name);mContext = context;}@Overridepublic void setFocus(boolean isFocused) {if (mOverlay != null) {mOverlay.setVisibility(isFocused ? INVISIBLE : VISIBLE);}}@Overridepublic void setUi(PrizeListBean bean) {ivPrize.setImageResource(bean.getPrize_path());tvPrize.setText(bean.getGoodName());}
}
/*** Created by huahen on 2021/10/25* ClassDescription :*/
public interface PrizeItemApi {void setFocus(boolean isFocused);//修改当前显示状态void setUi(PrizeListBean bean);
}
这里写了一个自定义View,实现两个方法。
1,更新奖品数据修改UI
2,更新奖品选中背景
  1. LuckDrawView(转盘View)
    首先,布局是由8个PrizeItemView拼出来的,哈哈哈哈,中间加个iv,贴了张网上找的开始抽奖
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_marginBottom="4dp"android:layout_weight="1"android:orientation="horizontal"><com.huahen.luckdraw.luckDrawView.PrizeItemViewandroid:id="@+id/item1"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1" /><com.huahen.luckdraw.luckDrawView.PrizeItemViewandroid:id="@+id/item2"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1" /><com.huahen.luckdraw.luckDrawView.PrizeItemViewandroid:id="@+id/item3"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_marginBottom="8dp"android:layout_weight="1"android:orientation="horizontal"><com.huahen.luckdraw.luckDrawView.PrizeItemViewandroid:id="@+id/item8"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1" /><ImageViewandroid:id="@+id/iv_start"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1"android:background="@drawable/luck_draw_btn" /><com.huahen.luckdraw.luckDrawView.PrizeItemViewandroid:id="@+id/item4"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_marginBottom="8dp"android:layout_weight="1"android:orientation="horizontal"><com.huahen.luckdraw.luckDrawView.PrizeItemViewandroid:id="@+id/item7"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1" /><com.huahen.luckdraw.luckDrawView.PrizeItemViewandroid:id="@+id/item6"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1" /><com.huahen.luckdraw.luckDrawView.PrizeItemViewandroid:id="@+id/item5"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="8dp"android:layout_weight="1" /></LinearLayout></LinearLayout>
显示是这样的

来了。全文最主要的代码
public class LuckDrawView extends FrameLayout {private PrizeItemView itemView1, itemView2, itemView3,itemView8, itemView4,itemView7, itemView6, itemView5;private ImageView ivStart;private OnItemListener listener;private PrizeItemApi[] itemViewArr = new PrizeItemApi[8];private int currentIndex = 0;private int currentTotal = 0;private int stayIndex = 0;private boolean isMarqueeRunning = false;//private boolean isGameRunning = false; //是否处于转动private boolean isTryToStop = false;//是否增速/减速private static final int DEFAULT_SPEED = 150; //默认/最慢速度private static final int MIN_SPEED = 50;//最快速度private int currentSpeed = DEFAULT_SPEED;//当前速度Timer timer = new Timer();public LuckDrawView(@NonNull Context context) {this(context, null);}public LuckDrawView(@NonNull Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public LuckDrawView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);inflate(context, R.layout.view_luck_draw_nine, this);initView();}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();startMarquee();}@Overrideprotected void onDetachedFromWindow() {stopMarquee();super.onDetachedFromWindow();}private void initView() {itemView1 = (PrizeItemView) findViewById(R.id.item1);itemView2 = (PrizeItemView) findViewById(R.id.item2);itemView3 = (PrizeItemView) findViewById(R.id.item3);itemView4 = (PrizeItemView) findViewById(R.id.item4);itemView5 = (PrizeItemView) findViewById(R.id.item5);itemView6 = (PrizeItemView) findViewById(R.id.item6);itemView7 = (PrizeItemView) findViewById(R.id.item7);itemView8 = (PrizeItemView) findViewById(R.id.item8);itemViewArr[0] = itemView1;itemViewArr[1] = itemView2;itemViewArr[2] = itemView3;itemViewArr[3] = itemView4;itemViewArr[4] = itemView5;itemViewArr[5] = itemView6;itemViewArr[6] = itemView7;itemViewArr[7] = itemView8;ivStart = findViewById(R.id.iv_start);ivStart.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {listener.onClick();}});}private void stopMarquee() {isMarqueeRunning = false;isGameRunning = false;isTryToStop = false;}private void startMarquee() {isMarqueeRunning = true;new Thread(new Runnable() {@Overridepublic void run() {while (isMarqueeRunning) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}
//                    //灯带
//                    post(new Runnable() {//                        @Override
//                        public void run() {//                            if (bg_1 != null && bg_2 != null) {//                                if (VISIBLE == bg_1.getVisibility()) {//                                    bg_1.setVisibility(GONE);
//                                    bg_2.setVisibility(VISIBLE);
//                                } else {//                                    bg_1.setVisibility(VISIBLE);
//                                    bg_2.setVisibility(GONE);
//                                }
//                            }
//                        }
//                    });}}}).start();}//获取sleep时间,即转盘运动速度,越小即越快。private long getInterruptTime() {currentTotal++;if (isTryToStop) {//减速直至恢复为默认速度currentSpeed += 10;if (currentSpeed > DEFAULT_SPEED) {currentSpeed = DEFAULT_SPEED;}} else {//增速直至最快速度//第一圈不做加速if (currentTotal / itemViewArr.length > 0) {currentSpeed -= 10;}if (currentSpeed < MIN_SPEED) {currentSpeed = MIN_SPEED;}}return currentSpeed;}//返回当前状态public boolean isGameRunning() {return isGameRunning;}//开始抽奖public void startGame(final int stayIndex) {if (isGameRunning) {//运动中return;}isGameRunning = true;isTryToStop = false;currentSpeed = DEFAULT_SPEED;new Thread(new Runnable() {@Overridepublic void run() {while (isGameRunning) {try {Thread.sleep(getInterruptTime());} catch (InterruptedException e) {e.printStackTrace();}post(new Runnable() {@Overridepublic void run() {//防止线程多走了一次if (!isGameRunning) {return;}int preIndex = currentIndex;currentIndex++;if (currentIndex >= itemViewArr.length) {currentIndex = 0;}//根据前后两个itemView的视图变换,实现转动效果itemViewArr[preIndex].setFocus(true);itemViewArr[currentIndex].setFocus(false);//减速&&速度达到最小&&当前view为指定view——停止if (isTryToStop && currentSpeed == DEFAULT_SPEED && stayIndex == currentIndex) {isGameRunning = false;listener.onShop(currentIndex);}}});}}}).start();//五秒后开始减速timer.schedule(new TimerTask() {@Overridepublic void run() {tryToStop();}}, 5000);}//改变加速状态public void tryToStop() {isTryToStop = true;}public void setData(List<PrizeListBean> beans) {if (beans != null) {for (int i = 0; i < beans.size(); i++) {itemViewArr[i].setUi(beans.get(i));}}}public void setOnItemListener(OnItemListener listener) {this.listener = listener;}//放个接口出来做事件监听public interface OnItemListener {void onClick();//点击开始void onShop(int Index);//转动停止}
}

这么清晰的注释,应该不用我怎么解释了吧

最后是调用

        mLuckDrawView = findViewById(R.id.luck_draw);mLuckDrawView.setOnItemListener(new LuckDrawView.OnItemListener() {@Overridepublic void onClick() {//开始抽奖int stayIndex = new Random().nextInt(8);mLuckDrawView.startGame(stayIndex);}@Overridepublic void onShop(int Index) {//动画停止Toast.makeText(MainActivity.this, "这是第" + Index + "个商品", Toast.LENGTH_SHORT).show();}});mLuckDrawView.setData(getLuckDrawData());//设置奖品数据

就这样,一个抽奖转盘就这么实现

可能不尽完美,但也是我提供的一种思路吧。。也欢迎大家一起讨论。

笔者写到这里也不容易,如果这篇文章有帮助到你。冒昧地请求兄弟点个赞呗,如果有不同的见解。也欢迎在评论区一起探讨

Android开发:抽奖转盘的实现相关推荐

  1. Android实现抽奖转盘

    慕客网视频传送门:http://www.imooc.com/learn/444 好久都没去慕客网了,虽然这次学习的是一个比较老的视频了,但是总比不学的好.(末尾附源码) 在学习之前,先来了解一波Sur ...

  2. android自定义抽奖转盘

    项目中有用到抽奖转盘,网上找的demo有些不合设计的要求(不能随意添加转盘中item的个数,不能以上层view滚动等),于是自己尝试写了个自定义的抽奖转盘,方便以在别的项目中更改使用,大致的效果如下图 ...

  3. Android开发笔记(九十九)圆形转盘

    圆形转盘的实现思想 圆形转盘的运用场景常见的有:抽奖转盘.圆形菜单列表.热点客户端环状列表等等.对于圆形转盘的编码实现,主要难点除了手势的触摸控制之外,就在于旋转角度的计算了.下面是旋转角度计算的解决 ...

  4. Android撸一个转盘抽奖

    Android撸一个转盘抽奖 前言 最近在学习的时候想做个积分转盘抽奖的功能,以前项目中使用过,但是是用的H5写的,但是我现在还不是太会写网页,就想算了,用Android写个吧!因为我这边的业务逻辑是 ...

  5. android自定义抽奖,Android自定义view制作抽奖转盘

    本文实例为大家分享了Android自定义view制作抽奖转盘的具体代码,供大家参考,具体内容如下 效果图 TurntableActivity package com.bawei.myapplicati ...

  6. 详解与重构hyman《Android SurfaceView实战 打造抽奖转盘》

    详解与重构hyman<Android SurfaceView实战 打造抽奖转盘> 作者:邵励治 一.概述--关于SurfaceView您不得不知道的二三事 1.SurfaceView是干什 ...

  7. android自定义大转盘,android 代码绘制转盘抽奖的实现

    android 代码绘制转盘抽奖的实现 先上图 第一个是 整体的布局 xmlns:tools="http://schemas.android.com/tools" android: ...

  8. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  9. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

最新文章

  1. Linux中rsync备份数据使用实例
  2. aws python sdk send sns_AWS:boto3订阅SNS时的空SQS队列
  3. select选择框变得可以输入、编辑
  4. Java与汽车_Java NIO:IO与NIO的区别
  5. GDB常用调试命令(一)
  6. iOS通过ASIHTTPRequest提交JSON数据
  7. 高品质深圳市地图shp数据arcgis软件道路地名县区边界水系地铁站点2021年
  8. 《互联网大厂晋升指南》读书笔记-下
  9. rtk定位权限_无人机中的GPS定位、DGPS差分定位、RTK差分定位
  10. jszip打包下载文件
  11. 记一次阿里电话面试(java技术岗)
  12. Oracle Coherence中文教程三:配置
  13. 从0开始使用Git:Win10下使用Git配置并关联Gitbub远程仓库全教程与踩坑分析
  14. Java实现均值、索伯尔、拉普拉斯滤波
  15. 微型计算机联想c325,寓教于乐一体机 联想IdeaCentre B325评测
  16. ZigBee网络数据传递流程_蓝牙、WIFI、Zigbee谁更适合物联网,各有哪些优缺点?...
  17. php 数字上下选取,PHP中常见的数字掐头去尾操作方法
  18. 基于linux的qos编程接口研究与分析,基于Linux的QoS编程接口研究与分析(2)
  19. 新必应(New Bing)国内申请与使用教程
  20. JavaSE基础加强-学习黑马程序员Java基础视频教程(P93开始)

热门文章

  1. 如何写一个简便的富文本编辑器
  2. 机器推理系列文章概览:七大NLP任务最新方法与进展
  3. 我们的征途是星辰大海#
  4. 爱立信实习总结之外企的企业文化
  5. 某mo通过Xposed自动抢红包
  6. 搜狐新闻客户端Android端侧双擎Hybrid AI框架探索
  7. 解决微信小程序新版本覆盖 更新慢的问题
  8. ZIP压缩文件如何设置密码保护?
  9. mysql外网访问设置
  10. 我爱背单词 - 0301