- 上一篇已经完成一个不带边框的,等比缩放的,铺满控件的ImageView。但是需求往往是无止境的,可能你做好了一个,结果需求又有改变的增加。不过,不管怎么说,这个需求还是可以实现的。
- 在上一篇中,我没有强调的是:在使用该自定义的ImageView的时候,一定不要在布局文件xml中设置如下属性:
android:visibility="gone"
。是的,就是一定不是使用gone
属性。及时后面,你在的代码中将使用了imgview.setVisibility(View.VISIBLE);
也是不行的。这个原因参照void android.view.ViewTreeObserver.OnGlobalLayoutListener.onGlobalLayout()
方法的注释:
/**
<ul><li>Callback method to be invoked when the global layout state or the visibility of views</li>
<li>within the view tree changes
*/- 大致意思差不多就是:xxxxxx,算了,我就不翻译了,有需要的自行去找翻译软件吧。
- OK,这个带边框的,铺满控件的,等比缩放的
ImageView
就是这样来写了:
import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.ImageView; /** * 带边框的,铺满控件的ImageView */ @SuppressLint("DrawAllocation") public class BorderImageView extends ImageView implements OnGlobalLayoutListener { private static final int DEFAULT_FRAME_COLOR = 0x000; private static final boolean DEBUG = true; private int color = 0xff669900; private boolean once; private Matrix matrix; public BorderImageView(Context context) { this(context, null); } public BorderImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BorderImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { once = true; matrix = new Matrix(); setScaleType(ScaleType.MATRIX); } @Override protected void onAttachedToWindow() { getViewTreeObserver().addOnGlobalLayoutListener(this); super.onAttachedToWindow(); } @Override protected void onDetachedFromWindow() { getViewTreeObserver().removeOnGlobalLayoutListener(this); super.onDetachedFromWindow(); } @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 画边框 Rect rec = canvas.getClipBounds(); rec.bottom--; rec.right--; Paint paint = new Paint(); paint.setColor(color); paint.setStyle(Paint.Style.STROKE); canvas.drawRect(rec, paint); } @Override public void onGlobalLayout() { if (once) { // 1.view wh int width = getWidth(); int height = getHeight(); // 2. d dw dh Drawable drawable = getDrawable(); if (drawable == null) { return; } if (DEBUG) { System.out.println("drawable:" + drawable); } int dw = drawable.getIntrinsicWidth(); int dh = drawable.getIntrinsicHeight(); // first trans float dx = width * 1.0f / 2 - dw * 1.0f / 2; float dy = height * 1.0f / 2 - dh * 1.0f / 2; matrix.postTranslate(dx, dy); // second scale float scale = 1.0f; if (dw > width && dh < height) { scale = height * 1.0f / dh;// bigger } if (dw < width && dh > height) { scale = width * 1.0f / dw;// bigger } if (dw < width && dh < height) { float sh = height * 1.0f / dh; float sw = width * 1.0f / dw; scale = Math.max(sw, sh); System.out.println("case3:"+sw+"--"+sh+"==="+scale); } if (dw > width && dh > height) { float sw = width * 1.0f / dw; float sh = height * 1.0f / dh; scale = Math.max(sw, sh); System.out.println("case4:"+sw+"--"+sh+"==="+scale); } if (DEBUG) { System.out.println("scale:" + scale); } matrix.postScale(scale, scale, width / 2, height / 2); setImageMatrix(matrix); once = false; } } }
- 额,代码不算很多,里面的东西其实都是之前有写过的。就不去解释了。
- 然后在布局中去使用的话,就很简单了,比如:
<com.xxxxx.yyyyyy.BorderImageView android:id="@+id/borderImg" android:layout_width="440dp" android:layout_height="440dp" android:padding="2dp" android:scaleType="matrix" android:src="@drawable/install" android:visibility="visible" />
这里,我故意将宽高设置成一个固定的数字,是为了看到效果。当然,你设置成
match_parent
或者wrap_content
也是OK的。对于很小的图片,这里的操作逻辑也是将它等比拉大。如果在使用中,感觉这样不好,也可以去修改一下上面的代码,或者给我留言,我到时候再发一个更能满足需求的控件出来。