Android-繪圖機(jī)制總結(jié)

前言

早在今年年初就發(fā)過關(guān)于Android繪圖機(jī)制的博文锈候,只不過不是在簡(jiǎn)書泵琳,是在CSDN获列。而且已經(jīng)過去很久了有的地方也忘記了击孩,最重要的是當(dāng)時(shí)剛剛開始寫博客巩梢,很多地方不規(guī)范,自己查閱起來也比較麻煩饭聚,所以重新在簡(jiǎn)書上整理一篇繪圖機(jī)制的總結(jié)秒梳,內(nèi)容是整合了android群英傳和android開發(fā)藝術(shù)探索兩本書中的內(nèi)容端幼。覺得不錯(cuò)的話可以點(diǎn)擊一個(gè)“喜歡”。

這里你將了解到以下內(nèi)容:

  • Android屏幕相關(guān)知識(shí)
  • Android繪圖技巧
  • Android圖像處理技巧
  • SurfaceView的使用

1庭呜、屏幕尺寸信息

1.屏幕參數(shù)

一塊屏幕通常具備以下的幾個(gè)參數(shù)
屏幕大心蓟选:
指屏幕對(duì)角線的長(zhǎng)度数冬,通常用寸來表示拐纱,例如4.7寸秸架,5.5寸
分辨率:
分辨率是指實(shí)際屏幕的像素點(diǎn)個(gè)數(shù)东抹,例如720X1280就是指屏幕的分辨率缭黔,寬有720個(gè)像素點(diǎn)馏谨,高有1280個(gè)像素點(diǎn)
PPI
每英寸像素又稱為DPI田巴,他是由對(duì)角線的的像素點(diǎn)數(shù)除以屏幕的大小所得壹哺,通常有400PPI就已經(jīng)很6了

2.系統(tǒng)屏幕密度

這里寫圖片描述

3.獨(dú)立像素密度dp

這是由于各種屏幕密度的不同,導(dǎo)致同樣像素大小的長(zhǎng)度管宵,在不同密度的屏幕上顯示長(zhǎng)度不同箩朴,因此相同長(zhǎng)度的屏幕炸庞,高密度的屏幕包含更多的像素點(diǎn)埠居,在安卓系統(tǒng)中使用mdpi密度值為160的屏幕作為標(biāo)準(zhǔn)滥壕,在這個(gè)屏幕上绎橘,1px = 1dp称鳞,其他屏幕則可以通過比例進(jìn)行換算胡岔,例如同樣是100dp的長(zhǎng)度靶瘸,mdpi中為100px怨咪,而在hdpi中為150诗眨,我們也可以得出在各個(gè)密度值中的換算公式,在mdpi中 1dp = 1px, 在hdpi中厂财, 1dp = 1.5px璃饱,在xhdpi中荚恶,1dp = 2px,在xxhdpi中1dp = 3px,由此可見谒撼,我們換算公式l:m:h:xh:xxh = 3:4:6:8:12

4.換算公式

這里就不貼出來了,點(diǎn)擊跳轉(zhuǎn)到我歷史博客即可;
系統(tǒng)提供TypedValue幫助我們轉(zhuǎn)換

/**
     * dp2px
     * @param dp
     * @return
     */
    protected int dp2px(int dp){
        return (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,getResources()
.getDisplayMetrics());
    }

    /**
     * sp2px
     * @param dp
     * @return
     */
    protected int sp2px(int sp){
        return (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,sp
,getResources().getDisplayMetrics());
    }

二茉帅、繪圖基礎(chǔ)

1.Paint

作為一個(gè)非常重要的元素,功能也是很強(qiáng)大的以下是一些基礎(chǔ)的屬性和對(duì)應(yīng)的功能

  • setAntiAlias(); //設(shè)置畫筆的鋸齒效果
  • setColor(); //設(shè)置畫筆的顏色
  • setARGB(); //設(shè)置畫筆的A、R味滞、G剑鞍、B值
  • setAlpha(); //設(shè)置畫筆的Alpha值
  • setTextSize(); //設(shè)置字體的尺寸
  • setStyle(); //設(shè)置畫筆的風(fēng)格(空心或?qū)嵭模?/li>
  • setStrokeWidth(); //設(shè)置空心邊框的寬度
  • getColor(); //獲取畫筆的顏色

接下來實(shí)現(xiàn)一個(gè)Demo
代碼:

        paint1 = new Paint();
        paint1.setColor(Color.BLUE);
        paint1.setAntiAlias(true);
        //空心
        paint1.setStyle(Paint.Style.STROKE);
        paint2 = new Paint();
        paint2.setColor(Color.GREEN);
        //實(shí)心
        paint2.setStyle(Paint.Style.FILL);

效果圖:


這里寫圖片描述

2.Canvas

四種常用的方法

        canvas.save();          //保存畫布
        canvas.restore();       //合并圖層
        canvas.translate(x,y);  //畫布平移到x,y處
        canvas.rotate(翻轉(zhuǎn)的角度,圓心的X坐標(biāo),圓心的Y坐標(biāo));//畫布翻轉(zhuǎn)

DrawPoint 繪制點(diǎn)
canvas.drawPoint(x,y,paint);

DrawLine繪制直線
canvas.drawLine(startX,startY,endX,endY,paint);
繪制多條直線:
float[] pts1={startX1,startY1,endX1,endY1...startXn,startYnendXn,endYn};
canvas.drawLines(pts,paint);

DrawRect繪制矩形
canvas.drawRect(left,top,right,button,paint);

DrawRoundRect繪制圓角矩形
canvas.drawRect(left,top,right,button,radiusX,radiusY,paint);

DrawCircle繪制圓
canvas.drawCircle(圓心X坐標(biāo),Y坐標(biāo),半徑,paint1);

DrawArc繪制弧形/扇形
兩種寫法:
第一種:canvas.drawArc(left,top,right,button, startAngle, sweepAngle, useCenter, paint2);
第二種:
RectF rectF = new RectF(left,top,right,button);
canvas.drawArc(rectF, 0, 100, true, paint2);
在這里rectF代表的是圓弧外輪擴(kuò)矩形區(qū)域
startAngle表示起始的角度 (以X軸正方向?yàn)?度順時(shí)針開始算)
sweepAngle為圓弧掃過的角度
useCenter設(shè)置為true的時(shí)候顯示圓心

這里寫圖片描述

DrawPath繪制路徑
繪制多邊形

        //實(shí)例化路徑
        Path path = new Path();
        path.moveTo(80, 200);// 此點(diǎn)為多邊形的起點(diǎn)
        path.lineTo(120, 250);
        path.lineTo(80, 250);
        path.lineTo(300, 300);
        //path.close(); // 使這些點(diǎn)構(gòu)成封閉的多邊形
        canvas.drawPath(path, paint1);

繪制曲線:

        Path path=new Path();
        path.moveTo(100, 320);          //設(shè)置Path的起點(diǎn)
        path.quadTo(160,320,180,410);   //設(shè)置路徑點(diǎn)和終點(diǎn)
        canvas.drawPath(path, paint1);


DrawOval繪制橢圓
DrawOval(left,top,right,button,paint);

RectF rectF = new RectF(210,100,250,130) ;
 canvas.drawOval(rectF, paint2) ;

DrawText繪制文本
canvas.drawText("自定義文本",X坐標(biāo),Y坐標(biāo),paint);
繪制不同位置的文本信息

float [] pts=new float[]{100,100,200,200,300,300,400,400,500,500,600,600};
        canvas.drawPosText("text",pts,paint1);

效果圖:


不同位置繪制文本信息

三遂赠、XML繪圖

1跷睦、Bitmap

在XML中使用Bitmap很簡(jiǎn)單

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@mipmap/ic_launcher">
</bitmap>

通過這樣引用圖片就可以將圖片直接轉(zhuǎn)化成Bitmap讓我們?cè)诔绦蛑惺褂?/p>

2抑诸、Shape

通過Shape可以繪制各種圖形,下面展示一下shape的參數(shù)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!--默認(rèn)是rectangle-->
    <!--當(dāng)shape= rectangle的時(shí)候使用-->
    <corners
        android:bottomLeftRadius="1dp"
        android:bottomRightRadius="1dp"
        android:radius="1dp"
        android:topLeftRadius="1dp"
        android:topRightRadius="1dp" />
    <!--半徑边灭,會(huì)被后面的單個(gè)半徑屬性覆蓋绒瘦,默認(rèn)是1dp-->

    <!--漸變-->
    <gradient
        android:angle="1dp"
        android:centerColor="@color/colorAccent"
        android:centerX="1dp"
        android:centerY="1dp"
        android:gradientRadius="1dp"
        android:startColor="@color/colorAccent"
        android:type="linear"
        android:useLevel="true" />

    <!--內(nèi)間距-->
    <padding
        android:bottom="1dp"
        android:left="1dp"
        android:right="1dp"
        android:top="1dp" />

    <!--大小惰帽,主要用于imageview用于scaletype-->
    <size
        android:width="1dp"
        android:height="1dp" />

    <!--填充顏色-->
    <solid android:color="@color/colorAccent" />

    <!--指定邊框-->
    <stroke
        android:width="1dp"
        android:color="@color/colorAccent" />
    <!--虛線寬度-->
    android:dashWidth= "1dp"

    <!--虛線間隔寬度-->
    android:dashGap= "1dp"
</shape>

3.Layer

Layer是在PhotoShop中是非常常用的功能该酗,在Android中呜魄,我們同樣可以實(shí)現(xiàn)圖層的效果

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!--圖片1-->
    <item android:drawable="@mipmap/ic_launcher"/>

    <!--圖片2-->
    <item
        android:bottom="10dp"
        android:top="10dp"
        android:right="10dp"
        android:left="10dp"
        android:drawable="@mipmap/ic_launcher"
        />
</layer-list>

4.Selector

Selector的作用是幫助開發(fā)者實(shí)現(xiàn)靜態(tài)View的反饋爵嗅,通過設(shè)置不同的屬性呈現(xiàn)不同的效果

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 默認(rèn)時(shí)候的背景-->
    <item android:drawable="@mipmap/ic_launcher" />

    <!-- 沒有焦點(diǎn)時(shí)候的背景-->
    <item android:drawable="@mipmap/ic_launcher" android:state_window_focused="false" />

    <!-- 非觸摸模式下獲得焦點(diǎn)并點(diǎn)擊時(shí)的背景圖片-->
    <item android:drawable="@mipmap/ic_launcher" android:state_pressed="true" android:state_window_focused="true" />

    <!-- 觸摸模式下獲得焦點(diǎn)并點(diǎn)擊時(shí)的背景圖片-->
    <item android:drawable="@mipmap/ic_launcher" android:state_focused="false" android:state_pressed="true" />

    <!--選中時(shí)的圖片背景-->
    <item android:drawable="@mipmap/ic_launcher" android:state_selected="true" />

    <!--獲得焦點(diǎn)時(shí)的圖片背景-->
    <item android:drawable="@mipmap/ic_launcher" android:state_focused="true" />

</selector>

這一方法可以幫助開發(fā)者迅速制作View的反饋,通過配置不同的觸發(fā)事件伪很,selector會(huì)自動(dòng)選中不同的圖片锉试,特別是自定義button的時(shí)候呆盖,而我們不再使用原生單調(diào)的背景絮短,而是使用selector特別制作的背景丁频,就能完美實(shí)現(xiàn)觸摸反饋了

通常情況下叔磷,上面提到的這些方法都可以共同實(shí)現(xiàn)改基,下面這個(gè)例子就展示了在一個(gè)selector中使用shape作為他的item的例子秕狰,實(shí)現(xiàn)一個(gè)具體點(diǎn)擊反饋效果的鸣哀,圓角矩形的selector我衬,代碼如下

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <!--填充顏色-->
            <solid android:color="#33444444" />
            <!--設(shè)置按鈕的四個(gè)角為弧形-->
            <corners android:radius="5dp" />
            <!--間距-->
            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
        </shape>
    </item>

    <item>
        <shape android:shape="rectangle">
            <!--填充顏色-->
            <solid android:color="#FFFFFF" />
            <!--設(shè)置按鈕的四個(gè)角為弧形-->
            <corners android:radius="5dp" />
            <!--間距-->
            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
        </shape>
    </item>
</selector>

四、Android繪圖技巧

在學(xué)完Android的基本繪圖之后我們來講解一下常用的繪圖技巧

1破加、Canvas

  • Canvas.save()
  • Canvas.restore()
  • Canvas.translate()
  • Canvas.roate()
    首先拌喉,我們來看一下前面兩個(gè)方法
    在講解這兩個(gè)方法之前,首先來了解一下Android繪圖的坐標(biāo)體系捶惜,這個(gè)其實(shí)這個(gè)前面已經(jīng)講了吱七,這里不贅述踊餐,而Canvas.save()這個(gè)方法,從字面上的意思可以理解為保存畫布窜管,他的作用就是講之前的圖像保存起來幕帆,讓后續(xù)的操作能像在新的畫布一樣操作,這跟PS的圖層基本差不多

而Canvas.restore()這個(gè)方法失乾,則可以理解為合并圖層常熙,,就是講之前保存下來的東西合并.
8
而后面兩個(gè)方法尼碱茁?從字母上理解畫布平移或者旋轉(zhuǎn)裸卫,但是把他理解為坐標(biāo)旋轉(zhuǎn)更加形象,前面說了早芭,我們繪制的時(shí)候默認(rèn)坐標(biāo)點(diǎn)事左上角的起始點(diǎn)彼城,那么我們調(diào)用translate(x,y)之后退个,則將原點(diǎn)(0,0)移動(dòng)到(x,y)之后的所有繪圖都是在這一點(diǎn)上執(zhí)行的

2.Layer圖層

Android中的繪圖API募壕,很大程度上都來自繪圖的API,特別是借鑒了很多PS的原理语盈,比如圖層的概念舱馅,相信看過圖層的也都知道是個(gè)什么樣的,我們畫個(gè)圖來分析一下

Android通過saveLayer()方法刀荒,saveLayerAlpha()將一個(gè)圖層入棧代嗤,使用restore()方法,restoreToCount()方法將一個(gè)圖層出棧缠借,入棧的時(shí)候干毅,后面的所有才做都是發(fā)生在這個(gè)圖層上的,而出棧的時(shí)候泼返,則會(huì)把圖層繪制在上層Canvas上硝逢,我們仿照API Demo來

@Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        mPaint.setColor(Color.BLUE);
        canvas.drawCircle(150, 150, 100, mPaint);

        canvas.saveLayerAlpha(0, 0,400,400,127,LAYER_TYPE_NONE);
        mPaint.setColor(Color.RED);
        canvas.drawCircle(200, 200, 100, mPaint);
        canvas.restore();
    }

當(dāng)繪制兩個(gè)相交的圓時(shí),就是圖層
接下來將圖層后面的透明度設(shè)置成0-255不同值
我們分別演示 127 255 0三個(gè)


五.Android圖像處理之畫筆特效處理

不管是在我們的世界里绅喉,還是在Android的世界里渠鸽,要想畫出好的圖片,就必須賬務(wù)畫筆的特效柴罐,今天我們就來玩玩這個(gè)Paint的特殊Get

1.PorterDuffXfermode

image.png

途中列舉了16種PorterDuffXfermode徽缚,有點(diǎn)像數(shù)學(xué)中的集合,主要是一個(gè)混合顯示模式

這里注意了,PorterDuffXfermode設(shè)置兩個(gè)圖層交集區(qū)域的顯示方法des是先畫的圖像革屠,src是后畫的

當(dāng)然凿试,這些模式也不是經(jīng)常的用到排宰,用到最多的事,使用一張圖片作為另一張圖片的遮罩红省,通過控制遮罩層的圖形额各,來控制下面被遮罩的顯示效果,其中最常用的就是通過DST_IN.SRC_IN模式來實(shí)現(xiàn)將一個(gè)矩形變成圓角圖片的效果吧恃,我們這里來實(shí)現(xiàn)一下

mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.nice);
        mOut = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mOut);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        canvas.drawRoundRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), 80, 80, mPaint);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(mBitmap,0,0,mPaint);

下面我們來做一個(gè)比較類似于刮刮卡的效果,其實(shí)效果就是兩張圖片虾啦,上面那張一刮就顯示下面的那張看,這個(gè)效果同樣我們可以使用PorterDuffXfermode去實(shí)現(xiàn)痕寓,我們首先要做的就是初始化一些數(shù)據(jù)

Join
Cap
public class PlayView extends View {

    private Bitmap mBgBitmap, mFgBitmap;
    private Paint mPaint;
    private Canvas mCanvas;
    private Path mPath;

    /**
     * 構(gòu)造方法
     *
     * @param context
     * @param attrs
     */
    public PlayView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        mPaint = new Paint();
        mPaint.setAlpha(0);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);//讓筆更加圓滑一些
        mPaint.setStrokeWidth(50);
        mPaint.setStrokeCap(Paint.Cap.ROUND);//讓筆更加圓滑一些

        mPath = new Path();
        mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.nice);
        mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mFgBitmap);
        mCanvas.drawColor(Color.GRAY);
    }

    /**
     * 觸摸事件
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPath.reset();
                mPath.moveTo(event.getX(), event.getY());
                break;
            case MotionEvent.ACTION_UP:
                mPath.lineTo(event.getX(), event.getY());
                break;
        }
        mCanvas.drawPath(mPath, mPaint);
        invalidate();
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBgBitmap, 0, 0, null);
        canvas.drawBitmap(mFgBitmap, 0, 0, null);
    }
}

2,Shader

Shader又被稱為著色器傲醉。渲染器,它可以實(shí)現(xiàn)渲染呻率,漸變等效果硬毕,Android中的Shader包括以下幾種

BitmapShader:位圖Shader
LinearGradient:線性Shader
RadialGradient:光束Shader
SweepGradient:梯形Shader
ComposeShader:混合Shader

除了第一個(gè)之外,其他的都是比較正常的礼仗,實(shí)現(xiàn)了名副其實(shí)的漸變吐咳,渲染效果,而與其他Shader的效果不同的是元践,BitmapShader所產(chǎn)生的是一個(gè)圖像韭脊,有點(diǎn)類似PS里面的圖像填充,他的作用是通過Paint對(duì)畫布進(jìn)行制定bitmap的填充单旁,填充式有一下幾個(gè)模式供選擇沪羔。

  • CLAMP拉伸——拉伸的是圖片最后的哪一個(gè)像素,不斷重復(fù)
  • REPEAT重復(fù)——橫向象浑,縱向不斷重復(fù)
  • MIRROR鏡像——橫向不斷翻轉(zhuǎn)重復(fù)蔫饰,縱向不斷翻轉(zhuǎn)重復(fù)

這幾種模式的含義都非常好理解的,與字面意識(shí)基本相同愉豺,這里最常用的是CLAMP拉伸模式篓吁,雖然他會(huì)拉伸最后一個(gè)像素,但是只要將突破設(shè)置成一個(gè)固定的像素蚪拦,是可以避免的越除,

六.View之孿生兄弟---SurfaceView

Android系統(tǒng)提供了VieW進(jìn)行繪圖處理, vieW可以滿足大部分的繪圖需求,但在某些時(shí)卻也有些心有余而力不足,特別是在進(jìn)行一些開發(fā)的時(shí)候外盯。 我們知道,VieW通過刷新來視圖, Android系統(tǒng)通過發(fā)出VSYNC信號(hào)來進(jìn)行屏幕的重繪, 刷新的間隔時(shí)間為I6ms。在16ms內(nèi)View完成了你所需要執(zhí)行的所有操作,那么用戶在視覺上, 就不會(huì)產(chǎn)生卡頓的感覺:而如果執(zhí)行的操作邏輯太多,特別是需要頻繁刷新的界面上翼雀,例如游戲界面,那么就塞主線程饱苟,從而導(dǎo)致畫面卡頓,很多時(shí)候,在自定義VieW的Log中經(jīng)常會(huì)看見如下示的警告

Skipped 47 frames! The application may be doing too much work on its main thread

這些警告的產(chǎn)生狼渊,很多情況下就是因?yàn)樵诶L制過程中, 處理邏輯太多造成的為了避免這一問題的產(chǎn)生一 Android系統(tǒng)提供了surfacevicW組件來解決這個(gè)問題,可以說是VieW的孿生兄弟,但它與View還是有所不同的,它們的區(qū)別主要體現(xiàn)

  1. View主要用于自動(dòng)更新的情況下,而surfaceVicw主要適用于被動(dòng)更新,例如頻繁刷新
  2. View在主線程中刷新箱熬,而surfaceView通常會(huì)通過一 個(gè)子線程來進(jìn)行頁面刷新类垦。
  3. View在繪制的時(shí)候沒有雙緩沖機(jī)制,而surfaceVicw在底層實(shí)現(xiàn)機(jī)制中就已經(jīng)實(shí)現(xiàn)了雙緩沖機(jī)制;

總結(jié)起來城须,如果你的自定義View需要頻繁刷新,或者刷新時(shí)數(shù)據(jù)處理量比較大蚤认,那么你就可以考慮使用surfaceVicw取代View了

1.surfaceView的使用

一套模板代碼:

public class SurfaView extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    //SurfaceHolder
    private SurfaceHolder mHolder;
    //用于繪制的Canvas
    private Canvas mCanvas;
    //子線程標(biāo)志位
    private boolean mIsDrawing;

    /**
     * 構(gòu)造方法
     *
     * @param context
     * @param attrs
     */
    public SurfaView(Context context, AttributeSet attrs) {
        super(context, attrs);

        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) {
        mIsDrawing = false;
    }

    @Override
    public void run() {
        while (mIsDrawing) {
            draw();
      //在這里不斷繪制要繪制的內(nèi)容
        }
    }

    private void draw() {
        try {
            mCanvas = mHolder.lockCanvas();
            //這里要不斷地用mCanvas方法繪制
        } catch (Exception e) {

        } finally {
            if (mCanvas != null) {
                //提交
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    }
}

注意

@Override
public void run() {
long start = System.currentTimeMillis();
while (mIsDrawing) {
draw();
}
long end = System.currentTimeMillis();
// 50 - 100
if (end - start < 100) {
try {
Thread.sleep(100 - (end - start));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
由于不斷的調(diào)用draw()來進(jìn)行繪制,有時(shí)候也不用那么頻繁糕伐∨樽粒可以設(shè)置Sleep操作。盡可能的省資源
100ms是一個(gè)經(jīng)驗(yàn)值良瞧,通撑闫可以設(shè)置成50-100ms.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市褥蚯,隨后出現(xiàn)的幾起案子挚冤,更是在濱河造成了極大的恐慌,老刑警劉巖赞庶,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件训挡,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡歧强,警方通過查閱死者的電腦和手機(jī)澜薄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來誊锭,“玉大人表悬,你說我怎么就攤上這事∩ッ遥” “怎么了蟆沫?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)温治。 經(jīng)常有香客問我饭庞,道長(zhǎng),這世上最難降的妖魔是什么熬荆? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任舟山,我火速辦了婚禮,結(jié)果婚禮上卤恳,老公的妹妹穿的比我還像新娘累盗。我一直安慰自己,他們只是感情好突琳,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布若债。 她就那樣靜靜地躺著,像睡著了一般拆融。 火紅的嫁衣襯著肌膚如雪蠢琳。 梳的紋絲不亂的頭發(fā)上啊终,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音傲须,去河邊找鬼蓝牲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛泰讽,可吹牛的內(nèi)容都是我干的例衍。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼菇绵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼肄渗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咬最,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤翎嫡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后永乌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惑申,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年翅雏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了圈驼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡望几,死狀恐怖绩脆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情橄抹,我是刑警寧澤靴迫,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站楼誓,受9級(jí)特大地震影響玉锌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜疟羹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一主守、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榄融,春花似錦参淫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至民效,卻和暖如春憔维,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背畏邢。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工业扒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舒萎。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓程储,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親臂寝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子章鲤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容