Android 实现九宫格抽奖功能

作者:itfitness 时间:2021-10-02 21:42:27 

目录
  • 效果展示

  • 实现步骤

    • 1.生成抽奖矩形:

    • 2.添加奖品图片:

    • 3.实现抽奖动画:

    • 4.实现动态设置参数:

    • 5.添加抽奖结果回调

效果展示

Android 实现九宫格抽奖功能

实现步骤

1.生成抽奖矩形:

其中每个矩形的宽高相同,长度为整个控件宽度的1/3。

Android 实现九宫格抽奖功能

代码展示


public class NineLuckPan extends View {
private Paint mPaint;
private ArrayList<RectF> mRects;//存储矩形的集合
private float mStrokWidth = 5;//矩形的描边宽度
private int mRectSize;//矩形的宽和高(矩形为正方形)
private int[] mItemColor = {Color.GREEN, Color.YELLOW};//矩形的颜色

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();
}

/**
 * 初始化数据
 */
private void init() {
 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 mPaint.setStyle(Paint.Style.FILL);
 mPaint.setStrokeWidth(mStrokWidth);
 mRects = new ArrayList<>();
}

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

/**
 * 加载矩形数据
 */
private void initRect() {
 //加载前三个矩形
 for (int x = 0; x < 3; x++) {
  float left = x * mRectSize;
  float top = 0;
  float right = (x + 1) * mRectSize;
  float bottom = mRectSize;
  RectF rectF = new RectF(left, top, right, bottom);
  mRects.add(rectF);
 }
 //加载第四个
 mRects.add(new RectF(getWidth() - mRectSize, mRectSize, getWidth(), mRectSize * 2));
 //加载第五~七个
 for (int y = 3; y > 0; y--) {
  float left = getWidth() - (4 - y) * mRectSize;
  float top = mRectSize * 2;
  float right = (y - 3) * mRectSize + getWidth();
  float bottom = mRectSize * 3;
  RectF rectF = new RectF(left, top, right, bottom);
  mRects.add(rectF);
 }
 //加载第八个
 mRects.add(new RectF(0, mRectSize, mRectSize, mRectSize * 2));
 //加载第九个
 mRects.add(new RectF(mRectSize, mRectSize, mRectSize * 2, mRectSize * 2));
}

@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 drawRects(canvas);
}

/**
 * 画矩形
 *
 * @param canvas
 */
private void drawRects(Canvas canvas) {
 for (int x = 0; x < mRects.size(); x++) {
  RectF rectF = mRects.get(x);
  if (x == 8) {//中心的矩形背景为白色
   mPaint.setColor(Color.WHITE);
   canvas.drawRect(rectF, mPaint);
  } else {
   mPaint.setColor(mItemColor[x % 2]);
   canvas.drawRect(rectF, mPaint);
  }
 }
}
}

效果展示

Android 实现九宫格抽奖功能

2.添加奖品图片:

我们在矩形的中心点画出图片,图片的宽高都为矩形宽高的1/2,其中矩形的中心点通过rectF.centerX()和rectF.centerY()获取。

Android 实现九宫格抽奖功能

代码展示(为了方便只展示部分代码)


public class NineLuckPan extends View {
private int[] mImgs = {R.drawable.ic_df, R.drawable.ic_jt, R.drawable.ic_mf, R.drawable.ic_scjx, R.drawable.ic_scng, R.drawable.ic_thl, R.drawable.ic_x, R.drawable.ic_xc, R.drawable.ic_j};

@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(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;
  canvas.drawBitmap(Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), mImgs[x]), mRectSize / 2, mRectSize / 2, false), left, top, null);
 }
}
}

效果展示

Android 实现九宫格抽奖功能

3.实现抽奖动画:

这里我们使用ValueAnimator使数字从0递增到我们的中奖位置比如3,然后改变递增所在的位置的矩形的背景以实现抽奖的效果,另外为了让用户感到逼真我们需要让抽奖色块多转几圈,同时我们需要将下一次的开始位置设为上一次的结束位置。

Android 实现九宫格抽奖功能

代码展示(为了方便只展示部分代码)

NineLuckPan:


public class NineLuckPan extends View {
private int mRepeatCount = 3;//转的圈数
private int mLuckNum = 3;//最终中奖位置
private int mPosition = -1;//抽奖块的位置
private int mStartLuckPosition = 0;//开始抽奖的位置
/**
 * 画矩形
 * @param canvas
 */
private void drawRects(Canvas canvas) {
 for (int x = 0;x<mRects.size();x++){
  RectF rectF = mRects.get(x);
  if(x == 8){
   mPaint.setColor(Color.WHITE);
   canvas.drawRect(rectF, mPaint);
  }else {
   mPaint.setColor(mItemColor[x%2]);
   if(mPosition == x){
    mPaint.setColor(Color.BLUE);
   }
   canvas.drawRect(rectF, mPaint);
  }
 }
}
public void setPosition(int position){
 mPosition = position;
 invalidate();
}
/**
 * 开始动画
 */
public void startAnim(){
 ValueAnimator valueAnimator = ValueAnimator.ofInt(mStartLuckPosition, mRepeatCount * 8 + mLuckNum).setDuration(5000);
 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
  public void onAnimationUpdate(ValueAnimator animation) {
   int position = (int) animation.getAnimatedValue();
   setPosition(position%8);
  }
 });
 valueAnimator.addListener(new AnimatorListenerAdapter() {
  @Override
  public void onAnimationEnd(Animator animation) {
   mStartLuckPosition = mLuckNum;
  }
 });
 valueAnimator.start();
}
}

Activity:


public class MainActivity extends AppCompatActivity {
private NineLuckPan luckpan;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 luckpan = (NineLuckPan) findViewById(R.id.luckpan);
 luckpan.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
   luckpan.startAnim();
  }
 });
}
}

效果展示

Android 实现九宫格抽奖功能

虽然效果实现了但是我们发现好像点哪里都能启动动画,因此我们需要调整一下代码使只有点击中心的矩形才开始动画。


//(为了方便只展示部分代码)
public class NineLuckPan extends View {
private boolean mClickStartFlag = false;//是否点击中间矩形的标记

//这样需要我们将Activity里的启动动画的逻辑删掉
@Override
public boolean onTouchEvent(MotionEvent event) {
 if(event.getAction() == MotionEvent.ACTION_DOWN){
  if(mRects.get(8).contains(event.getX(),event.getY())){
   mClickStartFlag = true;
  }else {
   mClickStartFlag = false;
  }
  return true;
 }
 if(event.getAction() == MotionEvent.ACTION_UP){
  if(mClickStartFlag){
   if(mRects.get(8).contains(event.getX(),event.getY())){
    startAnim();//判断只有手指落下和抬起都在中间的矩形内才开始抽奖
   }
   mClickStartFlag = false;
  }
 }
 return super.onTouchEvent(event);
}
}

4.实现动态设置参数:

效果基本实现了,接下来就需要实现动态设置数据了。

代码展示(这里为了方便只展示部分代码)


public class NineLuckPan extends View {
private int mLuckNum = 3;//最终中奖位置
private int [] mImgs = {R.drawable.ic_df,R.drawable.ic_jt,R.drawable.ic_mf,R.drawable.ic_scjx,R.drawable.ic_scng,R.drawable.ic_thl,R.drawable.ic_x,R.drawable.ic_xc,R.drawable.ic_j};
private String[] mLuckStr = {"豆腐","鸡腿","米饭","卷心菜","南瓜","糖葫芦","大虾","香肠"};//这是抽奖的提示信息

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();;//要注意设置完后要进行重绘
}
}

5.添加抽奖结果回调

这里需要在动画结束的回调里加入我们自定义的回调函数。

代码展示(这里为了方便只展示部分代码)


public class NineLuckPan extends View {
private OnLuckPanAnimEndListener onLuckPanAnimEndListener;

public OnLuckPanAnimEndListener getOnLuckPanAnimEndListener() {
 return onLuckPanAnimEndListener;
}

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

/**
 * 开始动画
 */
private void startAnim(){
 ValueAnimator valueAnimator = ValueAnimator.ofInt(mStartLuckPosition, mRepeatCount * 8 + mLuckNum).setDuration(5000);
 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
  public void onAnimationUpdate(ValueAnimator animation) {
   int position = (int) animation.getAnimatedValue();
   setPosition(position%8);
  }
 });
 valueAnimator.addListener(new AnimatorListenerAdapter() {
  @Override
  public void onAnimationEnd(Animator animation) {
   mStartLuckPosition = mLuckNum;
   //在动画结束的回调函数里加入我们自定义的回调函数
   if(onLuckPanAnimEndListener!=null){
    onLuckPanAnimEndListener.onAnimEnd(mPosition,mLuckStr[mPosition]);
   }
  }
 });
 valueAnimator.start();
}
public interface OnLuckPanAnimEndListener{
 void onAnimEnd(int position,String msg);
}
}

Activity代码:


public class MainActivity extends AppCompatActivity {
private NineLuckPan luckpan;
@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 luckpan = (NineLuckPan) findViewById(R.id.luckpan);
 luckpan.setOnLuckPanAnimEndListener(new NineLuckPan.OnLuckPanAnimEndListener() {
  @Override
  public void onAnimEnd(int position, String msg) {
   Toast.makeText(MainActivity.this, "位置:"+position+"提示信息:"+msg, Toast.LENGTH_SHORT).show();
  }
 });
}
}

效果展示

Android 实现九宫格抽奖功能

源码地址:

https://github.com/myml666/NineLuckPan

到这里就结束啦!

来源:https://mp.weixin.qq.com/s/vVnGH2d0LrOcVnmlU8doEg

标签:Android,九宫格,抽奖
0
投稿

猜你喜欢

  • 用 FieldMask 提高 C# gRpc 的服务性能

    2023-05-03 19:19:05
  • 关于Assert.assertEquals报错的问题及解决

    2023-11-03 04:56:10
  • 横竖屏切换导致页面频繁重启screenLayout解析

    2021-06-14 05:16:22
  • C#中Dictionary泛型集合7种常见的用法

    2021-08-07 04:47:17
  • Android使用view仿支付宝月账单

    2022-03-08 22:54:28
  • 10分钟学会VS NuGet包私有化部署

    2022-04-23 02:28:31
  • C#使用windows服务发送邮件

    2022-05-31 11:54:55
  • 深入了解Java线程池的原理使用及性能优化

    2023-02-17 22:35:31
  • 解决Android 沉浸式状态栏和华为虚拟按键冲突问题

    2023-10-15 14:08:14
  • Java基础教程之接口的继承与抽象类

    2023-11-06 20:47:22
  • C# 多线程学习之基础入门

    2022-11-08 05:38:13
  • Android进阶CoordinatorLayout协调者布局实现吸顶效果

    2022-11-04 21:45:48
  • Android TV 3D卡片无限循环效果

    2022-03-26 04:06:48
  • spring mvc 组合mybatis框架实例详解

    2023-11-28 04:56:04
  • 一文带你了解如何正确使用Java中的字符串常量池

    2022-07-13 01:35:30
  • 移动端WebApp隐藏地址栏的方法

    2022-09-26 20:26:29
  • C#中使用Split方法拆分字符串实例

    2023-04-15 11:14:16
  • Elasticsearch学习之Terms set 查询

    2021-12-01 01:52:19
  • 实战SpringBoot集成JWT实现token验证

    2022-10-07 15:57:49
  • 详解SpringBoot使用RedisTemplate操作Redis的5种数据类型

    2022-12-03 07:35:29
  • asp之家 软件编程 m.aspxhome.com