andriod自定义view实现幸运抽奖盘

编程入门 行业动态 更新时间:2024-10-22 23:08:39

andriod<a href=https://www.elefans.com/category/jswz/34/1771438.html style=自定义view实现幸运抽奖盘"/>

andriod自定义view实现幸运抽奖盘

电商中常见有各种抽奖活动,如旋转幸运抽奖盘,本博客写的就是就是幸运抽奖盘。首先看看效果图。


效果图看起来不是很流程,将就看看就行,真机运行是很流畅的。

下面看看幸运抽奖盘的自定义实现LuckyPan,注释代码中都有,

package com.hai.widget;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.SurfaceHolder;
import android.view.SurfaceView;import com.hai.R;/*** 幸运抽奖盘* Created by 黄海 on 2/2/2016.*/
public class LuckyPan extends SurfaceView implements SurfaceHolder.Callback, Runnable {private SurfaceHolder mHolder;private Canvas mCanvas;//绘制盘块的画笔private Paint mArcPaint;//盘块的奖项private String[] mStrs = new String[]{"单反相机", "IPAD", "恭喜发财", "IPHONE", "服装一套", "恭喜发财"};//奖项的图片private int[] mImgs = new int[]{R.mipmap.danfan, R.mipmap.ipad, R.mipmap.xiaolian, R.mipmap.iphone, R.mipmap.meizi, R.mipmap.f015};//与图片对应的bitmap数组private Bitmap[] mImgsBitmap;private Bitmap mBgBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.bg2);//盘块的颜色private int[] mColor = new int[]{0xFFFFC300, 0xFFF17E01, 0xFFFFC300, 0xFFF17E01, 0xFFFFC300, 0xFFF17E01};private int mItemCount = 6;//绘制文本的画笔private Paint mTextPaint;private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());//用于绘制线程private Thread t;//线程的控制开关private boolean isRunning;//整个盘块的范围private RectF mRange = new RectF();//角度private volatile float mStartAngle = 0;//整个盘块的直径private int mRadius;//转盘的中心位置private int mCenter;//这里我们的padding直接以paddingLeft为准private int mPadding;//滚动的速度private double mSpeed = 0;//是否点击了停止按钮private boolean isShouldEnd;public LuckyPan(Context context) {super(context, null);}public LuckyPan(Context context, AttributeSet attrs) {super(context, attrs);mHolder = getHolder();mHolder.addCallback(this);//可获得焦点setFocusable(true);setFocusableInTouchMode(true);setKeepScreenOn(true);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = Math.min(getMeasuredWidth(), getMeasuredHeight());mPadding = getPaddingLeft();mCenter = width / 2;mRadius = width - mPadding * 2;setMeasuredDimension(width, width);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {//初始化绘制盘块的画笔mArcPaint = new Paint();mArcPaint.setAntiAlias(true);mArcPaint.setDither(true);//初始化绘制文字的画笔mTextPaint = new Paint();mTextPaint.setColor(0xffffffff);mTextPaint.setTextSize(mTextSize);mRange = new RectF(mPadding, mPadding, mPadding + mRadius, mPadding + mRadius);mImgsBitmap = new Bitmap[mItemCount];for (int i = 0; i < mItemCount; i++) {mImgsBitmap[i] = BitmapFactory.decodeResource(getResources(), mImgs[i]);}isRunning = true;t = new Thread(this);t.start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {isRunning = false;}@Overridepublic void run() {while (isRunning) {long start = System.currentTimeMillis();draw();long end = System.currentTimeMillis();if (end - start < 50) {try {Thread.sleep(50 - (end - start));} catch (InterruptedException e) {e.printStackTrace();}}}}private void draw() {try {mCanvas = mHolder.lockCanvas();if (mCanvas != null) {//绘制背景drawBg();float tmpAngle = mStartAngle;float sweepAngle = 360 / mItemCount;for (int i = 0; i < mItemCount; i++) {mArcPaint.setColor(mColor[i]);//绘制盘块mCanvas.drawArc(mRange, tmpAngle, sweepAngle, true, mArcPaint);//绘制文本drawText(tmpAngle, sweepAngle, mStrs[i]);//绘制icondrawIcon(tmpAngle, mImgsBitmap[i]);tmpAngle += sweepAngle;}mStartAngle += mSpeed;//如果点击了停止按钮if (isShouldEnd) {mSpeed -= 1;}if (mSpeed <= 0) {mSpeed = 0;isShouldEnd = false;}}} catch (Exception e) {} finally {if (mCanvas != null) {mHolder.unlockCanvasAndPost(mCanvas);}}}/*** 转盘旋转开始,同时设置停止位置** @param index*/public void luckyStart(int index) {float angle = 360 / mItemCount;//计算每一向的中奖范围//1->150-210//0->210-270float from = 270 - (index + 1) * 60;float end = from + angle;float targetFrom = 2 * 360 + from;float targetEnd = 2 * 360 + end;/*** <pre>*     v1->0且每次减1*     (v1+0)*(v1+1)/2=targetFrom* </pre>*/float v1 = (float) ((-1 + Math.sqrt(1 + 8 * targetFrom)) / 2);float v2 = (float) ((-1 + Math.sqrt(1 + 8 * targetEnd)) / 2);mSpeed = v1 + Math.random() * (v2 - v1);isShouldEnd = false;}public void luckyEnd() {mStartAngle = 0;isShouldEnd = true;}//转盘是否在旋转public boolean isStart() {return mSpeed != 0;}public boolean isShouldEnd() {return isShouldEnd;}/*** 绘制icon** @param tmpAngle* @param bitmap*/private void drawIcon(float tmpAngle, Bitmap bitmap) {//设置图片的宽度为直径1/8int imgWidth = mRadius / 8;//Math.PI/180,这里的单位为弧度float angle = (float) ((tmpAngle + 360 / mItemCount / 2) * Math.PI / 180);int x = (int) (mCenter + mRadius / 2 / 2 * Math.cos(angle));int y = (int) (mCenter + mRadius / 2 / 2 * Math.sin(angle));//确定那个图片的位置Rect rect = new Rect(x - imgWidth / 2, y - imgWidth / 2, x + imgWidth / 2, y + imgWidth / 2);mCanvas.drawBitmap(bitmap, null, rect, null);}/*** 绘制每个盘块的文本*/private void drawText(float tmpAngle, float sweepAngle, String mStr) {Path path = new Path();path.addArc(mRange, tmpAngle, sweepAngle);//利用水平偏移量让文字居中float textWidth = mTextPaint.measureText(mStr);mTextPaint.setTextAlign(Paint.Align.CENTER);int hOffset = (int) (mRadius * Math.PI / mItemCount / 2 - textWidth / 2);int vOffset = mRadius / 2 / 6;//垂直偏移量mCanvas.drawTextOnPath(mStr, path, 0, vOffset, mTextPaint);}/*** 绘制背景*/private void drawBg() {mCanvas.drawColor(0xffffffff);mCanvas.drawBitmap(mBgBitmap, null, new RectF(mPadding / 2, mPadding / 2, getMeasuredWidth() - mPadding / 2, getMeasuredHeight() - mPadding / 2), null);}
}
activity的代码如下:

package com.hai;import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.hai.widget.LuckyPan;import java.io.File;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;public class MyActivity extends AppCompatActivity {private LuckyPan mLuckyPan;private ImageView mStartBtn;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.luckypan);mLuckyPan = (LuckyPan) findViewById(R.id.id_luckyPan);mStartBtn = (ImageView) findViewById(R.id.id_start_btn);mStartBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (!mLuckyPan.isStart()) {mLuckyPan.luckyStart(0);mStartBtn.setImageResource(R.mipmap.stop);} else {if (!mLuckyPan.isShouldEnd()) {mLuckyPan.luckyEnd();mStartBtn.setImageResource(R.mipmap.start);}}}});}}
布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android=""android:id="@+id/lay"android:layout_width="match_parent"android:layout_height="match_parent"><com.hai.widget.LuckyPanandroid:id="@+id/id_luckyPan"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerInParent="true"android:padding="20dp" /><ImageViewandroid:id="@+id/id_start_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:src="@mipmap/start" /></RelativeLayout>
至此实现幸运抽奖盘的代码已经结束。luckypan的实现难点颇多,如文字的绘制、文字的位置控制和图片的绘制和居中等等。对于在自定义veiw方面不太深入的同学,有很多的学习之处。

最后补充下,本幸运抽奖盘的代码是借鉴zhy大神的代码完成,原作者视频解说地址



luckypan是继承与SurfaceView的,因此这里附上继承SurfaceView的一般重写模版

package com.hai.widget;import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;/*** SurfaceViewTemplate的一般重写模版* Created by 黄海 on 2/2/2016.*/
public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable {private SurfaceHolder mHolder;private Canvas mCanvas;//用于绘制线程private Thread t;//线程的控制开关private boolean isRunning;public SurfaceViewTemplate(Context context) {super(context, null);}public SurfaceViewTemplate(Context context, AttributeSet attrs) {super(context, attrs);mHolder = getHolder();mHolder.addCallback(this);//可获得焦点setFocusable(true);setFocusableInTouchMode(true);setKeepScreenOn(true);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {isRunning = true;t = new Thread(this);t.start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {isRunning = false;}@Overridepublic void run() {while (isRunning) {draw();}}private void draw() {try {mCanvas = mHolder.lockCanvas();if (mCanvas != null) {}} catch (Exception e) {} finally {}}
}





更多推荐

andriod自定义view实现幸运抽奖盘

本文发布于:2024-03-09 23:31:48,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1726437.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自定义   幸运   andriod   view

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!