項目需求討論:截圖—塗鴉—分享

你們好,又到了新的一期項目需求分析。臺下的觀衆舉起手,讓我看到大家。javascript

同時我已經上傳該項目:截屏及仿支付寶塗鴉功能

歡迎各位點個star哦。(⊙o⊙)
java


開始秋名山飄移之路

這個也是具體項目中遇到的項目需求:須要在一個特定的界面中(都是圖表和各類數據,可能需求分享給別人,告訴別人這個數據怎麼怎麼,這個圖表怎麼怎麼)
因此給咱們開發的需求就是:android

  1. 對該界面進行截屏
  2. 截屏後跳到塗鴉界面,可能某個數據圈出來,讓別人一看就知道。(塗鴉,橡皮擦,撤銷,清空操做)
  3. 分享給QQ,微信等等其餘第三方軟件。

功能上來講,其實沒啥難度。各類第三方的,別人寫好的塗鴉封裝包也有不少。可是要麼是不能隨意定製化,要麼就是寫的也不是特別好,並且我更加提倡的是技術自己不是特別好的各位同僚們,仍是寧肯下載下來觀看,而後本身試着去寫一下,寫一個本身的工具。可能寫的沒別人好,可能有點重複造輪子的意思,可是對於本身的提高仍是很大的。固然你們能夠提出意見。我寫的也不見得很好。。(大牛請忽略這段話。哈哈)git

具體步驟

1.界面截屏功能

由於當前我作的是截屏後把得到的Bitmap保存爲本地圖片,而後跳轉到塗鴉界面,而後打開這個本地圖片進行塗鴉處理。其餘人能夠根據本身的需求對這個截屏獲取的Bitmap進行處理。github

/** * 截屏並將圖片保存到相應路徑下 * @param activity 當前須要截屏的activity * @param path 圖片保存路徑 */
public static void SaveScreenShot(Activity activity,String path) {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bitmap = view.getDrawingCache();

    FileOutputStream outputStream = null;
    try {
        outputStream = new FileOutputStream(path);
        bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }finally {
        if(outputStream != null){
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        view.setDrawingCacheEnabled(false);
    }
}複製代碼

核心的代碼就是:canvas

View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
view.setDrawingCacheEnabled(false);複製代碼

2.塗鴉功能

核心的概念就是:自定義View(畫板),而後在上面先畫上咱們截屏的圖片,而後再在上面畫上一層圖片,咱們的塗鴉其實也就是在上面一層圖片畫來畫去。一臉懵逼?? 必定要逼我換個通俗易懂的???微信

好比畫板是一個桌子,咱們先在上面放了一個海報,而後咱們再拿一個透明的圖片(這裏好比咱們拿的是一塊透明玻璃)蓋在海報上面,而後咱們拿個粉筆在玻璃上面畫來畫去,這時候來咱們看來,是否是就等於海報被塗了各類顏色。好比咱們要清空塗鴉。是否是隻要把玻璃上面的塗鴉給擦光就好了。而後下面的海報就又變成了原來的樣子。app

因此咱們這個塗鴉也要一步步來處理,由於在實際開發中會遇到各類問題,因此要一步步來。ide


如何把截圖的圖片,按照咱們自定義的View(畫板)的大小,等比例放進去。

可能有人要問了。爲啥要等比例放進去,咱們就直接把圖片塞進去咱們的畫板不就OK了嗎。
由於咱們此次是全屏截圖!!!而咱們的畫板確定是比全屏的截圖面積要小,由於下面有畫筆、橡皮擦等其餘功能菜單區域。
看效果(我故意把個人塗鴉畫板的高度設置小不少):
工具

所要截圖的界面

截圖不作調整直接放入

截圖作了調整放入

這下你們懂了吧

OK,咱們接下去就知道了。若是咱們要在自定義的View(畫板)上先放上去截圖的圖片,就要先把圖片按比例處理好再放入。因此也就是說這個圖片須要根據咱們的畫板的面積來作相應調整。

也有可能有人要問,若是個人需求不是截屏塗鴉,是打開內置的某個圖片,而後畫板反而比個人圖片大怎麼辦
。不要緊。這裏教大家一招。不用在乎圖片跟畫板哪一個大哪一個小。

1.獲取圖片的寬和高:bitmapWidth,bitmapHeight
2.獲取畫板的寬和高:boardWidth,boardHeight
3.若是bitmapWidth > boardWidth或者 bitmapHeight > boardHeight,則把圖片縮小比例,來適應畫板
4.不然就設置畫板控件的寬和高等於圖片的寬和高。既讓boardWidth = bitmapWidth,boardHeight = bitmapHeight。咱們反過來讓畫板來適應圖片便可。

/** * * 圖片過大則根據容器把原始圖片改變大小。從而適應容器。 * 不然改變畫板大小適應圖片 * * @param bitmap * @param boardView * @return */
public static Bitmap resizeBitmap(Bitmap bitmap, View boardView) {

    int bitmapHeight = bitmap.getHeight();
    int bitmapWidth = bitmap.getWidth();
    int boardHeight = boardView.getHeight();
    int boardWidth = boardView.getWidth();

    float scale = 1f;
    if(bitmapHeight > boardHeight || bitmapWidth > boardWidth){
        scale = bitmapHeight > bitmapWidth
                ? boardHeight / (bitmapHeight * 1f)
                : boardWidth / (bitmapWidth * 1f);
    }

    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale);
    Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, false);

    ViewGroup.LayoutParams params = boardView.getLayoutParams();
    params.height = resizeBitmap.getHeight();
    params.width = resizeBitmap.getWidth();
    boardView .setLayoutParams(params);

    return resizeBitmap;
}複製代碼

添加第二層Canvas。用於塗鴉

咱們上面拿到了截圖的Bitmap,咱們畫上去後,還要畫一層用於塗鴉的Bitmap,也就是我前面舉例的那塊透明玻璃。
也很簡單。咱們只要再新建一個Bitmap,大小等同於畫板的大小,而後用Canvas包裹,讓這個Bitmap可以具備畫畫的功能,
而後再把這個新的Bitmap讓咱們的畫板畫出來就能夠了。
咱們在自定義View 中寫入一個方法:

/** * 設置背景圖片及監理新的用來塗鴉的Bitmap * * @param bitmap 傳入的截圖界面圖片 */
public void setBackgroud(Bitmap bitmap) {
    this.backgroudBitmap = bitmap;
    this.bitmap = Bitmap.createBitmap(backgroudBitmap.getWidth(), backgroudBitmap.getHeight(), Bitmap.Config.ARGB_8888);
    paintCanvas = new Canvas(this.bitmap);
}複製代碼

這樣咱們把第一步處理好的截圖圖片傳進來的時候。同時建一個和這個截圖圖片同樣大小的圖片,而且用Canvas包裹。這樣等會咱們就能夠用這個paintCanvas在新的圖片上面進行畫畫了。

咱們在onDraw方法中也只要畫這二個Bitmap就能夠了。

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (backgroudBitmap != null && !backgroudBitmap.isRecycled()) {
        canvas.drawBitmap(backgroudBitmap, 0, 0, null);
    }

    if (bitmap != null && !bitmap.isRecycled()) {
        canvas.drawBitmap(bitmap, 0, 0, null);
    }
}複製代碼

真正的塗鴉實現

真正的塗鴉功能,其實只是對咱們的後面新建的Bitmap進行各類操做,也就是用上面的paintCanvas來進行畫線等操做。

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startX = event.getX();
            startY = event.getY();

            path = new Path();
            path.moveTo(startX, startY);

            break;

        case MotionEvent.ACTION_MOVE:
            endX = event.getX();
            endY = event.getY();
            path.quadTo(startX, startY, endX, endY);
            paintCanvas.drawPath(path, isEraser ? eraserPaint : paint);
            startX = endX;
            startY = endY;
            postInvalidate();
            break;

        case MotionEvent.ACTION_UP:
            drawPathList.add(new DrawPathEntry(path, isEraser ? eraserPaint.getColor() : paint.getColor(), isEraser));
            break;

        default:
            break;
    }
    return true;
}複製代碼

切換塗鴉顏色功能

其實用不一樣顏色畫筆來畫,就是單純的切換Paint的顏色值便可。

/** * 設置畫筆顏色及橡皮擦 * * @param type */
public void setPaintType(int type) {

    isEraser = false;
    switch (type) {
        case AnnotationConfig.PaintType.Paint_Red:
            paint.setColor(ContextCompat.getColor(context, R.color.red_radio));
            break;
        case AnnotationConfig.PaintType.Paint_Orange:
            paint.setColor(ContextCompat.getColor(context, R.color.orange_radio));
            break;
        case AnnotationConfig.PaintType.Paint_Yellow:
            paint.setColor(ContextCompat.getColor(context, R.color.yellow_radio));
            break;
        case AnnotationConfig.PaintType.Paint_Green:
            paint.setColor(ContextCompat.getColor(context, R.color.green_radio));
            break;
        case AnnotationConfig.PaintType.Paint_Blue:
            paint.setColor(ContextCompat.getColor(context, R.color.blue_radio));
            break;
        case AnnotationConfig.PaintType.Paint_Purple:
            paint.setColor(ContextCompat.getColor(context, R.color.purple_radio));
            break;
        case AnnotationConfig.PaintType.Paint_Eraser:
            isEraser = true;
            break;
        default:
            break;
    }
}複製代碼

橡皮擦功能

其實橡皮擦功能,你能夠理解就是在畫一個透明的線,這個線蓋在了你的其餘的畫好的線的上面。咱們的目標就是他們二個交集的地方,讓本來的線消失。
下表就是二個線交集的時候,不一樣Mode下呈現的狀況。咱們這裏就能夠用Clear模式。交集的地方,讓底下的顏色消失就能夠。

Xfermode

設置橡皮擦的Paint的Xfermode模式爲Mode.Clear。

Xfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
eraserPaint.setXfermode(xfermode);複製代碼

而後讓這個earserPaint按照上面塗鴉的寫法,讓它畫線就能夠。


撤銷功能

撤銷其實也很簡單,就是咱們在畫的時候,把每次畫的Path和所畫這個Path的畫筆顏色保存下來,放在一個List集合裏面,而後每次點撤銷,就把List集合裏面最後一個的Path給去掉,而後把二層Bitmap(也就是那個透明玻璃)清空,再把List裏面的全部的Path按照其對應的畫筆顏色畫出來就能夠了。

/** * 撤銷操做 */
public void cancelPath() {
    if (drawPathList != null && drawPathList.size() <= 0) {
        return;
    }
    drawPathList.remove(drawPathList.size() - 1);
    paintCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    for (DrawPathEntry entry : drawPathList) {
        paint.setColor(entry.getPaintColor());
        paintCanvas.drawPath(entry.getPath(), entry.isEraser() ? eraserPaint : paint);
    }
    postInvalidate();
}複製代碼

清空塗鴉

清空塗鴉就比上面撤銷功能更簡單了。把二層Bitmap(也就是那個透明玻璃)清空,而後把咱們的上面存Path的List給清空,這樣撤銷也就不會出現原來的塗鴉。

/** * 清空塗鴉 */
public void clearScrawlBoard() {
    paintCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    drawPathList.clear();
    postInvalidate();
}複製代碼

返回最終的塗鴉好的圖片

新建一個Canvas。把最終的截圖圖片的bitmap和最終已經塗鴉好的二層Bitmap(透明玻璃)給畫上去,而後獲取最終的合成的Bitmap便可。

/** * @return 返回最終的塗鴉好的圖片 */
public Bitmap getSrawBoardBitmap() {
    Bitmap resultBitmap = Bitmap.createBitmap(backgroudBitmap.getWidth(), backgroudBitmap.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(resultBitmap);
    canvas.drawBitmap(backgroudBitmap, 0, 0, null);
    canvas.drawBitmap(bitmap, 0, 0, null);
    canvas.save();
    return resultBitmap;
}複製代碼

3.圖片分享功能

咱們經過上面的getSrawBoardBitmap()方法得到了最後的合成的圖片。而後分享到微信,QQ等第三方軟件。我這邊用的是友盟分享

友盟分享Android SDK

它只是幫你作了個封裝,而各個第三方的分享都要去其相應的平臺去申請Key。
好比你要分享到微信和QQ,就要分別取申請微信和QQ的key。而後再集成到友盟分享中去,才能使用。

UMImage image = new UMImage(DrawBaseActivity.this, bit);
new ShareAction(DrawBaseActivity.this).withText("hello").withMedia(image)
    .setDisplayList(SHARE_MEDIA.QQ,SHARE_MEDIA.WEIXIN,SHARE_MEDIA.ALIPAY)
    .setCallback(new UMShareListener() {
        @Override
        public void onStart(SHARE_MEDIA share_media) {

        }

        @Override
        public void onResult(SHARE_MEDIA share_media) {
            Toast.makeText(DrawBaseActivity.this, share_media + " 分享成功啦", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onError(SHARE_MEDIA share_media, Throwable throwable) {
            Toast.makeText(DrawBaseActivity.this,share_media + " 分享失敗啦", Toast.LENGTH_SHORT).show();
            if(throwable!=null){
                Log.d("throw","throw:"+throwable.getMessage());
            }
        }

        @Override
        public void onCancel(SHARE_MEDIA share_media) {
            Toast.makeText(DrawBaseActivity.this,share_media + " 分享取消了", Toast.LENGTH_SHORT).show();
            }
    }).open();複製代碼

最終

最後的最後,貼上相應的相關自定義View和塗鴉的所屬的Activity的代碼。你們也能夠去我上面貼的Github地址中取下載demo。更方便查看:截屏及仿支付寶塗鴉功能

ScrawlActivity.java
package com.example.scrawldemo;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.IdRes;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.example.scrawldemo.config.AnnotationConfig;
import com.example.scrawldemo.util.BitmapUtil;
import com.example.scrawldemo.widget.ScrawlBoardView;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class ScrawlActivity extends AppCompatActivity {

    @BindView(R.id.color_group)
    RadioGroup colorGroup;
    @BindView(R.id.board_view)
    ScrawlBoardView boardView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        String path = getIntent().getStringExtra("path");
        final Bitmap bitmap = BitmapFactory.decodeFile(path);


        boardView.post(new Runnable() {
            @Override
            public void run() {
                final Bitmap resizeBitmap = BitmapUtil.resizeBitmap(bitmap,boardView);
                //final Bitmap resizeBitmap = bitmap;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        boardView.setBackgroud(resizeBitmap);
                    }
                });
            }
        });

        colorGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
                switch (checkedId) {
                    case R.id.red_radio:
                        boardView.setPaintType(AnnotationConfig.PaintType.Paint_Red);
                        break;
                    case R.id.orange_radio:
                        boardView.setPaintType(AnnotationConfig.PaintType.Paint_Orange);
                        break;
                    case R.id.yellow_radio:
                        boardView.setPaintType(AnnotationConfig.PaintType.Paint_Yellow);
                        break;
                    case R.id.green_radio:
                        boardView.setPaintType(AnnotationConfig.PaintType.Paint_Green);
                        break;
                    case R.id.blue_radio:
                        boardView.setPaintType(AnnotationConfig.PaintType.Paint_Blue);
                        break;
                    case R.id.purple_radio:
                        boardView.setPaintType(AnnotationConfig.PaintType.Paint_Purple);
                        break;
                    case R.id.eraser_radio:
                        boardView.setPaintType(AnnotationConfig.PaintType.Paint_Eraser);
                        break;
                    default:
                        break;
                }
            }
        });
    }

    @OnClick({R.id.cancel, R.id.rubbish,R.id.finish_btn,R.id.send_btn})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.cancel:
                boardView.cancelPath();
                break;
            case R.id.rubbish:
                boardView.clearScrawlBoard();
                break;
            case R.id.finish_btn:
                finish();
                break;
            case R.id.send_btn:
                Bitmap bitmap = boardView.getSrawBoardBitmap();

                //該處的bitmap是塗鴉好的圖片。
                //該例子中是把塗鴉好的圖片保存到本地
                try {
                    FileOutputStream outputStream = new FileOutputStream(ScrawlActivity.this.getExternalFilesDir(Environment.DIRECTORY_PICTURES)+"/ChintScreenShot.png");
                    bitmap.compress(Bitmap.CompressFormat.PNG,100,outputStream);
                    Toast.makeText(this, "保存到本地成功", Toast.LENGTH_SHORT).show();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }

                //我分享用的是友盟分享。也就是把上面獲取到的bitmap傳入到相應的友盟分享中的方法便可
                /* UMImage image = new UMImage(ScrawlActivity.this, bitmap); new ShareAction(DrawBaseActivity.this).withText("hello").withMedia(image) .setDisplayList(SHARE_MEDIA.QQ,SHARE_MEDIA.WEIXIN,SHARE_MEDIA.ALIPAY) .setCallback(new UMShareListener() { @Override public void onStart(SHARE_MEDIA share_media) { } @Override public void onResult(SHARE_MEDIA share_media) { Toast.makeText(DrawBaseActivity.this, share_media + " 分享成功啦", Toast.LENGTH_SHORT).show(); } @Override public void onError(SHARE_MEDIA share_media, Throwable throwable) { Toast.makeText(DrawBaseActivity.this,share_media + " 分享失敗啦", Toast.LENGTH_SHORT).show(); if(throwable!=null){ Log.d("throw","throw:"+throwable.getMessage()); } } @Override public void onCancel(SHARE_MEDIA share_media) { Toast.makeText(DrawBaseActivity.this,share_media + " 分享取消了", Toast.LENGTH_SHORT).show(); } }).open(); */



                break;

            default:
                break;
        }
    }
}複製代碼
ScrawlBoardView.java
package com.example.scrawldemo.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.example.scrawldemo.R;
import com.example.scrawldemo.bean.DrawPathEntry;
import com.example.scrawldemo.config.AnnotationConfig;

import java.util.ArrayList;
import java.util.List;

/** * Project:AndroidDemo * Author:dyping * Date:2017/4/11 10:36 */

public class ScrawlBoardView extends View {

    Canvas paintCanvas;
    Paint paint, eraserPaint;
    Bitmap bitmap;
    Bitmap backgroudBitmap;

    float startX, startY, endX, endY;

    Context context;

    boolean isEraser;
    List<DrawPathEntry> drawPathList = new ArrayList<>();
    Path path;

    public ScrawlBoardView(Context context) {
        super(context);
    }

    public ScrawlBoardView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setFilterBitmap(true);
        paint.setColor(ContextCompat.getColor(context, R.color.red_radio));
        paint.setStrokeWidth(10);

        eraserPaint = new Paint();
        eraserPaint.setStyle(Paint.Style.STROKE);
        eraserPaint.setStrokeWidth(20);
        eraserPaint.setColor(Color.TRANSPARENT);
        Xfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
        eraserPaint.setXfermode(xfermode);

        this.context = context;
    }

    public ScrawlBoardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (backgroudBitmap != null && !backgroudBitmap.isRecycled()) {
            canvas.drawBitmap(backgroudBitmap, 0, 0, null);
        }

        if (bitmap != null && !bitmap.isRecycled()) {
            canvas.drawBitmap(bitmap, 0, 0, null);
        }
    }

    /** * 設置背景圖片及監理新的用來塗鴉的Bitmap * * @param bitmap 傳入的截圖界面圖片 */
    public void setBackgroud(Bitmap bitmap) {
        this.backgroudBitmap = bitmap;
        this.bitmap = Bitmap.createBitmap(backgroudBitmap.getWidth(), backgroudBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        paintCanvas = new Canvas(this.bitmap);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                startY = event.getY();

                path = new Path();
                path.moveTo(startX, startY);

                break;

            case MotionEvent.ACTION_MOVE:
                endX = event.getX();
                endY = event.getY();
                path.quadTo(startX, startY, endX, endY);
                paintCanvas.drawPath(path, isEraser ? eraserPaint : paint);
                startX = endX;
                startY = endY;
                postInvalidate();
                break;

            case MotionEvent.ACTION_UP:
                drawPathList.add(new DrawPathEntry(path, isEraser ? eraserPaint.getColor() : paint.getColor(), isEraser));
                break;

            default:
                break;
        }
        return true;
    }

    /** * 設置畫筆顏色及橡皮擦 * * @param type */
    public void setPaintType(int type) {

        isEraser = false;
        switch (type) {
            case AnnotationConfig.PaintType.Paint_Red:
                paint.setColor(ContextCompat.getColor(context, R.color.red_radio));
                break;
            case AnnotationConfig.PaintType.Paint_Orange:
                paint.setColor(ContextCompat.getColor(context, R.color.orange_radio));
                break;
            case AnnotationConfig.PaintType.Paint_Yellow:
                paint.setColor(ContextCompat.getColor(context, R.color.yellow_radio));
                break;
            case AnnotationConfig.PaintType.Paint_Green:
                paint.setColor(ContextCompat.getColor(context, R.color.green_radio));
                break;
            case AnnotationConfig.PaintType.Paint_Blue:
                paint.setColor(ContextCompat.getColor(context, R.color.blue_radio));
                break;
            case AnnotationConfig.PaintType.Paint_Purple:
                paint.setColor(ContextCompat.getColor(context, R.color.purple_radio));
                break;
            case AnnotationConfig.PaintType.Paint_Eraser:
                isEraser = true;
                break;
            default:
                break;
        }
    }

    /** * 撤銷操做 */
    public void cancelPath() {
        if (drawPathList != null && drawPathList.size() <= 0) {
            return;
        }
        drawPathList.remove(drawPathList.size() - 1);
        paintCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        for (DrawPathEntry entry : drawPathList) {
            paint.setColor(entry.getPaintColor());
            paintCanvas.drawPath(entry.getPath(), entry.isEraser() ? eraserPaint : paint);
        }
        postInvalidate();
    }


    /** * 清空塗鴉 */
    public void clearScrawlBoard() {
        paintCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        drawPathList.clear();
        postInvalidate();
    }

    /** * @return 返回最終的塗鴉好的圖片 */
    public Bitmap getSrawBoardBitmap() {
        Bitmap resultBitmap = Bitmap.createBitmap(backgroudBitmap.getWidth(), backgroudBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(resultBitmap);
        canvas.drawBitmap(backgroudBitmap, 0, 0, null);
        canvas.drawBitmap(bitmap, 0, 0, null);
        canvas.save();
        return resultBitmap;
    }

}複製代碼
BitmapUtil.java
package com.example.scrawldemo.util;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.view.View;
import android.view.ViewGroup;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/** * Project:AndroidDemo * Author:dyping * Date:2017/4/11 10:40 */

public class BitmapUtil {

    /** * * 圖片過大則根據容器把原始圖片改變大小。從而適應容器。 * 不然改變畫板大小適應圖片 * * @param bitmap * @param boardView * @return */
    public static Bitmap resizeBitmap(Bitmap bitmap, View boardView) {

        int bitmapHeight = bitmap.getHeight();
        int bitmapWidth = bitmap.getWidth();
        int boardHeight = boardView.getHeight();
        int boardWidth = boardView.getWidth();

        float scale = 1f;
        if(bitmapHeight > boardHeight || bitmapWidth > boardWidth){
            scale = bitmapHeight > bitmapWidth
                    ? boardHeight / (bitmapHeight * 1f)
                    : boardWidth / (bitmapWidth * 1f);
        }

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);
        Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, false);

        ViewGroup.LayoutParams params = boardView.getLayoutParams();
        params.height = resizeBitmap.getHeight();
        params.width = resizeBitmap.getWidth();
        boardView .setLayoutParams(params);

        return resizeBitmap;
    }


    /** * 截屏並將圖片保存到相應路徑下 * * @param activity 當前須要截屏的activity * @param path 圖片保存路徑 */
    public static void SaveScreenShot(Activity activity, String path) {
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();

        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(path);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            view.setDrawingCacheEnabled(false);
        }
    }
}複製代碼
相關文章
相關標籤/搜索