最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android通過自定義view實現(xiàn)刮刮樂效果詳解

 更新時間:2022年03月29日 08:55:33   作者:吐爾洪江Coding  
這篇文章主要介紹了如何在Android中利用自定義的view實現(xiàn)刮刮樂的效果,文中的示例代碼講解詳細,感興趣的小伙伴可以跟上小編一起動手試一試

前言

已經有兩個月沒有更新博客了,其實這篇文章我早在兩個月前就寫好了,一直保存在草稿箱里沒有發(fā)布出來。原因是有一些原理性的東西還沒了解清楚,最近抽時間研究了一下混合模式,終于也理解了刮刮樂是怎么實現(xiàn)的,所以想繼續(xù)分享一下自己的一些心得,先上效果圖。

效果圖:

實現(xiàn)原理

其實刮刮樂實現(xiàn)原理也不算很復雜,最關鍵的還是需要了解Paint的混合模式。因為刮刮樂是由兩個bitmap組成的,一個是源圖另一個是目標圖,我們需要把目標圖的顏色改成灰色,在源圖上面蓋上了一張灰色的目標圖。當手指滑動屏幕時paint會在新的canvas上畫出路徑,由于新的canvas會持有一個新的bitmap,最終兩個bitmap的像素點重疊時就顯示源圖的部分,從而實現(xiàn)了刮刮樂的效果。這里用的是混合模式中的PorterDuff.Mode.DST_IN。

關鍵代碼:

pathPaint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.DST_IN)));

關鍵步驟

創(chuàng)建bitmap

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmapBackground = getBitmap(mBitmapBackground, w, h);
        mBitmapFront = Bitmap.createBitmap(mBitmapBackground.getWidth(),
                mBitmapBackground.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas.setBitmap(mBitmapFront);
        drawText(mCanvas, w, h);
    }

onSizeChanged方法里面創(chuàng)建了兩個bitmap,一個是背景圖,另一個是覆蓋在背景圖上面的bitmap。然后是在上面的bitmap上面繪制文字。

繪制文字

    private void drawText(Canvas canvas, int mWidth, int mHeight) {
        String text = "趕緊刮開吧";
        canvas.drawColor(Color.GRAY);
        Paint.FontMetrics fm = mPaintText.getFontMetrics();
        int mTxtWidth = (int) mPaintText.measureText(text, 0, text.length());
        int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);
        int x = mWidth / 2 - mTxtWidth / 2; //文字在畫布中的x坐標
        int y = mHeight / 2 + mTxtHeight / 4; //文字在畫布中的y坐標
        canvas.drawText(text, x, y, mPaintText);
    }

調用canvas的drawText方法繪制文字,x,y是文字中心位置的坐標。測量文字寬高有兩種方式,這里用的是更精確的getFontMetrics方法。

畫路徑

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path.reset();
                path.moveTo(event.getX(), event.getY());//原點移動至手指的觸摸點
                break;
            case MotionEvent.ACTION_MOVE:
                path.lineTo(event.getX(), event.getY());
                break;
        }
        mCanvas.drawPath(path, pathPaint);
        invalidate();
        return true;
    }

最終效果圖

完整代碼

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
 
import androidx.annotation.Nullable;
 
import com.example.androidprogressbar.R;
 
public class ScratchCard extends View {
 
    private Bitmap mBitmapBackground;
    private Bitmap mBitmapFront;
    private Canvas mCanvas;
    private Paint pathPaint;
    private Path path;
    private Paint mPaintText;
 
    public ScratchCard(Context context) {
        super(context);
        init();
    }
 
    public ScratchCard(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }
 
    public ScratchCard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
 
    private void init() {
        pathPaint = new Paint();
        pathPaint.setAlpha(0);
        pathPaint.setStyle(Paint.Style.STROKE);
        pathPaint.setStrokeWidth(70);
        pathPaint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.DST_IN)));//混合模式
        pathPaint.setStrokeJoin(Paint.Join.ROUND);//線段之間連接處的樣式
        pathPaint.setStrokeCap(Paint.Cap.ROUND);//設置畫筆的線冒樣式
        path = new Path();
        mBitmapBackground = BitmapFactory.decodeResource(getResources(), R.drawable.card);
        mCanvas = new Canvas();
        mPaintText = new Paint();
        mPaintText.setColor(Color.WHITE);
        mPaintText.setTextSize(100);
        mPaintText.setStrokeWidth(20);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBitmapBackground, 0, 0, null);
        canvas.drawBitmap(mBitmapFront, 0, 0, null);
    }
 
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmapBackground = getBitmap(mBitmapBackground, w, h);
        mBitmapFront = Bitmap.createBitmap(mBitmapBackground.getWidth(),
                mBitmapBackground.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas.setBitmap(mBitmapFront);
        drawText(mCanvas, w, h);
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path.reset();
                path.moveTo(event.getX(), event.getY());//原點移動至手指的觸摸點
                break;
            case MotionEvent.ACTION_MOVE:
                path.lineTo(event.getX(), event.getY());
                break;
        }
        mCanvas.drawPath(path, pathPaint);
        invalidate();
        return true;
    }
 
    private void drawText(Canvas canvas, int mWidth, int mHeight) {
        String text = "趕緊刮開吧";
        canvas.drawColor(Color.GRAY);
        Paint.FontMetrics fm = mPaintText.getFontMetrics();
        int mTxtWidth = (int) mPaintText.measureText(text, 0, text.length());
        int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);
        int x = mWidth / 2 - mTxtWidth / 2; //文字在畫布中的x坐標
        int y = mHeight / 2 + mTxtHeight / 4; //文字在畫布中的y坐標
        canvas.drawText(text, x, y, mPaintText);
    }
 
    public Bitmap getBitmap(Bitmap bm, int newWidth, int newHeight) {
        // 獲得圖片的寬高
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 計算縮放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 取得想要縮放的matrix參數
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 得到新的圖片
        Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
        return newbm;
    }
 
}

以上就是Android通過自定義view實現(xiàn)刮刮樂效果詳解的詳細內容,更多關于Android刮刮樂的資料請關注腳本之家其它相關文章!

相關文章

  • Android數據持久化之ContentProvider機制詳解

    Android數據持久化之ContentProvider機制詳解

    這篇文章主要介紹了Android數據持久化之ContentProvider機制,結合實例形式分析了ContentProvider機制的原理與相關使用技巧,需要的朋友可以參考下
    2017-05-05
  • Android解析服務器端發(fā)來的xml數據示例

    Android解析服務器端發(fā)來的xml數據示例

    Android跟服務器交互數據,有時數據量大時,就需要以xml形式的交互數據,下面與大家分享下使用XmlPullParser來解析xml數據,感興趣的朋友可以參考下哈
    2013-06-06
  • Android自定義下拉刷新控件RefreshableView

    Android自定義下拉刷新控件RefreshableView

    這篇文章主要介紹了Android自定義下拉刷新控件RefreshableView,支持所有控件的下拉刷新,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • loadavg數據異常引發(fā)問題起源分析

    loadavg數據異常引發(fā)問題起源分析

    這篇文章主要為大家介紹了loadavg數據異常引發(fā)問題起源分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • Android端使用Modbus協(xié)議的簡單方法

    Android端使用Modbus協(xié)議的簡單方法

    Modbus協(xié)議是全球第一個用于工業(yè)現(xiàn)場的總線協(xié)議,與外設交互可以采用串口通信,tcp等方式,這篇文章主要給大家介紹了關于Android端使用Modbus協(xié)議的簡單方法,需要的朋友可以參考下
    2021-11-11
  • 使用Android WebSocket實現(xiàn)即時通訊功能

    使用Android WebSocket實現(xiàn)即時通訊功能

    即時通訊(Instant Messaging)最重要的毫無疑問就是即時,不能有明顯的延遲,要實現(xiàn)IM的功能其實并不難,目前有很多第三方,比如極光的JMessage,都比較容易實現(xiàn)。本文通過實例代碼給大家分享Android WebSocket實現(xiàn)即時通訊功能,一起看看吧
    2019-10-10
  • Android自定義ImageView實現(xiàn)圓角功能

    Android自定義ImageView實現(xiàn)圓角功能

    這篇文章主要為大家詳細介紹了Android自定義ImageView實現(xiàn)圓角功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Jetpack Compose自定義動畫與Animatable詳解

    Jetpack Compose自定義動畫與Animatable詳解

    在今年的Google/IO大會上,亮相了一個全新的 Android 原生 UI 開發(fā)框架-Jetpack Compose, 與蘋果的SwiftIUI一樣,Jetpack Compose是一個聲明式的UI框架,這篇文章主要介紹了Jetpack Compose自定義動畫與Animatable
    2022-10-10
  • Android實現(xiàn)短信驗證碼自動填寫功能

    Android實現(xiàn)短信驗證碼自動填寫功能

    這篇文章主要介紹了Android實現(xiàn)短信驗證碼自動填寫功能,感興趣的小伙伴們可以參考一下
    2015-12-12
  • flutter showModalBottomSheet常用屬性及說明

    flutter showModalBottomSheet常用屬性及說明

    這篇文章主要介紹了flutter showModalBottomSheet常用屬性及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09

最新評論

英山县| 河东区| 永嘉县| 册亨县| 平山县| 开化县| 婺源县| 昆山市| 柯坪县| 台前县| 托克托县| 蒙城县| 岳西县| 靖安县| 万年县| 互助| 吉首市| 万荣县| 曲阜市| 麻阳| 金门县| 宜州市| 辽源市| 衡阳县| 凌海市| 浙江省| 中西区| 新邵县| 革吉县| 香港| 辽阳市| 中阳县| 全南县| 南部县| 班玛县| 庆安县| 南丹县| 鄂伦春自治旗| 武邑县| 博野县| 于田县|