Android ImageView剖析及拓展_关于Android编程
时间:2023-10-05 05:31
阅读数:60人阅读
版本:1.0 日期:2014.6.11 2014.6.12版权:© 2014 kince 转载注明出处
ImageView是开发中经常使用到的一个控件,也可以说是必不可少的。对于它的使用,除了注意ScaleType的理解和设置外,还需要注意其他一些问题,比如设置一张大的背景图片内存占用和释放等。还有它的拓展性方面,像圆角图片、圆形图片、图片边框等等。因此,如果想熟练使用这个控件,就需要对其实现的机制有一个基本的了解。 ImageView也是直接继承于View类,主要的结构图如下:
鉴于篇幅大小,就不copy ImageView的整体代码,选择结构图中的部分作为重点。首先是构造方法,代码如下:
ImageView是开发中经常使用到的一个控件,也可以说是必不可少的。对于它的使用,除了注意ScaleType的理解和设置外,还需要注意其他一些问题,比如设置一张大的背景图片内存占用和释放等。还有它的拓展性方面,像圆角图片、圆形图片、图片边框等等。因此,如果想熟练使用这个控件,就需要对其实现的机制有一个基本的了解。 ImageView也是直接继承于View类,主要的结构图如下:
鉴于篇幅大小,就不copy ImageView的整体代码,选择结构图中的部分作为重点。首先是构造方法,代码如下:
public ImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initImageView(); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ImageView, defStyle, 0); Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src); if (d != null) { setImageDrawable(d); } mBaselineAlignBottom = a.getBoolean( com.android.internal.R.styleable.ImageView_baselineAlignBottom, false); mBaseline = a.getDimensionPixelSize( com.android.internal.R.styleable.ImageView_baseline, -1); setAdjustViewBounds( a.getBoolean(com.android.internal.R.styleable.ImageView_adjustViewBounds, false)); setMaxWidth(a.getDimensionPixelSize( com.android.internal.R.styleable.ImageView_maxWidth, Integer.MAX_VALUE)); setMaxHeight(a.getDimensionPixelSize( com.android.internal.R.styleable.ImageView_maxHeight, Integer.MAX_VALUE)); int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1); if (index >= 0) { setScaleType(sScaleTypeArray[index]); } int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0); if (tint != 0) { setColorFilter(tint); } int alpha = a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255); if (alpha != 255) { setAlpha(alpha); } mCropToPadding = a.getBoolean( com.android.internal.R.styleable.ImageView_cropToPadding, false); a.recycle(); //need inflate syntax/reader for matrix } private void initImageView() { mMatrix = new Matrix(); mScaleType = ScaleType.FIT_CENTER; mAdjustViewBoundsCompat = mContext.getApplicationInfo().targetSdkVersion vwidth * dheight) { scale = (float) vheight / (float) dheight; dx = (vwidth - dwidth * scale) * 0.5f; } else { scale = (float) vwidth / (float) dwidth; dy = (vheight - dheight * scale) * 0.5f; } mDrawMatrix.setScale(scale, scale); mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); } else if (ScaleType.CENTER_INSIDE == mScaleType) { mDrawMatrix = mMatrix; float scale; float dx; float dy; if (dwidth nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常。
另外,需要特别注意:decodeStream是直接读取图片资料的字节码了, 不会根据机器的各种分辨率来自动适应,使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。public static Bitmap readBitMap(Context context, int resId){ BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inPreferredConfig = Bitmap.Config.RGB_565; opt.inPurgeable = true; opt.inInputShareable = true; InputStream is = context.getResources().openRawResource(resId); return BitmapFactory.decodeStream(is,null,opt); }3、手动收回占用资源 虽然虚拟机会自动回收垃圾资源,但是有时候不是那么及时,这时候可以手动回收。if(!bmp.isRecycle() ){ bmp.recycle() //回收图片所占的内存 system.gc() //提醒系统及时回收 }4、优化Dalvik虚拟机的堆内存分配 使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。private final static float TARGET_HEAP_UTILIZATION = 0.75f;在程序onCreate时就可以调用VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);即可。 除了 优化Dalvik虚拟机的堆内存分配 外,还可以强制定义自己软件的对内存大小,使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例:Dalvik.VMRuntime类,提供对虚拟机全局,Dalvik的特定功能的接口。Android为每个程序分配的内存可以通过Runtime类的 totalMemory() 、freeMemory() 两个方法获取VM的一些内存信息。private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ; VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。下面讲解一下如何自定义一个类继承于ImageView。首先以CircleButton为例,这是github上一个项目,实现一个圆形有点击效果的按钮。如下: 实现思路是这样的,先画两个圆形图案,一个是实心的圆,一个是圆环。圆环半径小于实心圆半径,这样默认就看不到圆环,然后再画出设置的图片,覆盖在二者之上。最后在按下的时候启动一个属性动画,将圆环放大显示,关于详细的分析可以看android-circlebutton介绍 这篇文章。