对于这个情况,第一时间想到的方法,就是imageview增加scaleType="centerCrop"。
imageview自带的centerCrop是不管图片小于还是大于imageview的大小,都会等比例拉伸填充满,然后裁剪;
另外,如果图片加载框使用的是glide,那么glide自己也有一个centerCrop,但是跟imageview自带的不一样。
Glide的centerCrop对于大图是裁剪,如果图片小于imageview,则是等比例全部显示在imageview里而不是填满裁剪;
注意:如果imageview自己设置了centeCrop,这时候Glide再设置圆角,如果图片原图小于imageview,圆角是无效的。
这是因为glide先处理了图片数据,同时由于图片是小于imageview的大小的,所以glide的处理是全部显示在imageview上,然后处理圆角。最后把处理完的图片数据(有圆角),设置在imageview上,由于imageview有centerCrop属性,图片会等比例拉伸填充裁剪,导致了圆角的失效。
imageview同时设置fitXY 和adjustViewBounds 也能达到效果。
fitXY 这种图片的显示方式的效果是:根据 ImageView 设置的大小拉伸图片以填充满空间,(单独设置此属性时)图片会变形。
adjustViewBounds 是限制图片在显示时保持原图比例。(和 fitXY 显示方式合用能到达自适应的效果)
不使用Android自带属性,怎么达到一样的效果?
①自定义view,继承iamgeview,重写onMeasure
@SuppressLint("AppCompatCustomView")
public class ResizableImageView extends ImageView {
private int value=0;
public ResizableImageView(Context context) {
super(context);
}
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Drawable d = getDrawable();
if(d!=null){
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width;
//高度根据使得图片的宽度充满屏幕计算而得(这个是默认计算)
// int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
if (value==1){
height = (int) Math.ceil((float) (width*4/3));
}
setMeasuredDimension(width, height);
}else{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
//根据传过来的值,1是宽度3:4,其它值是1:1
public void setMeasure(int value){
this.value= value;
}
}
但是如果利用glide来加载图片,又会发现,上面的方法也是不行的,因为glide是根据imageview的大小来加载的,由于上面设置的是warp_content,所以glide无法准确根据大小来加载图片。
解决方法:
1、你已经知道图片(或其他方式提前知道)图片的比例,然后在用 Glide 请求图片时限制图片的加载大小,即设置 override(int width, int height) 。这时候加载到的图片是原图比例,显示的时候虽然有拉伸/压缩但都会保存原比例的。这种方式适用于你加载的图片大小都比较规范固定的时候。
2、当你请求的图片源大小不一定一致。那这时候就可以使用下面这种方式了。这种方式的原理是,先使用 Glide 把图片的原图请求加载过来,然后再按原图来显示图片。
Glide.with(mContext)
.load(url)
.asBitmap()
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
ivOcnyang.setImageBitmap(resource);
}
});
这两种方法中,其实更加提倡的是第一种方式,因为这种方式不会造成任何负面的影响。但第二种方式,由于Glide加载图片时是以全分辨率加载的,当加载图片过大且图片很多时,可能造成 OOM。同时第二种方式使用在列表上复用时会造成条目错乱错位。
但是我们要图片不拉伸,view大小也不改变,将空白解决。
其实也简单,也是需要自定义view。
①自定义view,重写ondraw方法。
②获得将要显示的图片的尺寸或者比例,传入自定义view中,备用。
③onMeasure可以获得控件的大小,记录下来。
④在ondraw方法里,根据控件的大小和图片的大小,利用canvas先把图片从左上角开始填充。
⑤记录填充后的位置,如果还小于控件的大小,那就继续接着填充同样的图片bitmap,直到填满为止。