上一期咱們已經實現了一個簡易的刮刮卡功能,這一期咱們來將其完善一下android
將信息層的圖片換成文字(重點)canvas
將刮刮獎的寬高改成合適高度和將刮刮獎位置居中app
這裏其實很簡單,咱們直接到layout佈局之中將大小修改一下便可,同時,在佈局中利用gravity
修改位置ide
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" tools:context="com.wan.guajiang.MainActivity"> <com.wan.guajiang.GuaGuaKa android:layout_width="300dp" android:layout_height="100dp"/> </LinearLayout>
將信息層的圖片換成文字佈局
以前咱們信息層繪製的是中獎圖片,若是沒有圖片怎麼辦?固然是直接拿文字來代替啦,canvas不只能夠畫圖片,還能夠畫文字,寫文字測試
首先,咱們來了解一下canvas的drawText
方法參數3d
drawText(String text, float x, floaty, Paint paint);
code
text即便要寫的文字內容,x,y是寫的位置,須要注意的是,這裏的x,y座標並非文字的左上角,而是一個與左下角比較接近的位置。大概在這裏:如圖
最後一個參數就是畫筆了,這個畫筆設置與以前類似,待會再補充一下xml
咱們想要把文字寫在信息層的正中間,x,y的座標該怎麼寫呢?由上圖能夠知道,canvas使用drawText
方法,xy的座標實際上是位於文字的左下角的,下圖即是圖解
相信這張圖仍是很好理解的,咱們繼續,開始寫代碼
首先,咱們須要個文字內容
String message = "恭喜中獎,3萬元!";
定義咱們的畫筆Paint,對其進行相關設置
這裏得提一下,咱們須要一個Rect矩形來獲得文字內容的背景大小,也就是上圖中的紅色矩形,Paint畫筆中提供了一個方法getTextBounds
,咱們能夠經過此方法來得到文字內容的背景大小
messagePaint.getTextBounds(String text,float start,float end,Rect rect);
上述代碼的意思是,截取text文字中的從start到end的長度,將截取的長度和文字的高度造成一個矩形,rect矩形接收這個矩形
Rect mBackground = new Rect();//用來接收getTextBounds返回的矩形 Paint messagePaint = new Paint(); messagePaint.setColor(Color.RED); messagePaint.setAntiAlias(true); messagePaint.setStyle(Paint.Style.STROKE); messagePaint.getTextBounds(message,0,message.length(),mBackground); messagePaint.setTextSize(30);
計算x,y座標,canvas使用drawText寫出文字
咱們有兩種方法來得到以前黑色矩形的長和寬,一種是使用getMeasured
,另外一種使用mBitmap.get
方法來得到長和寬
canvas.drawText(message,getMeasuredWidth()/2-mBackground.width()/2,getMeasuredHeight()/2+mBackground.height()/2,messagePaint);
或者:
canvas.drawText(message,mBitmap.getWidth()/2-mBackground.width()/2,mBitmap.getHeight()/2+mBackground.height()/2,messagePaint);
public class GuajiangView extends View { /** * 繪製線條的Paint,即用戶手指繪製Path */ private Paint mOutterPaint = new Paint(); /** * 記錄用戶繪製的Path */ private Path mPath = new Path(); /** * 內存中建立的Canvas */ private Canvas mCanvas; /** * mCanvas繪製內容在其上 */ private Bitmap mBitmap; private int mLastX; private int mLastY; private String message;//中獎信息 private Rect mBackground;//文字背景矩形大小 private Paint messagePaint = new Paint();//文字畫筆 private boolean isClear = false; public GuajiangView(Context context) { super(context); } public GuajiangView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public GuajiangView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public GuajiangView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.d(TAG, "onMeasure: 測量"); int width = getMeasuredWidth(); int height = getMeasuredHeight(); // 初始化bitmap mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//以得到的寬高建立一個32位的bitmap mCanvas = new Canvas(mBitmap);//以bitmap建立了一個畫布 mCanvas.drawColor(Color.GREEN);//設置畫布的顏色爲綠色 mBackground = new Rect(); message = "恭喜中獎,3萬元!"; messagePaint.setColor(Color.RED); messagePaint.setAntiAlias(true); messagePaint.setStyle(Paint.Style.STROKE); messagePaint.getTextBounds(message,0,message.length(),mBackground); messagePaint.setTextSize(30); // 設置畫筆 mOutterPaint.setColor(Color.BLUE); mOutterPaint.setAntiAlias(true);//使用抗鋸齒功能,會消耗較大資源,繪製圖形速度會變慢 mOutterPaint.setDither(true);//圖像抖動處理,會使繪製出來的圖片顏色更加平滑和飽滿,圖像更加清晰 mOutterPaint.setStyle(Paint.Style.STROKE); mOutterPaint.setStrokeJoin(Paint.Join.ROUND);//圓角,平滑 mOutterPaint.setStrokeCap(Paint.Cap.ROUND); //圓角 mOutterPaint.setStrokeWidth(20); // 設置畫筆寬度 messagePaint.setColor(Color.RED); } @Override protected void onDraw(Canvas canvas) { Log.d(TAG, "onDraw: 畫"); canvas.drawText(message,mBitmap.getWidth()/2-mBackground.width()/2,getMeasuredHeight()/2+mBackground.height()/2,messagePaint); drawPath(); canvas.drawBitmap(mBitmap, 0,0, null); } private void drawPath() { Log.d(TAG, "drawPath: "); mOutterPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); mCanvas.drawPath(mPath, mOutterPaint); } @Override public boolean onTouchEvent(MotionEvent event) { //當手指按到屏幕上的時候,Path路徑之中就使用moveto方法,移動到手指當前位置,invalidate刷新View,回調onDraw方法,(尚未畫出來) //以後,手指移動,action是處於ACTION_MOVE的狀態,Path路徑使用lineto方法(畫直線), // 同時,將x,y座標進行了更新,invalidate刷新View,回調onDraw方法,canvas經過drawpath使用畫筆將path畫了出來,以後若是用戶沒有擡起手指,則繼續循環ACTION_MOVE中的步驟 int action = event.getAction(); int x = (int) event.getX();//得到x座標 int y = (int) event.getY();//得到y座標 switch (action){ case MotionEvent.ACTION_DOWN: mLastX = x; mLastY = y; mPath.moveTo(mLastX, mLastY);//以後回調onDraw方法canvas將path break; case MotionEvent.ACTION_MOVE: mPath.lineTo(x, y);//以後回調onDraw方法時canvas畫直線到(x,y)該點 mLastX = x;//更新x座標 mLastY = y;//更新y座標 break; default:break; } invalidate();//刷新View,回調onDraw方法 Log.d(TAG, "onTouchEvent: invalidate"); return true; } }