1. 程式人生 > >自定義控制元件 輪盤 來源於GITHUB(記錄,筆記)

自定義控制元件 輪盤 來源於GITHUB(記錄,筆記)

自定義控制元件:輪盤抽獎

-------邏輯程式碼(輪盤的類)首先要寫一個類繼承SurfaceView 實現Callback和Runnable方法:
//所使用的包
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/*

*/
public class SurfaceViewTemp extends SurfaceView
implements SurfaceHolder.Callback ,Runnable{ SurfaceHolder mHolder; Canvas mCanvas; boolean mIsDrawing; public SurfaceViewTemp(Context context) { this(context,null);//呼叫自身的方法null不影響下一個方法的值 } public SurfaceViewTemp(Context context, AttributeSet attrs) { this(
context, attrs,0);//呼叫自身的方法0不影響下一個方法的值 } public SurfaceViewTemp(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 public void surfaceCreated(SurfaceHolder holder) { mIsDrawing = true; new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void run() { } }
------書寫Lunpan的具體類,主要功能和邏輯都在這個裡邊,要繼承上一個類--SurfaceViewTemp 

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;

public class LuckyPan extends SurfaceViewTemp {

    int mRadius;
    Paint mArcPaint;
    Paint mTextPaint;
    RectF mRange;
    int mSpeed = 0;
    boolean isShouldEnd;

    private float mTextSize = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());

    private String[] mStrs = new String[] { "單反相機", "IPAD", "恭喜發財", "IPHONE",
            "妹子一隻", "恭喜發財" };

    private int [] mColors = new int[] { 0xFFFFC300, 0xFFF17E01, 0xFFFFC300,
            0xFFF17E01, 0xFFFFC300, 0xFFF17E01};

    private int [] mBitmaps = new int[]{R.drawable.danfan, R.drawable.ipad, R.drawable.f015, R.drawable.iphone, R.drawable.meizi, R.drawable.f040};

    private Bitmap [] mImgs;

    private int mItemCount = 6;
    public LuckyPan(Context context) {
        super(context);
    }

    public LuckyPan(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void run() {
        while(mIsDrawing) {
            long start = System.currentTimeMillis();
            draw();
            long end = System.currentTimeMillis();
            try {
                if ((end - start)< 50){
                    Thread.sleep( 50 - (end-start));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    float mStartAngle = 0;
    public void draw() {
        try {
            mCanvas = mHolder.lockCanvas();
            if (mCanvas != null) {
                //先畫背景
                drawBg();
                //畫arc
//                drawArc();
                float tmpAngle = mStartAngle;

                mCanvas.save();
                mCanvas.translate(mCenter, mCenter);

                RectF r = new RectF(-1 * mRadius/2, -1 * mRadius/2, mRadius/2 , mRadius/2);
                for(int i = 0; i < mItemCount; i ++){
                    mArcPaint.setColor(mColors[i]);
                    mCanvas.drawArc(r, tmpAngle,  60, true, mArcPaint);
                    drawText2(tmpAngle, 60, mStrs[i]);
                    drawIcon2(tmpAngle, i);
                    mCanvas.rotate(60);
                }
                mCanvas.restore();

                mStartAngle += mSpeed;

                if (isShouldEnd){
                    mSpeed -= 1;
                }

                if (mSpeed < 0){
                    mSpeed = 0;
                    isShouldEnd = false;
                }

//                calInExactArea(mStartAngle);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (mCanvas != null){
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        super.surfaceCreated(holder);

        //畫弧的筆
        mArcPaint = new Paint();
        mArcPaint.setAntiAlias(true);
        mArcPaint.setDither(true);

        mRange = new RectF(getPaddingLeft(), getPaddingLeft(), mRadius + getPaddingLeft(), mRadius + getPaddingLeft());
        //畫文字的筆
        mTextPaint = new Paint();
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setColor(Color.WHITE);

        mImgs = new Bitmap[mItemCount];
        for(int i = 0; i < mItemCount; i ++){
            mImgs[i]= BitmapFactory.decodeResource(getResources(), mBitmaps[i]);
        }
    }

    //中心點
    int mCenter;
    //邊距
    int mPadding;
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = Math.min(getMeasuredHeight(), getMeasuredWidth());
        //直徑
        mRadius = width - getPaddingLeft() - getPaddingRight();

        mCenter = width/2;
        mPadding = getPaddingLeft();

        setMeasuredDimension(width, width);
    }


    //背景圖片
    Bitmap mBgBitmap;
    //畫背景
    public void drawBg(){
        mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg2);
        mCanvas.drawColor(0XFFFFFFFF);
        mCanvas.drawBitmap(mBgBitmap, null, new Rect(mPadding /2, mPadding /2 ,
                getMeasuredWidth() - mPadding/2, getMeasuredHeight() - mPadding /2), null);

    }

    public void drawText(float startAngle, float item, String title){
        Path  path = new Path();
        path.addArc(mRange, startAngle, item);
        float textWidth = mTextPaint.measureText(title);

        float h = (float) (Math.PI * mRadius /mItemCount/2 - textWidth/2);
        float v = mPadding * 3/2;
        mCanvas.drawTextOnPath(title, path, h, v, mTextPaint);
    }
    //旋轉的方式得到
    public void drawText2(float startAngle, float gapAngle, String title){
        RectF r = new RectF(-1 * mRadius/2, -1 * mRadius/2, mRadius/2, mRadius/2);
        Path p = new Path();
        p.addArc(r, startAngle , gapAngle);

        float textWidth = mTextPaint.measureText(title);

        float hoffset = (float) (Math.PI * mRadius /mItemCount/2 - textWidth/2);
        float voffset = mPadding * 3/2;
        mCanvas.drawTextOnPath(title, p, hoffset, voffset, mTextPaint);

    }

    public void drawIcon(float startAngle, int i){
        int imgWidth = mRadius/2/4;
        float angle = (float)( (30 + startAngle) * (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(mImgs[i], null, rect, null);

    }

    public void drawIcon2(float startAngle, int i){
        int imgWidth = mRadius/2/4;
        float angle = (float) ((mStartAngle + 30) * (Math.PI/180));
        int x = (int) (mRadius/4 * Math.cos(angle));
        int y = (int) (mRadius/4 * Math.sin(angle));
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), mBitmaps[i]);
        Rect r = new Rect(x - imgWidth/2, y - imgWidth/2, x + imgWidth/2 , y+imgWidth/2);
        mCanvas.drawBitmap(bitmap, null, r, null);
    }

    public boolean isStart(){
        return mSpeed != 0;
    }

    public boolean isShouldEnd(){
        return isShouldEnd;
    }

}

接下來就是在佈局檔案中寫入該自定義方法
佈局方法是RelativeLayout

<?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.liu.get.lunpan.LuckyPan
        android:id="@+id/pan"
        android:layout_width="match_parent"
        android:layout_centerInParent="true"
        android:padding="20dp"
        android:layout_height="match_parent" />

    <ImageView
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:src="@drawable/start"/>

</RelativeLayout>

最後一步:在Activity中寫點選監聽

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    ImageView iv;
    LuckyPan luckyPan;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        luckyPan = (LuckyPan) findViewById(R.id.pan);

        iv = (ImageView) findViewById(R.id.btn);

        iv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!luckyPan.isStart()) {
                    iv.setImageResource(R.drawable.stop);
                    luckyPan.mSpeed = 38;
                } else {
                    iv.setImageResource(R.drawable.start);
                    luckyPan.isShouldEnd = true;
                }
            }
        });
    }
}