您当前的位置:首页 > 安卓知识 

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的整体代码,选择结构图中的部分作为重点。首先是构造方法,代码如下:
 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介绍 这篇文章。













上一篇:Android-使用ViewFlipper实现轮番切换广告栏_关于Android编程

下一篇: 蜗牛—Android基础之按钮监听器_关于Android编程