Adroid Paint屬性(圖形、文字)

Paint mPaint = new Paint();//初始化畫筆
mPaint.setColor(Color.BLUE);//設置畫筆顏色
mPaint.setAlpha(255);//設置透明度 0-255
mPaint.setStrokeWidth(3);//設置畫筆寬度
canvas.drawLine(100,100,300,100,mPaint);//畫線
// mPaint.setStyle ()
// Paint.Style.FILL 只繪製圖形內容
// Paint.Style.STROKE 只繪製圖形輪廓(描邊)
// Paint.Style.FILL_AND_STROKE 既繪製輪廓也繪製內容
mPaint.reset();//重置
String DRAW_TEXT = "塗文遠";
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(3);
mPaint.setTextSize(100);
mPaint.setAntiAlias(true);//獲取與設置是否使用抗鋸齒功能,會消耗較大資源,繪製圖形速度會變慢,一般會開啓。設置後會平滑一些;
mPaint.setDither(true);//獲取與設定是否使用圖像抖動處理,會使繪製出來的圖片顏色更加平滑和飽滿、圖像更加清晰。
//測量文本高
Rect textBounds = new Rect();
mPaint.getTextBounds(DRAW_TEXT, 0, DRAW_TEXT.length(), textBounds);
int textH = textBounds.height();
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawText(DRAW_TEXT,0,100+textH*0,mPaint);

mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(DRAW_TEXT,0,100+textH*1,mPaint);

mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawText(DRAW_TEXT,0,100+textH*2,mPaint);

//mPaint.setStrokeCap
//Paint.Cap.BUTT(無線冒)
//Paint.Cap.ROUND(圓形線冒)
//Paint.Cap.SQUARE(方形線冒)
mPaint.reset();
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(50);

mPaint.setStrokeCap(Paint.Cap.BUTT);
canvas.drawLine(100,100,300,100,mPaint);

mPaint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(100,200,300,200,mPaint);

mPaint.setStrokeCap(Paint.Cap.SQUARE);
canvas.drawLine(100,300,300,300,mPaint);

//mPaint.setStrokeJoin();
//Paint.Join.BEVEL 結合處爲直線
//Paint.Join.ROUND 結合處爲圓弧
//Paint.Join.MITER 結合處爲銳角
mPaint.reset();
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(50);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
Path path = new Path();
path.moveTo(100,100);
path.lineTo(300,100);
path.lineTo(100,300);
path.close();
mPaint.setStrokeJoin(Paint.Join.BEVEL);
canvas.drawPath(path,mPaint);

Path path1 = new Path();
path1.moveTo(100,400);
path1.lineTo(300,400);
path1.lineTo(100,600);
path1.close();
mPaint.setStrokeJoin(Paint.Join.ROUND);
canvas.drawPath(path1,mPaint);

Path path2 = new Path();
path2.moveTo(100,700);
path2.lineTo(300,700);
path2.lineTo(100,900);
path2.close();
mPaint.setStrokeJoin(Paint.Join.MITER);
canvas.drawPath(path2,mPaint);

Paint之setXfermode--圖形混合模式

setXfermode(Xfermode xfermode)

  • 在繼承Xfermode這個類有三個子類AvoidXfermode,PixelXorXfermode,PorterDuffXfermode
  • AvoidXfermode,PixelXorXfermode是完全不支持硬件加速的,而PorterDuffXfermode是部分不支持的
public class TestPaintView extends View {

    private final Bitmap srcBmp;//源圖像
    private final Bitmap dstBmp;//目標圖像
    private final Paint mPaint;

    public TestPaintView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        srcBmp = makeSrc(400, 400);
        dstBmp = makeDst(400, 400);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int layerID = canvas.saveLayer(0,0,800,800,mPaint,Canvas.ALL_SAVE_FLAG);
        canvas.drawBitmap(dstBmp, 0, 0, mPaint);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawBitmap(srcBmp,200,200, mPaint);
        mPaint.setXfermode(null);
        canvas.restoreToCount(layerID);
    }

    // create a bitmap with a circle, used for the "dst" image
    static Bitmap makeDst(int w, int h) {
        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFFFFCC44);
        c.drawOval(new RectF(0, 0, w, h), p);
        return bm;
    }
    // create a bitmap with a rect, used for the "src" image
    static Bitmap makeSrc(int w, int h) {
        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFF66AAFF);
        c.drawRect(0, 0, w, h, p);
        return bm;
    }

}

 

PorterDuff.Mode

public class TestPaintView extends View {
    private final Bitmap srcBmp;//源圖像
    private final Bitmap dstBmp;//目標圖像
    private final Paint mPaint;
    private PorterDuff.Mode mode = PorterDuff.Mode.SCREEN;
    private final Paint paint2;

    public TestPaintView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        srcBmp = makeSrc(400, 400);
        dstBmp = makeDst(400, 400);
        paint2 = new Paint();
        paint2.setColor(Color.YELLOW);
        paint2.setStyle(Paint.Style.STROKE);
        paint2.setDither(true);
        paint2.setStrokeWidth(1);
        paint2.setTextSize(100);
        paint2.setAntiAlias(true);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int layerID = canvas.saveLayer(0,0,800,800,mPaint,Canvas.ALL_SAVE_FLAG);
        paint2.setColor(Color.GREEN);
        paint2.setStyle(Paint.Style.STROKE);
        canvas.drawRect(100-1f,0f,501f,402f,paint2);
        canvas.drawBitmap(dstBmp, 100, 1, null);
        mPaint.setXfermode(new PorterDuffXfermode(mode));
        canvas.drawBitmap(srcBmp,100,1, mPaint);
        mPaint.setXfermode(null);
        canvas.restoreToCount(layerID);
        paint2.setColor(Color.RED);
        paint2.setStyle(Paint.Style.FILL);
        canvas.drawText(mode.name(),50,350,paint2);

    }
    static Bitmap makeDst(int w, int h) {
        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFFE81E63);
        c.drawOval(new RectF(w/4, h/4, w/4+w/2, h/4+h/2), p);
        return bm;
    }
    // create a bitmap with a rect, used for the "src" image
    static Bitmap makeSrc(int w, int h) {
        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(0xFF2195F2);
        c.drawRect(0, h/2, w/2, h, p);
        return bm;
    }

    public void setPorterDuffXfermode(PorterDuff.Mode mode){
        this.mode = mode;
        postInvalidate();
    }
}

//setMaskFilter(MaskFilter maskfilter);
//設置MaskFilter,可以用不同的MaskFilter實現濾鏡的效果,如濾化,立體等
//MaskFilter的兩個子類BlurMaskFilter和EmbossMaskFilter
mPaint.setColor(Color.RED);
setLayerType(LAYER_TYPE_SOFTWARE,null);//關閉硬件加速
//第一個參數:radius很容易理解,值越大我們的陰影越擴散,用過PS的人會很容易理解,其實就是陰影範圍。
//第二個參數:style表示的是模糊的類型 SOLID,NORMAL,OUTER和INNER
mPaint.setMaskFilter(new BlurMaskFilter(20,BlurMaskFilter.Blur.SOLID));//這個方法已經被標註爲過時的方法了,如果你的應用啓用了硬件加速,你是看不到任何陰影效果的。
canvas.drawRect(200,200,600,600,mPaint);

setColorFilter(ColorFilter colorfilter);   
設置顏色過濾器,可以在繪製顏色時實現不用顏色的變換效果

setShader(Shader shader);   
設置圖像效果,使用Shader可以繪製出各種漸變效果 

Shader 子類 BitmapShader,ComposeShader,LinearGradient,RadialGradient,SweepGradient

BitmapShader

BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)

  • 第一個參數:要處理的bitmap對象
  • 第二個參數:在X軸處理的效果,Shader.TileMode裏有三種模式:CLAMP、MIRROR和REPETA
  • 第三個參數:在Y軸處理的效果,Shader.TileMode裏有三種模式:CLAMP、MIRROR和REPETA
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.mv);
// 設置shader
mPaint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
// 用設置好的畫筆繪製一個矩形
canvas.drawRect(0, 0, 800, 800, mPaint);

Shader.TileMode.CLAMP 會將邊沿一個像素進行拉伸、擴展。

Shader.TileMode.MIRROR 鏡像

Shader.TileMode.REPEAT 重複模式

mPaint.setAntiAlias(true);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.mv);
// 設置shader
mPaint.setShader(new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
canvas.drawCircle(400, 400, 300, mPaint);

LinearGradient

它就是一個線性漸變的處理類,有兩個構造方法

public LinearGradient (float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)

(x0,y0)表示漸變的起點座標而(x1,y1)則表示漸變的終點座標 而color0和color1則表示起點的顏色和終點的顏色。TileMode和上面講的完全一致

public LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile)

座標都是一樣的,但這裏的colors和positions都是數組,也就是說我們可以傳入多個顏色和顏色的位置,產生更加豐富的漸變效果

測試第一個構造方法

Shader shader = new LinearGradient(0, 0, 200, 200, Color.RED, Color.YELLOW, Shader.TileMode.REPEAT);
// 設置shader
mPaint.setShader(shader);  
canvas.drawRect(0, 0, 600, 600, mPaint);

測試第二個構造方法

Shader shader = new LinearGradient(0, 0, 200, 200,
                new int[] { Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE },
                new float[] { 0, 0.1F, 0.5F, 0.7F, 0.8F }, Shader.TileMode.REPEAT);
mPaint.setShader(shader);
canvas.drawRect(0, 0, 600, 600, mPaint);

SweepGradient

它的意思是梯度漸變,也稱之爲掃描式漸變,因爲其效果有點類似雷達的掃描效果,他也有兩個構造方法

第一個

SweepGradient(float cx, float cy, int color0, int color1)  

參數(cx,cy)是遠行的座標,產生從color0到color1的漸變

mPaint.setAntiAlias(true);
Shader shader = new SweepGradient(300,300,Color.GREEN,Color.RED);
mPaint.setShader(shader);
canvas.drawCircle(300, 300, 300, mPaint);

第二個

SweepGradient(float cx, float cy, int[] colors, float[] positions)  

mPaint.setAntiAlias(true);
Shader shader = new SweepGradient(300,300,new int[]{Color.GREEN,Color.RED,Color.YELLOW},new float[]{0.1f,0.5f,0.8f});
mPaint.setShader(shader);
canvas.drawCircle(300, 300, 300, mPaint);

RadialGradient

徑向漸變,徑向漸變說的簡單點就是個圓形中心向四周漸變的效果,他也一樣有兩個構造方法

第一個

RadialGradient (float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode) 

(centerX,centerY)是圓心的座標,radius是半徑,centerColor是邊緣的顏色,edgeColor是外圍的顏色,最後是模式

mPaint.setAntiAlias(true);
Shader shader = new RadialGradient(300,300,200,Color.RED,Color.GREEN,Shader.TileMode.REPEAT);
mPaint.setShader(shader);
canvas.drawCircle(300, 300, 300, mPaint);

第二個

RadialGradient (float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode) 

這個就是添加了多個色彩,設置色彩的位置

mPaint.setAntiAlias(true);
Shader shader = new RadialGradient(300,300,200,new int[]{Color.RED,Color.GREEN,Color.YELLOW},new float[]{0.2f,0.5f,0.8f},Shader.TileMode.REPEAT);
mPaint.setShader(shader);
canvas.drawCircle(300, 300, 300, mPaint);

ComposeShader

就是組合Shader的意思,顧名思義就是兩個Shader組合在一起作爲一個新Shader,它有兩個構造方法:

ComposeShader (Shader shaderA, Shader shaderB, Xfermode mode)  

ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode)  

兩個都差不多的,只不過一個指定了只能用PorterDuff的混合模式而另一個只要是Xfermode下的混合模式都沒問題

mPaint.setAntiAlias(true);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.mv);
Shader shader01 = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
Shader shader02 = new LinearGradient(0, 0, 0, 100, new int[] {
Color.WHITE, Color.LTGRAY, Color.TRANSPARENT, Color.GREEN }, null,Shader.TileMode.MIRROR);
// 設置shader
mPaint.setShader(new ComposeShader(shader01, shader02, PorterDuff.Mode.MULTIPLY));
canvas.drawCircle(300, 300, 300, mPaint);

setShadowLayer(float radius ,float dx,float dy,int color)

在圖形下面設置陰影層,產生陰影效果,radius爲陰影的角度,dx和dy爲陰影在x軸和y軸上的距離,color爲陰影的顏色  

mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setTextSize(50);
mPaint.setColor(Color.BLACK);
mPaint.setShadowLayer(5,3,3,Color.RED);
canvas.drawText("塗文遠",0,100,mPaint);

負責獲取文字相關

float getFontSpacing() 
                獲取字符行間距。
                float getLetterSpacing() 
                void setLetterSpacing(float letterSpacing) 
                設置和獲取字符間距
                
                final boolean isUnderlineText() 
                void setUnderlineText(boolean underlineText) 
                是否有下劃線和設置下劃線。
                final boolean isStrikeThruText() 
                void setStrikeThruText(boolean strikeThruText) 
                獲取與設置是否有文本刪除線。
                
                float getTextSize() 
                void setTextSize(float textSize) 
                獲取與設置文字大小,注意:Paint.setTextSize傳入的單位是px,TextView.setTextSize傳入的單位是sp,注意使用時不同分辨率處理問題。
                
                Typeface getTypeface() 
                Typeface setTypeface(Typeface typeface) 
                獲取與設置字體類型。Android默認有四種字體樣式:BOLD(加粗)、BOLD_ITALIC(加粗並傾斜)、ITALIC(傾斜)、NORMAL(正常),我們也可以通過Typeface類來自定義個性化字體。
                
                float getTextSkewX() 
                void setTextSkewX(float skewX) 
                獲取與設置文字傾斜,參數沒有具體範圍,官方推薦值爲-0.25,值爲負則右傾,爲正則左傾,默認值爲0。
                
                Paint.Align getTextAlign() 
                void setTextAlign(Paint.Align align) 
                獲取與設置文本對齊方式,取值爲CENTER、LEFT、RIGHT,也就是文字繪製是左邊對齊、右邊還是局中的。

                setSubpixelText(boolean subpixelText)
                固定的幾個範圍:320*480,480*800,720*1280,1080*1920等等;那麼如何在同樣的分辨率的顯示器中增強顯示清晰度呢?
                亞像素的概念就油然而生了,亞像素就是把兩個相鄰的兩個像素之間的距離再細分,再插入一些像素,這些通過程序加入的像素就是亞像素。在兩個像素間插入的像素個數是通過程序計算出來的,一般是插入兩個、三個或四個。
                所以打開亞像素顯示,是可以在增強文本顯示清晰度的,但由於插入亞像素是通過程序計算而來的,所以會耗費一定的計算機性能。
                
                int breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth) 
                比如文本閱讀器的翻頁效果,我們需要在翻頁的時候動態折斷或生成一行字符串,這就派上用場了~

                
                
                計算指定參數長度能顯示多少個字符,同時可以獲取指定參數下可顯示字符的真實長度,譬如:
                
                private static final String STR = "動腦ABCDEF";
                mPaint.setTextSize(50);
                float[] value = new float[1];
                int ret = mPaint.breakText(STR, true, 200, value);
                Log.i("YYYY", "breakText="+ret+", STR="+STR.length()+", value="+value[1]);
                //breakText=5, STR=8, value=195.0

                void getTextBounds(char[] text, int index, int count, Rect bounds) 
                void getTextBounds(String text, int start, int end, Rect bounds) 
                獲取文本的寬高,通過bounds的Rect拿到整型。

                float measureText(String text) 
                float measureText(CharSequence text, int start, int end) 
                float measureText(String text, int start, int end) 
                float measureText(char[] text, int index, int count) 
                粗略獲取文本的寬度,和上面的getTextBounds比較類似,返回浮點數。

                int getTextWidths(String text, int start, int end, float[] widths) 
                int getTextWidths(String text, float[] widths) 
                int getTextWidths(CharSequence text, int start, int end, float[] widths) 
                int getTextWidths(char[] text, int index, int count, float[] widths) 
                精確計算文字寬度,與上面兩個類似。

Android 文字基線(BaseLine)算法

String text = "塗文遠TWYtwy abcd";
int centery = 300;
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setTextSize(100);
mPaint.setColor(Color.RED);

paint2.reset();
paint2.setColor(Color.GREEN);
paint2.setAntiAlias(true);
canvas.drawLine(0,centery,1000,centery,paint2);//中心線

Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
int baseliney = centery+(fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.bottom;
canvas.drawLine(0,baseliney,1000,baseliney,paint2);//基線
canvas.drawText(text,0,baseliney,mPaint);

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章