繪圖工具與實戰
參考鏈接: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;
}
});
}
}
運行截圖: