android 自定義view實現圓盤抽獎的效果
阿新 • • 發佈:2018-12-19
廢話不多說直接上程式碼。
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.os.Handler; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; public class ZhuanpanView extends View implements OnGlobalLayoutListener { private int width; // 轉盤寬度 private int padding; // 轉盤內邊距 private int radius;// 半徑 private RectF rect; // 圓形矩形區域 private Paint paint; // 圖形畫筆 private Paint painttext; // 文字畫筆 private float angle = 0; // 起始旋轉角度 private int count = 8;// 扇形個數 private float shanxingangle; // 扇形角度 private String[] jianzhi = { "謝謝參與", "4999", "200", "50", "500", "9999", "100", "500" }; // 價值 private String[] jianzhimc = { "豆差一點兒", "流量豆", "經驗值", "流量豆", "流量豆", "流量豆", "流量豆", "經驗值" }; // 價值名稱 private float speed = 0; // 每次旋轉角度 private float decrease = 1; private int jg = 50; private Handler handler = new Handler(); public static final int NOMEAL = 0; // 正常狀態 public static final int ZHUANING = 1; // 正在轉 public static final int ENDING = 2; // 正在停止 private int state = NOMEAL; private Bitmap backbitmap=BitmapFactory.decodeResource(getResources(), R.drawable.zhuanpanwaiyuan); private Runnable runnable = new Runnable() { @Override public void run() { ZhuanpanView.this.invalidate(); handler.postDelayed(runnable, jg); } }; public ZhuanpanView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); getViewTreeObserver().addOnGlobalLayoutListener(this); padding = getPaddingLeft(); // 圖形畫筆 paint = new Paint(); paint.setAntiAlias(true); // 抗鋸齒 paint.setStyle(Paint.Style.FILL); //設定繪製的顏色,a代表透明度,r,g,b代表顏色值。 paint.setARGB(255, 14 * 16 + 9, 14 * 16 + 9, 14 * 16 + 9); //設定畫筆寬度 paint.setStrokeWidth(4); // 文字畫筆 painttext = new Paint(); painttext.setAntiAlias(true); // 抗鋸齒 //設定繪製文字的字號大小 painttext.setTextSize(30); //設定畫筆的樣式,為FILL,FILL_OR_STROKE,或STROKE Style.FILL: 實心 STROKE:空心 FILL_OR_STROKE:同時實心與空心 painttext.setStyle(Paint.Style.FILL); painttext.setARGB(255, 15 * 16 + 4, 6 * 16 + 12, 10); shanxingangle = 360.0f / 8; } public ZhuanpanView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ZhuanpanView(Context context) { this(context, null); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //計算最小值 width = Math.min(getMeasuredHeight(), getMeasuredWidth()); // radius = (width - padding * 2) / 2; rect = new RectF(padding, padding, width - padding, width - padding); setMeasuredDimension(width, width); } public void StartZhuan(int index) { state = ZHUANING; // 計算速度 // 每項角度大小 float angle = (float) (360 /count); // 中獎角度範圍(因為指標向上,所以水平第一項旋轉到指標指向,需要旋轉210-270;) float from = 270 - (index + 1) * angle; float to = from + angle; // 停下來時旋轉的距離 float targetFrom = 0* 360 + from; /** * <pre> * (v1 + 0) * (v1+1) / 2 = target ; * v1*v1 + v1 - 2target = 0 ; * v1=-1+(1*1 + 8 *1 * target)/2; * </pre> */ float v1 = (float) (Math.sqrt(1 * 1 + 8 * 1 * targetFrom) - 1) / 2; float targetTo = 0 * 360 + to; float v2 = (float) (Math.sqrt(1 * 1 + 8 * 1 * targetTo) - 1) / 2; speed = (float) (v1 + Math.random() * (v2 - v1)); Log.v("speed",""+speed); //speed = 30; } public void EndZhuan() { state = ENDING; angle=0; } public int getState() { return state; } public boolean isZhan() { return speed != 0; } @Override protected void onDraw(Canvas canvas) { angle += speed; if (angle >= 360) { angle -= 360; } // 點選停止 if (state == ENDING) { speed -= decrease; // 速度的減少量 } if (speed <= 0) { speed = 0; state = NOMEAL; } //繪製背景 paint.setARGB(80, 13 * 16 + 12, 13 * 16 + 12, 13 * 16 + 12); //展示在螢幕上的區域 canvas.drawBitmap(backbitmap, null, new Rect(padding / 2, padding / 2, getMeasuredWidth() - padding / 2, getMeasuredWidth() - padding / 2), null); //canvas.drawCircle(radius + padding, radius + padding, radius, paint); // 繪製扇形 paint.setARGB(255, 13 * 16 + 12, 13 * 16 + 12, 13 * 16 + 12); paint.setStyle(Paint.Style.STROKE); float vOffset = 0; float hOffset = 0; float textwidth = 0; for (int i = 0; i < count; i++) { float startangle = i * shanxingangle + angle; canvas.drawArc(rect, startangle, shanxingangle, true, paint); // 繪製文字 Path path = new Path(); path.addArc(rect, startangle, shanxingangle); // 計算文字 painttext.setTextSize(35); painttext.setStyle(Paint.Style.FILL); painttext.setARGB(255, 15 * 16 + 4, 6 * 16 + 12, 10); textwidth = painttext.measureText(jianzhi[i]); vOffset = radius / 5; hOffset = (float) (radius * Math.PI / count - textwidth / 2); canvas.drawTextOnPath(jianzhi[i], path, hOffset, vOffset, painttext); painttext.setTextSize(30); painttext.setStyle(Paint.Style.FILL); painttext.setARGB(255, 9 * 16 + 12, 9 * 16 + 12, 9 * 16 + 12); textwidth = painttext.measureText(jianzhimc[i]); hOffset = (float) (radius * Math.PI / count - textwidth / 2); canvas.drawTextOnPath(jianzhimc[i], path, hOffset, vOffset + 30, painttext); } } @Override public void onGlobalLayout() { // 如果整個佈局完成啟動handler getViewTreeObserver().removeGlobalOnLayoutListener(this); handler.postDelayed(runnable, jg); } }
Activity中的一些邏輯
import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { // 逗你轉 private Button btn_zhan; private ZhuanpanView zview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); zview = this.findViewById(R.id.zview); btn_zhan = this.findViewById(R.id.btn_zhan); btn_zhan.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_zhan: //判斷是否為正常狀態 if (zview.getState() == ZhuanpanView.NOMEAL) { //開始轉動 zview.StartZhuan(1); //給按鈕換一個背景 btn_zhan.setBackgroundResource(R.drawable.icon_end); } else { //判斷是否為正在轉 if (zview.getState() == ZhuanpanView.ZHUANING) { //停止 zview.EndZhuan(); btn_zhan.setBackgroundResource(R.drawable.icon_bengin); } } break; } } }
佈局程式碼就是一個button加一個背景圖片。