自定义控件实现以左上或右下点为标准切割图片的ImageView

目前系统自带的ImageView的scaleType的属性值只有:MATRIX,FIT_XY,FIT_START,FIT_END,FIT_CENTER,CENTER,CENTER_CROP,CENTER_INSIDE.

1.android:scaleType=“center” 
保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size时,多出来的部分被截掉。 


2.android:scaleType=“center_inside” 
以原图正常显示为目的,如果原图大小大于ImageView的size,就按照比例缩小原图的宽高,居中显示在ImageView中。如果原图size小于ImageView的size,则不做处理居中显示图片。 


3.android:scaleType=“center_crop” 
以原图填满ImageView为目的,如果原图size大于ImageView的size,则与center_inside一样,按比例缩小,居中显示在ImageView上。如果原图size小于ImageView的size,则按比例拉升原图的宽和高,填充ImageView居中显示。 


4.android:scaleType=“matrix” 
不改变原图的大小,从ImageView的左上角开始绘制,超出部分做剪切处理。 


5.androd:scaleType=“fit_xy” 
把图片按照指定的大小在ImageView中显示,拉伸显示图片,不保持原比例,填满ImageView. 


6.android:scaleType=“fit_start” 
把原图按照比例放大缩小到ImageView的高度,显示在ImageView的start(前部/上部)。 


7.android:sacleType=“fit_center” 
把原图按照比例放大缩小到ImageView的高度,显示在ImageView的center(中部/居中显示)。 


8.android:scaleType=“fit_end” 
把原图按照比例放大缩小到ImageView的高度,显示在ImageVIew的end(后部/尾部/底部)。

需求要求:

1.需要占满imageview;

2.原图按比例缩放,不能变形;

3.以原图的左上角或者右下角作为基准,截掉多余部分;

综上分析,我们使用android:scaleType=“matrix” 属性来实现自定义;

    private void init() {
        setScaleType(ScaleType.MATRIX);
    }

计算matrix:

/**
     * 计算matrix
     *
     * @param drawable
     */
    public void calculationMatrix(Drawable drawable) {
        if (drawable == null)
            return;
        if (matrix == null) {
            skinDrawable = drawable;
            int dwidth = drawable.getIntrinsicWidth();
            int dheight = drawable.getIntrinsicHeight();

            if (dwidth <= 0 || dheight <= 0 || imgWidth <= 0) {
                super.setImageDrawable(drawable);
                return;
            }
            matrix = new Matrix();           //创建一个单位矩阵
            float scale = (float) imgWidth / (float) dwidth;
            float dy = imgHeight - dheight * scale;
            matrix.setScale(scale, scale);
            if (cropType != TYPE_START_CROP) {
                float dx = 0;
                if (dy > 0) {
                    scale = (float) imgHeight / (float) dheight;
                    dy = 0;
                    dx = imgWidth - dwidth * scale;
                }
                matrix.setScale(scale, scale);
                matrix.postTranslate(Math.round(dx), Math.round(dy));
            }

            setImageMatrix(matrix);       //设置并应用矩阵
        } else {
            setImageMatrix(matrix);       //设置并应用矩阵
        }
    }

注意在ImageView大小改变时重新计算matrix(如某些手机虚拟键收起或弹出):

    @Override
    protected boolean setFrame(int l, int t, int r, int b) {
        SkinImageView.this.imgWidth = r - l;
        SkinImageView.this.imgHeight = b - t;
        matrix = null;
        calculationMatrix(skinDrawable);
        return super.setFrame(l, t, r, b);
    }

最后奉上源码:

package com.migu.android.widget;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.ViewTreeObserver;


public class SkinImageView extends android.support.v7.widget.AppCompatImageView {
    private int imgWidth;
    private int imgHeight;
    private Context context;
    private Matrix matrix;
    public static final int TYPE_START_CROP = 1;
    public static final int TYPE_END_CROP = 0;
    private int cropType = TYPE_END_CROP;
    private Drawable skinDrawable;

    public SkinImageView(Context context) {
        super(context);
        this.context = context;
        init();
    }

    public SkinImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public SkinImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }

    private void init() {
        setScaleType(ScaleType.MATRIX);
    }

    @Override
    protected boolean setFrame(int l, int t, int r, int b) {
        SkinImageView.this.imgWidth = r - l;
        SkinImageView.this.imgHeight = b - t;
        matrix = null;
        calculationMatrix(skinDrawable);
        return super.setFrame(l, t, r, b);
    }

    @Override
    public void setImageDrawable(@Nullable Drawable drawable) {
        calculationMatrix(drawable);
        super.setImageDrawable(drawable);
    }

    /**
     * 计算matrix
     *
     * @param drawable
     */
    public void calculationMatrix(Drawable drawable) {
        if (drawable == null)
            return;
        if (matrix == null) {
            skinDrawable = drawable;
            int dwidth = drawable.getIntrinsicWidth();
            int dheight = drawable.getIntrinsicHeight();

            if (dwidth <= 0 || dheight <= 0 || imgWidth <= 0) {
                super.setImageDrawable(drawable);
                return;
            }
            matrix = new Matrix();           //创建一个单位矩阵
            float scale = (float) imgWidth / (float) dwidth;
            float dy = imgHeight - dheight * scale;
            matrix.setScale(scale, scale);
            if (cropType != TYPE_START_CROP) {
                float dx = 0;
                if (dy > 0) {
                    scale = (float) imgHeight / (float) dheight;
                    dy = 0;
                    dx = imgWidth - dwidth * scale;
                }
                matrix.setScale(scale, scale);
                matrix.postTranslate(Math.round(dx), Math.round(dy));
            }

            setImageMatrix(matrix);       //设置并应用矩阵
        } else {
            setImageMatrix(matrix);       //设置并应用矩阵
        }
    }

    public void setCropType(int type) {
        this.cropType = type;
        matrix = null;
    }

}

注意:1.TYPE_START_CROP 以左上为标准;TYPE_END_CROP 以右下为标准;

            2.目前只加了setImageDrawable方法,如有需要请自行添加。

发布了11 篇原创文章 · 获赞 1 · 访问量 3911

猜你喜欢

转载自blog.csdn.net/qin19930929/article/details/84579138
今日推荐