Android基礎入門教程——8.3.7 Paint API之—— Xfermode與PorterDuff詳解(四)

來源:互聯網
上載者:User

標籤:android   xfermode   porterduff   dst-out   映像混排   

Android基礎入門教程——8.3.7 Paint API之—— Xfermode與PorterDuff詳解(四)

標籤(空格分隔): Android基礎入門教程

本節引言:

上節我們寫了關於Xfermode與PorterDuff使用的第一個例子:圓角&圓形圖片ImageView的實現,
我們體會到了PorterDuff.Mode.DST_IN給我們帶來的好處,本節我們繼續來寫例子練練手,
還記得Android基礎入門教程——8.3.2 繪圖類實戰樣本給大家帶來的拔掉美女衣服的實現嗎?

當時我們的實現方案是,將手指觸碰地區附近的20*20個像素點設定為透明,是這樣的:

不知道你有沒有發現一個問題,我們擦美女衣服的時候,擦拭的時候都是方塊的,但是我們畫圖板
畫圖的時候,劃線都是很平滑的,有沒有辦法將兩者結合起來,我們擦衣服時也是圓滑的呢?
答案肯定是有的,就是使用Xfermode咯!本節我們使用另一個模式,DST_OUT模式!
在不相交的地方繪製靶心圖表

如果你忘記了某個模式或者連18種模式都沒見過的話,那麼請移步:
Android基礎入門教程——8.3.5 Paint API之—— Xfermode與PorterDuff詳解(二)
另外,還是要貼下PorterDuff.Mode的:

嗯,話不多說,開始本節內容~

1.要實現的以及實現流程分析:

要實現的

嗯,不知道你看了那個Gif圖多少次了呢?不知道圖中是否適合大家的口味,小豬
是從別人的APP上扒下來的,別問我番號或者留郵箱什麼的,我什麼都不知道~找番什麼的,
問群裡的老司機——基神吧,好的,我們來分析下實現流程吧~

  • 我們來說說原理,其實就是兩個Bitmap,一前一後,前面的是穿著衣服的,後面的是沒穿衣服的,
    然後通過一個Path來記錄使用者繪製出來的圖形,然後為我們的畫筆設定DST_OUT的模式,那麼
    與Path重疊部分的DST(靶心圖表),就是穿著衣服的圖,會變成透明!好噠,很簡單!
    我們再慢慢細化!
  • 首先我們需要兩個Bitmap,用來儲存前後兩張圖片,這裡我們讓兩個Bitmap都全屏!
  • 接著設定下畫筆,圓角,筆寬,消除鋸齒等!
  • 再接著定義一個畫Path,即使用者繪製地區的方法,設定Xfermode後畫地區而已!
  • 然後重寫onTouchEvent方法,這部分和之前的自訂畫圖板是一樣的!
  • 最後重寫onDraw()方法,先繪製背景圖片,調用使用者繪製地區的方法,再繪製前景圖片!

可能看上去有點複雜,其實不然,代碼超簡單的說~

2.代碼實現:

直接就一個自訂View——StripMeiZi.java

/** * Created by Jay on 2015/10/25 0025. */public class StripMeiZi extends View{    private Paint mPaint = new Paint();    private Path mPath = new Path();    private Canvas mCanvas;    private Bitmap mBeforeBitmap;    private Bitmap mBackBitmap;    private int mLastX,mLastY;    private int screenW, screenH; //螢幕寬高    private Xfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);    public StripMeiZi(Context context) {        this(context, null);    }    public StripMeiZi(Context context, AttributeSet attrs) {        super(context, attrs);        screenW = ScreenUtil.getScreenW(context);        screenH = ScreenUtil.getScreenH(context);        init();    }    public StripMeiZi(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    private void init() {        //背後圖片,這裡讓它全屏        mBackBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.meizi_back);        mBackBitmap = Bitmap.createScaledBitmap(mBackBitmap, screenW, screenH, false);        //前面的圖片,並繪製到Canvas上        mBeforeBitmap = Bitmap.createBitmap(screenW, screenH, Bitmap.Config.ARGB_8888);        mCanvas = new Canvas(mBeforeBitmap);        mCanvas.drawBitmap(BitmapFactory.decodeResource(getResources(),                R.mipmap.meizi_before), null, new RectF(0, 0, screenW, screenH), null);        //畫筆相關的設定        mPaint.setAntiAlias(true);        mPaint.setDither(true);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeJoin(Paint.Join.ROUND); // 圓角        mPaint.setStrokeCap(Paint.Cap.ROUND); // 圓角        mPaint.setStrokeWidth(80);    // 設定畫筆寬    }    private void drawPath() {        mPaint.setXfermode(mXfermode);        mCanvas.drawPath(mPath, mPaint);    }    @Override    protected void onDraw(Canvas canvas) {        canvas.drawBitmap(mBackBitmap, 0, 0, null);        drawPath();        canvas.drawBitmap(mBeforeBitmap, 0, 0, null);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        int action = event.getAction();        int x = (int) event.getX();        int y = (int) event.getY();        switch (action)        {            case MotionEvent.ACTION_DOWN:                mLastX = x;                mLastY = y;                mPath.moveTo(mLastX, mLastY);                break;            case MotionEvent.ACTION_MOVE:                int dx = Math.abs(x - mLastX);                int dy = Math.abs(y - mLastY);                if (dx > 3 || dy > 3)                    mPath.lineTo(x, y);                mLastX = x;                mLastY = y;                break;        }        invalidate();        return true;    }}

布局代碼activity_main.xml

<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">    <com.jay.xfermodedemo2.StripMeiZi        android:layout_width="match_parent"        android:layout_height="match_parent"/></RelativeLayout>
3.程式碼範例下載:

XfermodeDemo2.zip

本節小結:

好的,本節我們寫了Xfermode與PorterDuff的另一個實戰例子——手撕美女衣服的Demo,相比起我們之前
那種撕美女衣服(讓觸摸點附近20*20的像素點變成透明)的方式斯文多了~代碼也簡單很多是吧,有沒有
體會到Android映像混排Xfermode給我們帶來的好處,或者對於自訂控制項的重要性!嗯,還等什麼,
開啟你的IDE,把代碼擼一遍,嘗嘗手撕美女衣服的快感吧~

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Android基礎入門教程——8.3.7 Paint API之—— Xfermode與PorterDuff詳解(四)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.