天天看點

實作抽獎輪盤(surfaceView)自定義控件

MainActivity

package com.example.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 LuckPan mLuckPan;
    private ImageView mStartBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLuckPan = findViewById(R.id.id_luckypan);
        mStartBtn = findViewById(R.id.id_start_btn);
        mStartBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (!mLuckPan.isStart()){
                    mLuckPan.lucyStart();
                    mStartBtn.setImageResource(R.drawable.stop);
                }else{
                    if (!mLuckPan.isShouldEnd()){
                        mLuckPan.lucyEnd();
                        mStartBtn.setImageResource(R.drawable.start);
                    }
                }
            }
        });
    }
}

           

Main布局

<?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"
    android:background="#ffffff"
    tools:context=".MainActivity">

    <com.example.luckyview.LuckPan
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="30dp"
        android:layout_centerInParent="true"
        android:id="@+id/id_luckypan"
        />
    <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>
           

SurfaceView(沒用到)

package com.example.luckyview;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * date:2018/11/3
 * author:
 * function:
 */
public class SurfaceViewImpl extends SurfaceView implements SurfaceHolder.Callback,Runnable{
    private SurfaceHolder holder;
    private Canvas mCanvas;
    //線程的控制開關
    private boolean isruning;
    //用于繪制線程
    private Thread t;

    public SurfaceViewImpl(Context context) {
        this(context,null);
    }

    public SurfaceViewImpl(Context context, AttributeSet attrs) {
        super(context, attrs);

        holder = getHolder();
        holder.addCallback(this);
        //設定可以獲得焦點
        setFocusable(true);
        setFocusableInTouchMode(true);
        //設定常量
        setKeepScreenOn(true);

    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {

        isruning = true;
        t = new Thread(this);
        t.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        isruning = false;
    }

    @Override
    public void run() {

        while(isruning){
            Draw();
        }
    }

    private void Draw() {
        try {
            mCanvas = holder.lockCanvas();

            if (mCanvas !=null){

            }
        }catch (Exception e){

        }finally {
            if (mCanvas != null){
                holder.unlockCanvasAndPost(mCanvas);
            }
        }

    }
}

           

自定義的控件(LuckyPan)

package com.example.luckyview;

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;

/**
 * date:2018/11/3
 * author:
 * function:
 */
public class LuckPan extends SurfaceView implements SurfaceHolder.Callback,Runnable{
    private SurfaceHolder holder;
    private Canvas mCanvas;
    //線程的控制開關
    private boolean isruning;
    //用于繪制線程
    private Thread t;

    private String[] mStrs = new String[]{"單反相機","ipad","恭喜發财","IPHONE","服裝一套","恭喜發财"};

    private int[] mImgs = new int[]{R.drawable.danfan,R.drawable.ipad,R.drawable.f015,
            R.drawable.iphone,R.drawable.meizi,R.drawable.f040};
    private int[] mColors = new int[]{0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01};

    private int mItemCount=6;

    private Bitmap[] mImgsBitmap;

    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 取最小值   或者以left為準
    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 LuckPan(Context context) {
        this(context,null);
    }

    public LuckPan(Context context, AttributeSet attrs) {
        super(context, attrs);

        holder = getHolder();
        holder.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 surfaceHolder) {
        //初始化繪制盤塊的畫筆
        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]);
        }

        isruning = true;
        t = new Thread(this);
        t.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        isruning = false;
    }

    @Override
    public void run() {

        while(isruning){
            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 = holder.lockCanvas();

            if (mCanvas !=null){

                drawBg();

                float tmpAngle = mStartAngle;
                float sweepAngle = 360 / mItemCount;

                for (int i=0;i<mItemCount;i++){
                    mArcPaint.setColor(mColors[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;
                }




            }
        }catch (Exception e){

        }finally {
            if (mCanvas != null){
                holder.unlockCanvasAndPost(mCanvas);
            }
        }

    }

    public void lucyStart(){
        mSpeed = 50;
        isShouldEnd = false;
    }
    public void lucyEnd(){
        isShouldEnd = true;
    }
    public boolean isStart(){
        return mSpeed != 0;
    }
    public boolean isShouldEnd(){
        return isShouldEnd;
    }


    //繪制圖檔
    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 str) {

        Path path = new Path();
        path.addArc(mRange,tmpAngle,sweepAngle);

        //水準偏移量讓文字居中

        float textWidth = mTextPaint.measureText(str);
        int hOffest = (int)(mRadius * Math.PI / mItemCount / 2 - textWidth / 2 );

        int vOffest = mRadius/2/6;

        mCanvas.drawTextOnPath(str,path,hOffest,vOffest,mTextPaint);


    }

    private void drawBg() {

        mCanvas.drawColor(0xFFFFFFFF);
        mCanvas.drawBitmap(mBgBitmap,null,new Rect(mPadding/2,
                mPadding/2,getMeasuredWidth()-mPadding/2,
                getMeasuredHeight()-mPadding/2),null);


    }
}

           

繼續閱讀