Android:FullImageView 自定义等比缩放的铺满控件显示的ImageView

  • 何谓铺满控件的显示:也就是说,一个ImageView控件里面,全部是图片,没有空白部分。
  • 适用范围:加载晓得ImageView,比如,作为AbsListView的一个Item的图标。
  • 如我们所知:Android 系统提供的ImageView控件,通过设置属性:android:scaleType="fitXY"就可以让图片铺满控件显示了。但是,在我们实际开发中,应该很少有人会去使用这个属性,因为这样做就让图片变形了。
  • OK,既然Android系统没有给我提供这样方便的显示方式,那么,我们就去自定义一个ImageView以满足我们的需求。
  • 代码不是很多,里面注释也是比较详细的,就不先解释了。
  • 自定义ImageView的代码:

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;

/**
 * 自动让图片铺满控件显示的ImageView
* 何谓铺满控件:就是图片等比缩放。然后占满控件。多余的部分会加载在控件之外,也就是看不见的地方 */
public class FullImage extends ImageView implements OnGlobalLayoutListener { private static final boolean DEBUG = true; private boolean once; private Matrix matrix; public FullImage(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FullImage(Context context) { this(context, null); } public FullImage(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // init init(); } private void init() { once = true; matrix = new Matrix(); // setScaleType(ScaleType.MATRIX);// 这一步不加,以上全是白费 } @Override protected void onAttachedToWindow() { // 注册 OnGlobalLayoutListener 的监听 ViewTreeObserver observer = getViewTreeObserver(); observer.addOnGlobalLayoutListener(this); super.onAttachedToWindow(); } @SuppressLint("NewApi") @Override protected void onDetachedFromWindow() { // 反注册 OnGlobalLayoutListener 的监听 getViewTreeObserver().removeOnGlobalLayoutListener(this); super.onDetachedFromWindow(); } @Override public void onGlobalLayout() { if (once) {// 初始化操作,只需要搞一次即可。但是onGlobalLayout 会被多次调用 // 1. 获取当前控件,加载之后的(this)的宽高 int width = this.getWidth(); int height = this.getHeight(); // 2. 获取显示的图片,以及宽高 Drawable drawable = this.getDrawable();// 获取显示的图片 if (drawable == null) return; if (DEBUG) { System.out.println("drawable: " + drawable); } int dw = drawable.getIntrinsicWidth();// 获取图片的宽高 int dh = drawable.getIntrinsicHeight();// 获取图片的宽高 if (DEBUG) { System.out.println("dw: " + dw); System.out.println("dh: " + dh); System.out.println("width: " + width); System.out.println("height: " + height); } // 5.不仅要缩放,还要让图片居中(图片中心点和控件中心点重合),也就是平移 int dx = Math.round(width * 1.0f / 2 - dw * 1.0f / 2);// x方向:向右移动:控件宽度的一半-图片宽度的一般 int dy = Math.round(height * 1.0f / 2 - dh * 1.0f / 2);// y方法:向下移动:控件高度的一半-图片高度的一半 // ___TODO:一定要先平移再进行缩放拆走 matrix.postTranslate(dx, dy);// 这个OK // 3. 根据控件宽高一级图片宽高,设置缩放比例 float scale = 1.0f; // case 1:图片宽度>控件宽度,高度<控件高度 if (dw > width && dh < height) {// 如果要铺满控件,且等比缩放,则 /** // scale = width * 1.0f / dw;// <1,缩小的*/ scale = height * 1.0f / dh;// >1,放大 System.out.println("case 1:" + scale); } // case 2:图片宽度<控件宽度,高度>控件高度 if (dw < width && dh > height) {// 如果要完全显示图片,且等比缩放,则 /** // scale = height / dh;// <1,缩小的*/ scale = width * 1.0f / dw;// >1,放大 System.out.println("case 2:" + scale); } // case 3:图片宽度>控件宽度,高度>控件高度 if (dw > width && dh > height) {// 如果要铺满控件,且等比缩放,则 scale = Math.max(width * 1.0f / dw, height* 1.0f / dh);// <1,缩小的 System.out.println("case 3:" + scale); } // case 4:图片宽度<控件宽度,高度<控件高度 if (dw < width && dh < height) {// 如果要完全显示图片,且等比缩放,则 scale = Math.max(width * 1.0f / dw, height* 1.0f / dh);// >1,放大的 System.out.println("case 4:" + scale); } // ------图片与控件的尺寸比较,只有以上4种情况 // 4. 根据缩放比例进行缩放 if (DEBUG) { System.out.println("scale: " + scale); } matrix.postScale(scale, scale, width / 2, height / 2); this.setImageMatrix(matrix); once = false; } } }
  • 需要注意的是:我在代码中是先进行平移,再进行缩放的。是因为,如果先缩放,再平移,可能会出现一些不正常的效果。

  • 使用该控件的代码:

 <com.xxx.yyyy.FullImage
        android:id="@+id/imageView1"
        android:layout_width="240dp"
        android:layout_height="240dp"
        android:background="@android:color/darker_gray"
        android:padding="2dp"
        android:src="@drawable/install" />

只要,在我们需要使用这种显示方式的地方,将xnl中ImageView改成我们自定义的FullImage即可。不需要做任何的自定义属性,自定义命名空间等等。

你可能感兴趣的:(实际需求解决方案)