Android 繪圖工具與實戰(具體例子)

繪圖工具與實戰

參考鏈接:https://www.runoob.com/w3cnote/android-tutorial-drawable-tool.html
三大繪圖工具:

1)Paint(畫筆):
就是畫筆,用於設置繪製風格,如:線寬(筆觸粗細),顏色,透明度和填充風格等 直接使用無參構造方法就可以創建Paint實例: Paint paint = new Paint( );

我們可以通過下述方法來設置Paint(畫筆)的相關屬性,另外,關於這個屬性有兩種, 圖形繪製相關與文本繪製相關:

方法 解釋
setARGB(int a,int r,int g,int b): 設置繪製的顏色,a代表透明度,r,g,b代表顏色值。
setAlpha(int a):
setAntiAlias(boolean aa): 設置是否使用抗鋸齒功能,會消耗較大資源,繪製圖形速度會變慢。
setDither(boolean dither): 設定是否使用圖像抖動處理,會使繪製出來的圖片顏色更加平滑和飽滿,圖像更加清晰
setFilterBitmap(boolean filter): 如果該項設置爲true,則圖像在動畫進行中會濾掉對Bitmap圖像的優化操作, 加快顯示速度,本設置項依賴於dither和xfermode的設置
setMaskFilter(MaskFilter maskfilter): 設置MaskFilter,可以用不同的MaskFilter實現濾鏡的效果,如濾化,立體等
setColorFilter(ColorFilter colorfilter): 設置顏色過濾器,可以在繪製顏色時實現不用顏色的變換效果
setPathEffect(PathEffect effect) 設置繪製路徑的效果,如點畫線等
setShader(Shader shader): 設置圖像效果,使用Shader可以繪製出各種漸變效果
setShadowLayer(float radius ,float dx,float dy,int color): 在圖形下面設置陰影層,產生陰影效果, radius爲陰影的角度,dx和dy爲陰影在x軸和y軸上的距離,color爲陰影的顏色
setStyle(Paint.Style style): 設置畫筆的樣式,爲FILL,FILL_OR_STROKE,或STROKE
setStrokeCap(Paint.Cap cap): 當畫筆樣式爲STROKE或FILL_OR_STROKE時,設置筆刷的圖形樣式, 如圓形樣Cap.ROUND,或方形樣式Cap.SQUARE
setSrokeJoin(Paint.Join join): 設置繪製時各圖形的結合方式,如平滑效果等
setStrokeWidth(float width): 當畫筆樣式爲STROKE或FILL_OR_STROKE時,設置筆刷的粗細度
setXfermode(Xfermode xfermode): 設置圖形重疊時的處理方式,如合併,取交集或並集,經常用來製作橡皮的擦除效果
setFakeBoldText(boolean fakeBoldText): 模擬實現粗體文字,設置在小字體上效果會非常差
setSubpixelText(boolean subpixelText): 設置該項爲true,將有助於文本在LCD屏幕上的顯示效果
setTextAlign(Paint.Align align): 設置繪製文字的對齊方向
setTextScaleX(float scaleX): 設置繪製文字x軸的縮放比例,可以實現文字的拉伸的效果
setTextSize(float textSize): 設置繪製文字的字號大小
setTextSkewX(float skewX): 設置斜體文字,skewX爲傾斜弧度
setTypeface(Typeface typeface): 設置Typeface對象,即字體風格,包括粗體,斜體以及襯線體,非襯線體等
setUnderlineText(boolean underlineText): 設置帶有下劃線的文字效果
setStrikeThruText(boolean strikeThruText): 設置帶有刪除線的效果
setStrokeJoin(Paint.Join join): 設置結合處的樣子,Miter:結合處爲銳角, Round:結合處爲圓弧:BEVEL:結合處爲直線
setStrokeMiter(float miter): 設置畫筆傾斜度
setStrokeCap (Paint.Cap cap): 設置轉彎處的風格 其他常用方法:
float ascent( ): 測量baseline之上至字符最高處的距離
float descent(): baseline之下至字符最低處的距離
int breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth): 檢測一行顯示多少文字
clearShadowLayer( ): 清除陰影層 其他的自行查閱文檔~

2)Canvas(畫布):
畫筆有了,接着就到畫布(Canvas),總不能憑空作畫是吧~常用方法如下:

首先是構造方法,Canvas的構造方法有兩種:

Canvas(): 創建一個空的畫布,可以使用setBitmap()方法來設置繪製具體的畫布。

Canvas(Bitmap bitmap): 以bitmap對象創建一個畫布,將內容都繪製在bitmap上,因此bitmap不得爲null。

接着是 1.drawXXX()方法族:以一定的座標值在當前畫圖區域畫圖,另外圖層會疊加, 即後面繪畫的圖層會覆蓋前面繪畫的圖層。 比如:

方法 解釋
drawRect(RectF rect, Paint paint) : 繪製區域,參數一爲RectF一個區域
drawPath(Path path, Paint paint) : 繪製一個路徑,參數一爲Path路徑對象
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) : 貼圖,參數一就是我們常規的Bitmap對象,參數二是源區域(這裏是bitmap), 參數三是目標區域(應該在canvas的位置和大小),參數四是Paint畫刷對象, 因爲用到了縮放和拉伸的可能,當原始Rect不等於目標Rect時性能將會有大幅損失。
drawLine(float startX, float startY, float stopX, float stopY, Paintpaint) : 畫線,參數一起始點的x軸位置,參數二起始點的y軸位置,參數三終點的x軸水平位置, 參數四y軸垂直位置,最後一個參數爲Paint 畫刷對象。
drawPoint(float x, float y, Paint paint): 畫點,參數一水平x軸,參數二垂直y軸,第三個參數爲Paint對象。
drawText(String text, float x, floaty, Paint paint) : 渲染文本,Canvas類除了上面的還可以描繪文字,參數一是String類型的文本, 參數二x軸,參數三y軸,參數四是Paint對象。
drawOval(RectF oval, Paint paint): 畫橢圓,參數一是掃描區域,參數二爲paint對象;
drawCircle(float cx, float cy, float radius,Paint paint): 繪製圓,參數一是中心點的x軸,參數二是中心點的y軸,參數三是半徑,參數四是paint對象;
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint): 畫弧,參數一是RectF對象,一個矩形區域橢圓形的界限用於定義在形狀、大小、電弧,參數二是起始角 (度)在電弧的開始,參數三掃描角(度)開始順時針測量的,參數四是如果這是真的話,包括橢圓中心的電 弧,並關閉它,如果它是假這將是一個弧線,參數五是Paint對象;

2.clipXXX()方法族:在當前的畫圖區域裁剪(clip)出一個新的畫圖區域,這個畫圖區域就是canvas 對象的當前畫圖區域了。比如:clipRect(new Rect()),那麼該矩形區域就是canvas的當前畫圖區域

3.save()和restore()方法: save( ):用來保存Canvas的狀態。save之後,可以調用Canvas的平移、放縮、旋轉、錯切、裁剪等操作! restore():用來恢復Canvas之前保存的狀態。防止save後對Canvas執行的操作對後續的繪製有影響。 save()和restore()要配對使用(restore可以比save少,但不能多),若restore調用次數比save多,會報錯!

4.translate(float dx, float dy): 平移,將畫布的座標原點向左右方向移動x,向上下方向移動y.canvas的默認位置是在(0,0)

5.scale(float sx, float sy):擴大,x爲水平方向的放大倍數,y爲豎直方向的放大倍數

6.rotate(float degrees):旋轉,angle指旋轉的角度,順時針旋轉

3)Path(路徑)
簡單點說就是描點,連線~在創建好我們的Path路徑後,可以調用Canvas的drawPath(path,paint) 將圖形繪製出來~常用方法如下:

方法 解釋
addArc(RectF oval, float startAngle, float sweepAngle: 爲路徑添加一個多邊形
addCircle(float x, float y, float radius, Path.Direction dir): 給path添加圓圈
addOval(RectF oval, Path.Direction dir) 添加橢圓形
addRect(RectF rect, Path.Direction dir): 添加一個區域
addRoundRect(RectF rect, float[] radii, Path.Direction dir): 添加一個圓角區域
isEmpty(): 判斷路徑是否爲空
transform(Matrix matrix): 應用矩陣變換
transform(Matrix matrix, Path dst): 應用矩陣變換並將結果放到新的路徑中,即第二個參數。

更高級的效果可以使用PathEffect類!

幾個To:

方法 解釋
moveTo(float x, float y): 不會進行繪製,只用於移動移動畫筆
lineTo(float x, float y): 用於直線繪製,默認從(0,0)開始繪製,用moveTo移動! 比如 mPath.lineTo(300, 300); canvas.drawPath(mPath, mPaint);
quadTo(float x1, float y1, float x2, float y2): 用於繪製圓滑曲線,即貝塞爾曲線,同樣可以結合moveTo使用!
rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 同樣是用來實現貝塞爾曲線的。 (x1,y1) 爲控制點,(x2,y2)爲控制點,(x3,y3) 爲結束點。 Same as cubicTo, but the coordinates are considered relative to the current point on this contour.就是多一個控制點而已~ 繪製上述的曲線: mPath.moveTo(100, 500); mPath.cubicTo(100, 500, 300, 100, 600, 500); 如果不加上面的那個moveTo的話:則以(0,0)爲起點,(100,500)和(300,100)爲控制點繪製貝塞爾曲線
arcTo(RectF oval, float startAngle, float sweepAngle): 繪製弧線(實際是截取圓或橢圓的一部分)ovalRectF爲橢圓的矩形,startAngle 爲開始角度, sweepAngle 爲結束角度。

實戰刮刮樂
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/bg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg1"/>

    <ImageView
        android:id="@+id/imgv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/ggl"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="0dp" />

</RelativeLayout>

MainActivity.java

package com.example.scratchcard;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DiscretePathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private ImageView imageView;
    private Bitmap alterBitmap;
    private double nX;
    private double nY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView)findViewById(R.id.imgv);
        //從資源文件中解析一張Bitmap
        final Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ggl);
        alterBitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(),bitmap.getConfig());
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        nX = (double)bitmap.getWidth()/dm.widthPixels;
        nY = (double)bitmap.getHeight() / dm.heightPixels;
        //創建一個Canvas對象
        Canvas canvas = new Canvas(alterBitmap);
        //創建畫筆對象
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);
        //創建Matrix對象
        Matrix matrix = new Matrix();
        canvas.drawBitmap(bitmap,matrix,paint);
        //爲ImageView設置觸摸監聽
        imageView.setOnTouchListener(new View.OnTouchListener(){

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                try{
                    int x = (int)event.getX();
                    int y = (int)event.getY();
                    for (int i = -100;i<100;i++){
                        for (int j=-100;j<100;j++){
                            //將區域內的像素設置透明像素
                            if(Math.sqrt((i*i)+(j*j))<=100){
                                alterBitmap.setPixel((int)(x * nX)+i,(int)(y * nY+90)+j,Color.TRANSPARENT);
                            }
                        }
                    }
                    imageView.setImageBitmap(alterBitmap);
                }catch (Exception e){
                    e.printStackTrace();
                }
                return true;
            }
        });
    }
}

運行截圖:
在這裏插入圖片描述

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