文章目录

  • 前言
  • 思考
  • 代码
  • 总结

前言

无论是线上推广,还是线下营销,转盘游戏都是非常吸引人的一项活动,就像电视剧《赘婿》中的“拼刀刀”,达到的是万人空巷的影响力。其实,这是一种赌徒心理。每个人都希望不劳而获,这是赌徒心理的成长的肥沃土壤,不幸的是,千百万年的成长中,人已经形成了避难趋易的本性。转盘是一种傻瓜式的操作,只需要手指点一下,不过几秒钟,就可以收到反馈。而想要立即得到结果,害怕未知依然是每个人的本质。所以,转盘游戏有其滋生的土壤。

思考

怎么样实现一个转盘那?首先:转盘是一个圆,然后把圆等分成几份,每一份都是一个扇形区域,在扇形区域中画出我们先展示的内容,接着,中间可能有装饰(图片),最后,按照层级一层层画。
想必大家都对自定义View的过程了熟于心,这里就不过多介绍了。下面我们进入代码。

代码

  1. 自定义转盘
    这里没有给出全部的代码,而是抽取了一些关键步骤,文章的最后有给出全部代码。
class LuckySpinView : View {constructor(context: Context?) : super(context) {initPaint()}// 初始化画笔。自定义View前先想好需要哪些画笔,对实现View有神奇效果private fun initPaint() {mArcPaint = Paint()mArcPaint.isAntiAlias = truemArcPaint.isDither = truemTextPaint = TextPaint()mTextPaint.style = Paint.Style.FILLmTextPaint.isAntiAlias = truemTextPaint.isDither = truemTextPaint.color = mTextColormTextPaint.textSize = mTextSizemTextPaint.typeface = ResourcesCompat.getFont(context, R.font.impact)mTextStrokePaint = TextPaint(mTextPaint)mTextStrokePaint.style = Paint.Style.STROKEmTextStrokePaint.strokeWidth = TEXT_STROKE_WIDTHmBackgroundPaint = Paint()mBackgroundPaint.isAntiAlias = truemBackgroundPaint.isDither = true}// 测量阶段。自定义View必要的阶段,用来规范我们View的展示大小override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)val width = measuredWidth.coerceAtMost(measuredHeight)mPadding = paddingLeftif (mOutRadius == 0) mOutRadius = width / 2if (mInnerRadius == 0) mInnerRadius = width / 2setMeasuredDimension(mOutRadius * 2, mOutRadius * 2)}// 绘画阶段。自定义View必要的阶段,画布承载我们想要的效果,画笔将我们的想法变成现实/*** @param canvas*/@SuppressLint("DrawAllocation")override fun onDraw(canvas: Canvas) {super.onDraw(canvas)drawArc(canvas) // 画扇形区域drawCenterImg(canvas) //画中间的区域drawOutBoundImg(canvas) // 画外围的装饰}@SuppressLint("UseCompatLoadingForDrawables")private fun drawCenterImg(canvas: Canvas) {if (mCenterImageId == 0) returnif (mCenterBitmap == null) {val drawable = resources.getDrawable(mCenterImageId, null)val bitmap = Utils.drawableToBitmap(drawable)mCenterBitmap = Bitmap.createScaledBitmap(bitmap,drawable!!.intrinsicWidth,drawable.intrinsicHeight,false)}val bitmap = mCenterBitmap!!canvas.drawBitmap(bitmap, mCenterPoint.x - bitmap.width / 2.toFloat(),mCenterPoint.y - bitmap.height / 2.toFloat(), null)}@SuppressLint("UseCompatLoadingForDrawables")private fun drawOutBoundImg(canvas: Canvas) {val drawable = resources.getDrawable(mBackgroundImgId, null)drawable.bounds = Rect(mOutRange.left.toInt() ,mOutRange.top.toInt() ,mOutRange.right.toInt() ,mOutRange.bottom.toInt())drawable.draw(canvas)}private fun drawArc(canvas: Canvas) {var tmpAngle = mStartAngleval sweepAngle = 360f / mRewardList.sizefor (i in mRewardList.indices) {fillArc(canvas, tmpAngle, sweepAngle, i)drawArcBorder(canvas, tmpAngle, sweepAngle)drawItemContentWithoutIcon(i, canvas, tmpAngle, sweepAngle)tmpAngle += sweepAngle}}private fun rotateTo(index: Int) {HandlerUtils.runOnUiThread {val rand = Random()rotateTo(index, rand.nextInt() and 1, true)}}// 执行旋转fun rotateTo(index: Int, rotation: Int, startShow: Boolean) {if (isRunning) {return}val rotationAssess = if (rotation <= 0) 1 else -1var roundOfNumber = mRoundOfNumberval accDuration = 1500Lvar decDuration = 1500Lvar interpolator: TimeInterpolator// 从上一次转盘最终的位置处旋转if (getRotation() != 0.0f) {setRotation(getRotation() % 360f)interpolator = AccelerateInterpolator()animate().setInterpolator(interpolator).setDuration(accDuration).setListener(object : Animator.AnimatorListener {override fun onAnimationStart(animation: Animator) {isRunning = true}override fun onAnimationEnd(animation: Animator) {isRunning = falsesetRotation(0f) // 加速到角度为0的水平轴, 接着再减速到目标角度rotateTo(index, rotation, false)}override fun onAnimationCancel(animation: Animator) {}override fun onAnimationRepeat(animation: Animator) {}}).rotation(360f * roundOfNumber * rotationAssess).start()return}interpolator = DecelerateInterpolator()// 进入转盘后的第一次玩转盘, 先加速再减速if (startShow) {roundOfNumber = roundOfNumber shl 1decDuration = accDuration shl 1interpolator = AccelerateDecelerateInterpolator()}val targetAngle =360f * roundOfNumber * rotationAssess + 270f - getAngleOfIndexTarget(index) - 360f / mRewardList.size / 2animate().setInterpolator(interpolator).setDuration(decDuration + 500L).setListener(object : Animator.AnimatorListener {override fun onAnimationStart(animation: Animator) {isRunning = true}override fun onAnimationEnd(animation: Animator) {isRunning = falsesetRotation(getRotation() % 360f)if (mRotateListener != null) {mRotateListener!!.rotateDone(index)}}override fun onAnimationCancel(animation: Animator) {}override fun onAnimationRepeat(animation: Animator) {}}).rotation(targetAngle).start()}fun setTargetIndex(index: Int) {targetIndex = index}// 开始旋转fun startLuckyWheelWithTargetIndex(index: Int) {this.rotateTo(index)}fun startLuckyWheelWithRandomTarget() {val r = Random()this.rotateTo(r.nextInt(this.rewardListSize - 1))}// 取消旋转fun cancelRotate() {animate().cancel()}
}

这里有全部的代码,欢迎查看,LuckySpin

总结

在实现转盘游戏的过程中,总会碰到一些拦路虎。如果避其锋芒,不敢与之对抗,那么此消彼长,它会一步步成长,直到你觉得不能再逃避想要面对它时,它已经是个庞然大物,此时便会有心无力。碰到困难,最简单也是最有效的方法,直接面对它,将它分解成你能解决的许多小块,这就是分治算法的核心:分而治之。

Android--大转盘相关推荐

  1. Android 大转盘 好用的示例

    GitHub - MZCretin/WheelSurfDemo: 自定义Android原生转盘抽奖demohttps://github.com/MZCretin/WheelSurfDemo

  2. Android之九宫格抽奖及大转盘抽奖

    一:先来张效果图 二:实现步骤: -------.九宫格抽奖是从后台服务器获取的数据,图片文字以及抽奖选中位置都是后台控制 一:九宫格抽奖 1九宫格抽奖工具类(里面包含网络请求,不需要的可去掉) pa ...

  3. android抽奖大转盘

    前段时间看见朋友做了一个大转盘,效果很好,耐不住寂寞的我也操刀上阵,亲自实现一下这个抽奖,然后带个大奖回家给充气的gf..如果你的工资不是很高,或者最近有点缺钱花,那么你就更应该好好来看看这个大转盘, ...

  4. 基于 SurfaceView 详解 android 幸运大转盘,附带实例app

    基于 SurfaceView 详解 android 幸运大转盘,附带实例app 首先说一下,幸运大转盘,以及SurfaceView是在看了也为大神的博客,才有了比较深刻的理解,当然这里附上这位大神的博 ...

  5. android自定义大转盘,Android 自定义View 抽奖大转盘(1)

    站在别人的肩膀上慢慢前行 只是部分的转盘主要功能的实现,其他的东西可以慢慢填上,这里做一个简单的介绍 镇楼图 S71010-17315559.jpg github链接 https://github.c ...

  6. android自定义抽奖,Android 自定义View 抽奖大转盘(2)

    这是转盘的第二个版本,添加了外围的圆圈 第一个demo在这儿可以找到 镇楼图 S171011-11370203.jpg 项目的本来来源来自于 添加外围的圆圈,主要由两部分组成 1.画小圆.2.圆盘位置 ...

  7. 幸运大转盘抽奖(前端)

    采用Lottery.js插件, 无依赖, 简单易用(复制粘贴就能用) 效果图(可自己写算法定义概率,可自己定义奖项数量和名称) html <!DOCTYPE html> <html ...

  8. 实现可点击的幸运大转盘

    之前的项目有一个幸运大转盘的功能,在网上找了很久,都没有合适的方法. 这是效果图,实现目标:十二星座的图片可点击切换选中效果,根据选择不同的星座,实现不同的 方法.之前网上的都是带有指针的,或者可点击 ...

  9. HTML精美大转盘源码

    首先看下效果图: 1.JSP页面代码 <%@ page language="java" import="java.util.*" pageEncoding ...

  10. 用MaskFilter画抽奖大转盘Demo

    1.前言 MaskFilter类可以为Paint分配边缘效果. 对MaskFilter的扩展可以对一个Paint边缘的alpha通道应用转换. Android包含了下面几种MaskFilter:Blu ...

最新文章

  1. 二叉树的5种遍历方式
  2. JavaScript 页面跳转的几种方式
  3. 运行维护:UPS电源并列运行分析及维护应用
  4. 把SAP云平台上创建的API proxy添加到API product里去
  5. 设计模式是什么鬼(原型)
  6. PHP memcached memcache 扩展安装
  7. vs中能编译通过,但是会有红色下划线提示未定义标示符问题
  8. 在Qt/Embedded 2.3.8中添加MX21Ads键盘处理
  9. WebSocket入门使用教程
  10. python中数字转英文_如何用Python实现阿拉伯数字转换英文数字 python3 将中文句子中汉字数字转阿拉伯数字...
  11. (基础)单个字符的大小写转换
  12. 人脸识别算法一:特征脸方法(Eigenface)
  13. 手把手教你给女朋友编写一个公众号定时推送(java版本)
  14. c语言调用函数的方法案例,C语言经典例题100例——C语言练习实例34解答(函数调用)...
  15. CSS“超出显示省略号,后面还能显示其他内容”的解决方案
  16. 电话销售潜在客户从哪里找 电销行业还值得深入研究吗?
  17. 组织技术部的需求评审会
  18. 超级详细的晶圆厂前世今生,半导体研究史诗级长文
  19. superset 1.3 地图 汉字 展示,省市编码 ISO3166
  20. 闲鱼上怎么引流学生粉?闲鱼如何引流客源?闲鱼的引流技巧

热门文章

  1. 进程间通信——剪切板
  2. (10)QJ_黑电平AWBCCM校正步骤raw数据抓取
  3. java辐射汉化_如何让所有路径(顶点)从Java中的顶点辐射出来?
  4. 经络腧穴学-习题集-附答案
  5. MySQL 创建表 CREATE TABLE 语法
  6. watch、computed、methods的区别
  7. 大数据离线批处理化解决方案--离线批处理
  8. Python 竟能绘制出如此酷炫的三维图
  9. Linux压缩包管理
  10. [洛谷]P2255 [USACO14JAN]记录奥林比克 (#贪心)