自定義控制元件 實現 抽獎轉盤功能
阿新 • • 發佈:2018-12-19
先來看看佈局頁面 so easy 簡簡單單的佈局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.Lucky.luckyview.Luckypan android:id="@+id/id_luckyPan" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="30dp" android:layout_centerInParent="true" /> <ImageView android:id="@+id/id_start_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/start"/> </RelativeLayout>
接下來看一下 MainActivity 主要設定了 控制轉盤轉動與停止的監聽
package com.Lucky.luckyview; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { private Luckypan mLuckypan; private ImageView mStartBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mStartBtn = findViewById(R.id.id_start_btn); mLuckypan = findViewById(R.id.id_luckyPan); mStartBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!mLuckypan.isStart()){ mLuckypan.luckyStart(); mStartBtn.setImageResource(R.drawable.stop); }else { if (!mLuckypan.isShouldEnd()){ mLuckypan.luckyEnd(); mStartBtn.setImageResource(R.drawable.start); } } } }); } }
接下來就是重頭戲了 抽獎轉盤的 一些功能實現 文字 圖片 …
package com.Lucky.luckyview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; 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; /** * date:2018/11/3 * author:李壯(MR.da) * function: */ public class Luckypan extends SurfaceView implements SurfaceHolder.Callback,Runnable { private SurfaceHolder mHolder; private Canvas mCanvas; //用於繪製的執行緒 private Thread t; //用於控制執行緒的開關 private boolean isRunning; //盤塊的文字 private String[] mStrs = new String[]{"單反相機","IPAD","恭喜發財","IPONE","服裝一套","恭喜發財"}; //盤塊的圖片 private int[] mImgs = new int[]{R.drawable.danfan,R.drawable.ipad,R.drawable.f015,R.drawable.iphone,R.drawable.meizi,R.drawable.f015}; //與圖片對應的bitmap陣列 private Bitmap[] mImgsBitmap; //盤塊的顏色 private int[] mColor = new int[]{0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01}; private int mItemCount = 6; //整個盤塊的範圍 private RectF mRange = new RectF(); //整個盤塊的直徑 private int mRadius; //繪製盤塊的畫筆 private Paint mArcPaint; //繪製文字的畫筆 private Paint mTextPaint; //滾動的速度 private double mSpeed; //保證執行緒間的可見性 private volatile int mStartAngle = 0; //判斷是否點選了停止按鈕 private boolean isShouldEnd; //轉盤的中心位置 private int mCenter; //這裡我們的padding直接以paddingleft為準 private int mPadding; //背景圖 private Bitmap mBgBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.bg2); private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,20,getResources().getDisplayMetrics()); public Luckypan(Context context) { this(context,null); } public Luckypan(Context context, AttributeSet attrs) { this(context, attrs,0); } public Luckypan(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } private void initView() { mHolder = getHolder(); mHolder.addCallback(this); //可獲得焦點 setFocusable(true); setFocusableInTouchMode(true); //設定常量 setKeepScreenOn(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = Math.min(getMeasuredWidth(), getMeasuredHeight()); mPadding = getPaddingLeft(); //直徑 mRadius = width - mPadding *2; //中心點 mCenter = width / 2; setMeasuredDimension(width,width); } @Override public void surfaceCreated(SurfaceHolder holder) { //初始化繪製盤塊的畫筆 mArcPaint = new Paint(); mArcPaint.setAntiAlias(true); mArcPaint.setDither(true); //初始化繪製盤塊的畫筆 mTextPaint = new Paint(); mTextPaint.setColor(Color.WHITE); 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(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { isRunning = false; } @Override public void run() { while (isRunning){ draw(); } } private void draw() { mCanvas = mHolder.lockCanvas(); try { 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]); //繪製背景圖片 drawIcon(tmpAngle,mImgsBitmap[i]); tmpAngle += sweepAngle; } mStartAngle += mSpeed; //如果點選了停止按鈕 if (isShouldEnd){ mSpeed -= 1; } if (mSpeed <= 0){ mSpeed = 0; isShouldEnd = false; } } }finally { if (mCanvas != null){ mHolder.unlockCanvasAndPost(mCanvas); } } } //點選了啟動旋轉 public void luckyStart(){ mSpeed = 50; isShouldEnd = false; } //點選了停止旋轉 public void luckyEnd(){ isShouldEnd = true; } //轉盤是否在旋轉 public boolean isStart() { return mSpeed != 0; } public boolean isShouldEnd() { return isShouldEnd; } //繪製Icon 圖片 private void drawIcon(float tmpAngle, Bitmap bitmap) { //設定圖片的寬度為直徑的1/8 int imgWidth = mRadius / 8; 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 string) { Path path = new Path(); path.addArc(mRange,tmpAngle,sweepAngle); //利用水平偏移量讓文字居中 float textWidth = mTextPaint.measureText(string); int hOffset = (int) (mRadius * Math.PI / mItemCount /2 - textWidth /2); //垂直偏移量 int vOffset = mRadius /2 /6; mCanvas.drawTextOnPath(string,path,hOffset,vOffset,mTextPaint); } //繪製背景 private void drawBg() { mCanvas.drawColor(Color.WHITE); mCanvas.drawBitmap(mBgBitmap,null,new RectF(mPadding/2,mPadding/2,getMeasuredWidth()-mPadding /2 ,getMeasuredHeight() - mPadding /2),null); } }
最終看一下效果圖吧