目前系统自带的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方法,如有需要请自行添加。