android canvas.drawBitmap(bitmap, matrix, paint) 中 利用 matrix 實現平移到中心點及中心點縮放

南郭竽發表於2018-07-05

大體的實現是,這樣的,在 res/drawable/ 目錄下面放了一張圖片,但是圖片比較大,先根據view 的寬高,對 bitmap 進行等比縮放,縮放到能完全顯示到 view 裡面。(這時候如果直接呼叫canvas.drawBitmap()會把圖片載入在當前view的左上角。) 然後,再通過 matrix 的平移與縮放,讓 圖片 居中顯示在view中,並相對縮小了一點點。

程式碼如下:

public class ClipView extends View {
    private int mWidth;
    private int mHeight;
    private Matrix matrix;
    private Paint paint;
    private Bitmap bitmap;
    private Point center;
    private Point bmpCenter;
    private RectF oval;

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

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

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

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

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.mWidth = w;
        this.mHeight = h;
        matrix = new Matrix();
        paint = new Paint();
        paint.setAntiAlias(true);
        Bitmap temp = BitmapFactory.decodeResource(getResources(), R.drawable.bw);
        int bw = temp.getWidth();
        int bh = temp.getHeight();
        float scale = Math.min(1f * mWidth / bw, 1f * mHeight / bh);
        LogUtils.w("scale==" + scale);
        bitmap = scaleBitmap(temp, scale);
        // compute init left, top
        int bbw = bitmap.getWidth();
        int bbh = bitmap.getHeight();
        center = new Point(mWidth / 2, mHeight / 2);
        bmpCenter = new Point(bbw / 2, bbh / 2);
        matrix.postScale(0.9f, 0.9f, center.x, center.y); // 中心點引數是有用的
        matrix.postTranslate(center.x - bmpCenter.x, center.y - bmpCenter.y); // 移動到當前view 的中心
        oval = new RectF(center.x - bbw / 2, center.y - bbh / 2,
                center.x + bbw / 2, center.y + bbh / 2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(bitmap, matrix, paint);
//        canvas.scale(1.1f,1.1f,center.x,center.y);
//        canvas.drawRect(oval,paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return super.onTouchEvent(event);
    }

    /**
     * 根據給定的寬和高進行拉伸
     *
     * @param origin 原圖
     * @param scale  縮放比例
     * @return new Bitmap
     */
    private Bitmap scaleBitmap(Bitmap origin, float scale) {
        if (origin == null) {
            return null;
        }
        int height = origin.getHeight();
        int width = origin.getWidth();
        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);// 使用後乘
        Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
        if (!origin.isRecycled()) {
            origin.recycle();
        }
        return newBM;
    }
}

佈局檔案裡面是這樣的:

<com.cat.simpleapp20180620.view.ClipView
        android:id="@+id/clip_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="3dp" />

然後效果如下:

這裡寫圖片描述

就是這樣子的,圖片被縮小了,(不是被裁切),然後居中顯示在控制元件的正中心了。

相關文章