Android項目刮刮獎詳解(二)
前言
上一期我們已經實現了一個簡易的刮刮卡功能,這一期我們來將其完善一下
目標
- 將刮刮獎的寬高改為合適高度
- 將刮刮獎位置置中
將資訊層的圖片換成文字(重點)
實現
將刮刮獎的寬高改為合適高度和將刮刮獎位置置中
這裡其實很簡單,我們直接到layout布局之中將大小修改一下即可,同時,在布局中利用gravity
修改位置
<?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
方法參數
drawText(String text, float x, floaty, Paint paint);
text即使要寫的文字內容,x,y是寫的位置,需要注意的是,這裡的x,y座標並不是文字的左上方,而是一個與左下角比較接近的位置。大概在這裡:
最後一個參數就是畫筆了,這個畫筆設定與之前相似,待會再補充一下
我們想要把文字寫在資訊層的正中間,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; }}