SurfaceView的使用基础

1.SurfaceView的基本使用模板

public class SurfaceViewWriter extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    SurfaceHolder holder;
    boolean isRunning;
    Thread drawThread;
    Canvas canvas;
    int x = 0, y = 0;

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

    /*holder是SurfaceView的持有者,它不仅管理者SurfaceView的生命周期
    同时可以利用其获取Canvas来对SurfaceView进行绘制
     */
    public SurfaceViewWriter(Context context, AttributeSet attrs) {
        super(context, attrs);
        holder = getHolder();
        isRunning = false;
        setFocusable(true);//键盘能获取焦点
        setKeepScreenOn(true);//设置常亮
        setFocusableInTouchMode(true);//设置触摸能否获取焦点
        holder.addCallback(this);//通过添加回调进行生命周期的管理

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("tagsome", "execute");
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                x = (int) event.getX();
                y = (int) event.getY();
                return true;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void run() {
        while (isRunning) {
            draw();
        }
    }
    //用于清除View的所有已绘的图像
    public void clear(Canvas aCanvas) {
        Paint paint = new Paint();//PorterDuff.Mode.CLEAR所绘制不会提交到画布上。
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        //drawPaint等价于利用该Paint绘制一个无线大的矩形到屏幕上
        aCanvas.drawPaint(paint);//PorterDuff.Mode.SRC显示上层绘制图片
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
        invalidate();
    }
    private void draw() {
        try {
            canvas = holder.lockCanvas();
            Paint paint = new Paint();
            paint.setColor(Color.BLUE);
            if (canvas != null) {
                clear(canvas);
                canvas.drawRect(x, y, x + 50, y + 50, paint);
            }
        }//防止home键SurfaceFace被销毁或者SurfaceView被销毁但是线程没有被销毁
        catch (Exception e) {
        } finally {
            if (canvas != null) {
                holder.unlockCanvasAndPost(canvas);
            }
        }
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        isRunning = true;
        drawThread = new Thread(this);
        drawThread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        isRunning = false;
    }
}

2.案例学习

学到什么:
(1)利用带有范围限制的方法去限制绘制的图形或者图片
(2)SurfaceView的基本使用方法,通过独立线程而不用使用UI线程来进行绘制,主要关注SurfaceHolder
的作用及其通过CallBack来管理生命周期的方式
(3)通过Paint对文字长度的测量、按路径绘制文字的方法


实现的方法:
通过单独线程在Draw方法不断的绘制转盘、转盘的子项,对于转动方法只需不断修改第一项绘制的起始角度即可,
通过指定停止后的转动距离来计算速度约束停止时指向的子项

public class ApplySurface extends SurfaceView implements SurfaceHolder.Callback ,Runnable{
    SurfaceHolder holder;
    boolean isRunning;
    Thread drawThread;
    Canvas canvas;
    String mstrs[]=new String[]{"单反相机","ipad","恭喜发财","iphone","服装一套","恭喜发财"};
    int []imageId=new int[]{R.drawable.a1,R.drawable.a2,R.drawable.a3,R.drawable.a4,R.drawable.a5,R.drawable.a3};
    int []mcolors=new int[]{0xFFFC300,0xFFF17E01,0xFFFC300,0xFFF17E01,0xFFFC300,0xFFF17E01};//盘块的颜色
    int mitemcount=6;
    Bitmap []mimageBitmaps;//与Id匹配的图片
    RectF mrange=new RectF();//整个盘块的范围
    int radius;//盘块的直径
    Paint arcPaint;//绘制转盘用的画笔
    Paint textPaint;//绘制文字的画笔
    int speed=0;//转动速度
    volatile int startAngle=0;//保证线程间的可见性,起始角度
    boolean isshouldEnd;
    int center;//中心
    int padding;
    Bitmap bgBitmap= BitmapFactory.decodeResource(getResources(),R.drawable.bkpanel);
    float textSize= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,20,getResources().getDisplayMetrics());

    public ApplySurface(Context context) {
        this(context,null);
    }
    /*holder是SurfaceView的持有者,它不仅管理者SurfaceView的生命周期
    同时可以利用其获取Canvas来对SurfaceView进行绘制
     */
    public ApplySurface(Context context, AttributeSet attrs) {
        super(context, attrs);
        holder=getHolder();
        isRunning=false;
        setFocusable(true);//键盘能获取焦点
        setKeepScreenOn(true);//设置常亮
        setFocusableInTouchMode(true);//设置触摸能否获取焦点
        holder.addCallback(this);//通过添加回调进行生命周期的管理
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width=Math.min(getMeasuredWidth(),getMeasuredHeight());
        padding=getPaddingLeft();
        radius=width-padding*2;
        center=width/2;
        setMeasuredDimension(width,width);//必须调用
    }

    @Override
    public void run() {
        while (isRunning){
            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 {
            canvas = holder.lockCanvas();
            if (canvas != null) {
                drawBg();
                float tmpAngle=startAngle;
                float sweepAngle=360/mitemcount;
                for(int i=0;i<mitemcount;i++){
                    arcPaint.setColor(mcolors[i]);
                    //绘制盘块
                    canvas.drawArc(mrange,tmpAngle,sweepAngle,true,arcPaint);
                    //绘制文本
                    drawText(tmpAngle,sweepAngle,mstrs[i]);
                    //绘制图标
                    drawIcon(tmpAngle,mimageBitmaps[i]);
                    tmpAngle+=sweepAngle;
                }
                startAngle+=speed;
                startAngle=startAngle<360?startAngle:startAngle%360;
                //如果点击了停止按钮
                if(isshouldEnd){
                    speed=Math.max(0,speed-1);//速度逐渐减小
                     if(speed==0){
                        isshouldEnd=false;
                    }
                }
            }
        }//防止home键SurfaceFace被销毁或者SurfaceView被销毁但是线程没有被销毁
        catch (Exception e){}
        finally {
            if(canvas!=null){
                holder.unlockCanvasAndPost(canvas);
            }
        }
    }
    //点击启动旋转
    public void luckyStart(){

        speed=50;
        isshouldEnd=false;
    }
    //转盘是否还在旋转
    public boolean isRunning(){
        return speed!=0;
    }
    //点击停止旋转,并且指定停下来的位置,也可以采用欺骗的方式
    public void luckyEnd(int index){
        isshouldEnd=true;
        float angle=360/mitemcount;
        float from=270-(index+1)*angle;//270坐标0度与指针初始位置之差
        float end=from+angle;
        //设置停止按下后需转动的距离范围
        float targetFrom=((index+1)*angle-startAngle+360)+4*360+from;
        float targetEnd=((index+1)*angle-startAngle+360)+4*360+end;

        float v1= (float) (-1+Math.sqrt(1+8*targetFrom)/2);
        float v2= (float) (-1+Math.sqrt(1+8*targetEnd)/2);
        speed= (int) (v1+Math.random()*(v2-v1));
    }
    private void drawIcon(float tmpAngle, Bitmap bitmap) {
        int imgwidth=radius/8;
        float angle= (float) Math.toRadians(tmpAngle+360/mitemcount/2);
        int x= (int) (center+radius*3/10*Math.cos(angle));
        int y= (int) (center+radius*3/10*Math.sin(angle));
        //使用矩形区域来约束绘制图片的大小
        Rect rect=new Rect(x-imgwidth/2,y-imgwidth/2,x+imgwidth/2,y+imgwidth/2);
        canvas.drawBitmap(bitmap,null,rect,null);
    }

    //绘制文本
    private void drawText(float tmpAngle, float sweepAngle, String mstr) {
        Path path=new Path();
        path.addArc(mrange,tmpAngle,sweepAngle);
        int textWidth= (int) textPaint.measureText(mstr);
        int hoffset= (int) (radius*Math.PI/mitemcount/2-textWidth/2);//水平偏移
        int voffset=radius/2/6;//垂直偏移
        canvas.drawTextOnPath(mstr,path,hoffset,voffset,textPaint);
    }

    //绘制背景
    private void drawBg() {
        canvas.drawColor(0xFFFFFFFF);
        canvas.drawBitmap(bgBitmap,null,new RectF(padding/2,padding/2,getMeasuredWidth()-padding/2,
                getMeasuredHeight()-padding/2),null);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        isRunning=true;
        drawThread=new Thread(this);
        drawThread.start();
        arcPaint=new Paint();
        arcPaint.setAntiAlias(true);
        arcPaint.setDither(true);

        textPaint=new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setColor(0xFFFFFFFF);
        textPaint.setTextSize(textSize);

        mrange=new RectF(padding,padding,padding+radius,padding+radius);

        mimageBitmaps=new Bitmap[mitemcount];
        for(int i=0;i<mitemcount;i++){
            mimageBitmaps[i]=BitmapFactory.decodeResource(getResources(),imageId[i]);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        isRunning=false;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值