SurfaceView的基本用法模板自定义实现抽奖盘

来源:互联网 发布:红包软件代理加盟 编辑:程序博客网 时间:2024/05/16 16:57

一概述
SurfaceView是在子线程中进行绘制的,SurfaceHolder提供Canvas并管理SurfaceView的生命周期。

二、模板编程思路
1、继承SurfaceView,声明一个绘制的线程,获取SurfaceHolder,控制线程的变量,Canvas。
2、构造方法中对变量进行初始化,SurfaceHolder提供Canvas与生命周期的CallBack;
3、在surfaceCreated方法中启动线程绘制
4、surfaceDestroyed方法中停止线程

1、SurfaceViewTempLate类

package template;import android.content.Context;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.SurfaceHolder;import android.view.SurfaceView;public class SurfaceViewTempLate extends SurfaceView implements SurfaceHolder.Callback,Runnable {    private SurfaceHolder holder;    private Canvas  mCanvas;    //用于绘制的线程    private  Thread t;    //线程控制开关    private boolean isRunning = false;    public SurfaceViewTempLate(Context context) {       this(context,null);    }    public SurfaceViewTempLate(Context context, AttributeSet attrs) {        super(context, attrs);        holder = getHolder();        holder.addCallback(this);        //设置可获得焦点        setFocusable(true);        setFocusableInTouchMode(true);        //设置常量        setKeepScreenOn(true);    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        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() {        try {            mCanvas = holder.lockCanvas();            if (mCanvas != null)            {            }        }catch (Exception e)        {        }finally {            if (mCanvas != null)            {                 holder.unlockCanvasAndPost(mCanvas);            }        }    }}

三、PackPan的实现
编码思路:
1、拷贝模板SurfaceViewTempLate类修改下名字
2、声明变量
3、重写下onMeasure方法,并初始化布局大小
4、surfaceCreated类中初始化变量
5、在线程中进行绘制背景,盘块,文字,图片

2、LankPan类

package app.kuxiao.com.demo.lack;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.Log;import android.util.TypedValue;import android.view.SurfaceHolder;import android.view.SurfaceView;public class LackPan extends SurfaceView implements SurfaceHolder.Callback, Runnable {    private SurfaceHolder holder;    private Canvas mCanvas;    //用于绘制的线程    private Thread t;    //线程控制开关    private boolean isRunning = false;    //盘块的图片    private int[] lack_icons = new int[]{R.drawable.danfan, R.drawable.f015, R.drawable.ipad, R.drawable.f040, R.drawable.iphone, R.drawable.meizi};    //盘块的文字    private String[] lack_text = new String[]{"单反", "恭喜发财", "Ipad", "恭喜发财", "iPhone", "服装一套"};    private int[] lack_color = new int[]{0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01};    //盘块的数量    private int lack_count = 6;    private Bitmap[] lack_bitmap = null;    //范围    private RectF mRange = null;    //整个盘块的直径    private int mRadius = 0;    //盘状的画笔    private Paint mPanPaint;    //文字的画笔    private Paint mTextPaint;    //旋转的速度    private double mSpeed = 0;    //开始的角度    private volatile int mStartAngle = 0;    //是否点击停止    private boolean isOnClickStop = false;    //转盘的中心    private int mCentre = 0;    //    private int mPadding;    //转盘的背景图    private Bitmap bg_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg2);    //设置文字的大小    private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());    public LackPan(Context context) {        this(context, null);    }    public LackPan(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 - 2 * mPadding;        //设置中心点        mCentre = width / 2;        //设置下View的尺寸        setMeasuredDimension(width, width);    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        isRunning = true;        //初始化盘的画笔        mPanPaint = new Paint();        //设置普通显示        mPanPaint.setAntiAlias(true);        //设置高频        mPanPaint.setDither(true);        //初始化文字画笔        mTextPaint = new Paint();        mTextPaint.setTextSize(mTextSize);        mTextPaint.setColor(0xffffffff);        //初始化绘制的范围        mRange = new RectF(mPadding, mPadding, mPadding + mRadius, mPadding + mRadius);        //初始化图片        lack_bitmap = new Bitmap[lack_count];        for (int i = 0; i < lack_count; i++) {            lack_bitmap[i] = BitmapFactory.decodeResource(getResources(), lack_icons[i]);        }        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) {            long start = System.currentTimeMillis();            draw();            long end = System.currentTimeMillis();            //强制绘制的时间为50毫秒以上            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();                //绘制盘块                drawPan();            }        } catch (Exception e) {        } finally {            if (mCanvas != null) {                holder.unlockCanvasAndPost(mCanvas);            }        }    }    private void drawPan() {        float startAngle = mStartAngle;        float sweedAngle = 360 / lack_count;        for (int i = 0; i < lack_count; i++) {            mPanPaint.setColor(lack_color[i]);            //绘制背景扇形            mCanvas.drawArc(mRange, startAngle, sweedAngle, true, mPanPaint);            //绘制文字            drawText(startAngle, sweedAngle, lack_text[i]);            //绘制图片            drawIcon(startAngle, lack_bitmap[i]);            startAngle += sweedAngle;        }        mStartAngle += mSpeed;        if (isOnClickStop) {            mSpeed--;            if (mSpeed < 0) {                mSpeed = 0;                isOnClickStop = false;            }        }    }    /**     * 绘制图标     *     * @param startAngle     * @param bitmap     */    private void drawIcon(float startAngle, Bitmap bitmap) {        //图片的宽度        int icon_width = mRadius / 8;        float angle = (float) ((startAngle + 360 / lack_count / 2) * Math.PI / 180);        //极坐标换算公式 x = RCOSα        //             y = RSinα 求得图片的中心位置        int x = (int) (mCentre + mRadius / 4 * Math.cos(angle));        int y = (int) (mCentre + mRadius / 4 * Math.sin(angle));        //设置图片的范围        Rect rect = new Rect(x - icon_width / 2, y - icon_width / 2, x + icon_width / 2, y + icon_width / 2);        mCanvas.drawBitmap(bitmap, null, rect, null);    }    /**     * 绘制文字     *     * @param startAngle     * @param sweedAngle     * @param s     */    private void drawText(float startAngle, float sweedAngle, String s) {        Path path = new Path();        path.addArc(mRange, startAngle, sweedAngle);        //获取文字的长度        float textwidth = mTextPaint.measureText(s);        float hOffset = (float) (sweedAngle * Math.PI / 180 / 4 * mRadius - textwidth / 2);        float vOffset = mRadius / 2 / 4;        mCanvas.drawTextOnPath(s, path, hOffset, vOffset, mTextPaint);    }    /**     * 绘制背景     */    private void drawBg() {        mCanvas.drawColor(0xffffffff);        mCanvas.drawBitmap(bg_bitmap, null, new RectF(mPadding / 2, mPadding / 2,                getMeasuredHeight() - mPadding / 2, getMeasuredHeight() - mPadding / 2), null);    }    /**     * 开始转动     * @param mSpeed     */    public void start(int mSpeed,int index) {        this.mSpeed = mSpeed;        float angle = 360/lack_count;        //当前项的中奖范围        //0的话 正中奖是旋转240度,可以偏差30度 所以为 210-270        //1的话 正中奖是旋转180,180-30~180+30 (150-210)        //2        float start = 270 - (index + 1 )* angle + 360*3;//转4圈        float end = start + angle;        double mSpeed1 = (-1 +(Math.sqrt(1+4*2*start)))/2;        double mSpeed2 = (-1 +(Math.sqrt(1+4*2*end)))/2;        Log.i("LackPan","mSpeed1的值为" + mSpeed1);        Log.i("LackPan","mSpeed2的值为" + mSpeed2);        //设置速度为mSpeed1~mSpeed2中的一个随机数        this.mSpeed = mSpeed1;        //重新设置开始角度为0;    }    /**     * 停止转动     */    public void stop() {        mStartAngle = 0;        isOnClickStop = true;       /* final Timer timer = new Timer();        timer.schedule(new TimerTask() {            @Override            public void run() {                mSpeed--;                Log.i("LackPan", "mSpeed的值为" + mSpeed);                if (mSpeed <= 0) {                    mSpeed = 0;                    timer.cancel();                }            }        }, 0, 20);*/    }}

2、MainActivity类

package app.kuxiao.com.demo.lack;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.ImageView;public class MainActivity extends AppCompatActivity {    private LackPan mLackPan = null;    private ImageView mImageView = null;    private  boolean isOnclickStart = false;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.content_main);        mLackPan = (LackPan) findViewById(R.id.lackPan);        mImageView = (ImageView) findViewById(R.id.image_start);        mImageView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                  if (isOnclickStart)                  {                       mLackPan.stop();                      isOnclickStart = false;                      mImageView.setImageResource(R.drawable.start);                  }else                  {                      isOnclickStart = true;                      mImageView.setImageResource(R.drawable.stop);                      mLackPan.start(50,0);                  }            }        });    }}

通过改变每一次绘制的初始角度,让转盘运动。

0 0
原创粉丝点击