版本号:1.0 
日期:2014.6.11 2014.6.12
版权:© 2014 kince 转载注明出处
  ImageView是开发中经常使用到的一个控件,也能够说是不可缺少的。

对于它的使用。除了注意ScaleType的理解和设置外,还须要注意其它一些问题,比方设置一张大的背景图片内存占用和释放等。

还有它的拓展性方面,像圆角图片、圆形图片、图片边框等等。因此,假设想熟练使用这个控件,就须要对事实上现的机制有一个基本的了解。

  ImageView也是直接继承于View类。基本的结构图例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ2ppbnl1NTAx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

 鉴于篇幅大小,就不copy ImageView的总体代码,选择结构图中的部分作为重点。首先是构造方法,代码例如以下:
  1. public ImageView(Context context, AttributeSet attrs, int defStyle) {
  2. super(context, attrs, defStyle);
  3. initImageView();
  4.  
  5. TypedArray a = context.obtainStyledAttributes(attrs,
  6. com.android.internal.R.styleable.ImageView, defStyle, 0);
  7.  
  8. Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src);
  9. if (d != null) {
  10. setImageDrawable(d);
  11. }
  12.  
  13. mBaselineAlignBottom = a.getBoolean(
  14. com.android.internal.R.styleable.ImageView_baselineAlignBottom, false);
  15.  
  16. mBaseline = a.getDimensionPixelSize(
  17. com.android.internal.R.styleable.ImageView_baseline, -1);
  18.  
  19. setAdjustViewBounds(
  20. a.getBoolean(com.android.internal.R.styleable.ImageView_adjustViewBounds,
  21. false));
  22.  
  23. setMaxWidth(a.getDimensionPixelSize(
  24. com.android.internal.R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
  25.  
  26. setMaxHeight(a.getDimensionPixelSize(
  27. com.android.internal.R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
  28.  
  29. int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1);
  30. if (index >= 0) {
  31. setScaleType(sScaleTypeArray[index]);
  32. }
  33.  
  34. int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0);
  35. if (tint != 0) {
  36. setColorFilter(tint);
  37. }
  38.  
  39. int alpha = a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255);
  40. if (alpha != 255) {
  41. setAlpha(alpha);
  42. }
  43.  
  44. mCropToPadding = a.getBoolean(
  45. com.android.internal.R.styleable.ImageView_cropToPadding, false);
  46.  
  47. a.recycle();
  48.  
  49. //need inflate syntax/reader for matrix
  50. }
  51.  
  52. private void initImageView() {
  53. mMatrix = new Matrix();
  54. mScaleType = ScaleType.FIT_CENTER;
  55. mAdjustViewBoundsCompat = mContext.getApplicationInfo().targetSdkVersion <=
  56. Build.VERSION_CODES.JELLY_BEAN_MR1;
  57. }
  在构造方法中也是非经常规的从attrs文件里读取属性值,并进行设置。也能够看到ImageView默认使用的ScaleType是FIT_CENTER。说到ScaleType。它是一个枚举类型,用于设置。寻常使用的ScaleType就是在这里定义的。

  1. /**
  2. * Options for scaling the bounds of an image to the bounds of this view.
  3. */
  4. public enum ScaleType {
  5. /**
  6. * Scale using the image matrix when drawing. The image matrix can be set using
  7. * {@link ImageView#setImageMatrix(Matrix)}. From XML, use this syntax:
  8. * <code>android:scaleType="matrix"</code>.
  9. */
  10. MATRIX (0),
  11. /**
  12. * Scale the image using {@link Matrix.ScaleToFit#FILL}.
  13. * From XML, use this syntax: <code>android:scaleType="fitXY"</code>.
  14. */
  15. FIT_XY (1),
  16. /**
  17. * Scale the image using {@link Matrix.ScaleToFit#START}.
  18. * From XML, use this syntax: <code>android:scaleType="fitStart"</code>.
  19. */
  20. FIT_START (2),
  21. /**
  22. * Scale the image using {@link Matrix.ScaleToFit#CENTER}.
  23. * From XML, use this syntax:
  24. * <code>android:scaleType="fitCenter"</code>.
  25. */
  26. FIT_CENTER (3),
  27. /**
  28. * Scale the image using {@link Matrix.ScaleToFit#END}.
  29. * From XML, use this syntax: <code>android:scaleType="fitEnd"</code>.
  30. */
  31. FIT_END (4),
  32. /**
  33. * Center the image in the view, but perform no scaling.
  34. * From XML, use this syntax: <code>android:scaleType="center"</code>.
  35. */
  36. CENTER (5),
  37. /**
  38. * Scale the image uniformly (maintain the image's aspect ratio) so
  39. * that both dimensions (width and height) of the image will be equal
  40. * to or larger than the corresponding dimension of the view
  41. * (minus padding). The image is then centered in the view.
  42. * From XML, use this syntax: <code>android:scaleType="centerCrop"</code>.
  43. */
  44. CENTER_CROP (6),
  45. /**
  46. * Scale the image uniformly (maintain the image's aspect ratio) so
  47. * that both dimensions (width and height) of the image will be equal
  48. * to or less than the corresponding dimension of the view
  49. * (minus padding). The image is then centered in the view.
  50. * From XML, use this syntax: <code>android:scaleType="centerInside"</code>.
  51. */
  52. CENTER_INSIDE (7);
  53.  
  54. ScaleType(int ni) {
  55. nativeInt = ni;
  56. }
  57. final int nativeInt;
  58. }
 功能是设置图片的显示位置和大小等方面。

接着就是onMeasure()方法了,它用于设置ImageView的大小。我们在xml文件里设置ImageView的时候,假设指定了固定的宽高,那么onMeasur()方法中測量的大小就是固定的宽高大小;假设是包裹内容,那么就须要进一步的计算。

  1. @Override
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  3. resolveUri();//获取图片Drawable
  4. int w;
  5. int h;
  6.  
  7. // Desired aspect ratio of the view's contents (not including padding)
  8. float desiredAspect = 0.0f;
  9.  
  10. // We are allowed to change the view's width
  11. boolean resizeWidth = false;
  12.  
  13. // We are allowed to change the view's height
  14. boolean resizeHeight = false;
  15.  
  16. final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
  17. final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
  18.  
  19. if (mDrawable == null) {
  20. // If no drawable, its intrinsic size is 0.
  21. mDrawableWidth = -1;
  22. mDrawableHeight = -1;
  23. w = h = 0;
  24. } else {
  25. w = mDrawableWidth;在updateDrawable(Drawable d)方法赋值的。
  26. h = mDrawableHeight;
  27. if (w <= 0) w = 1;
  28. if (h <= 0) h = 1;
  29.  
  30. // We are supposed to adjust view bounds to match the aspect
  31. // ratio of our drawable. See if that is possible.
  32. if (mAdjustViewBounds) {
  33. resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
  34. resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
  35.  
  36. desiredAspect = (float) w / (float) h;
  37. }
  38. }
  39.  
  40. int pleft = mPaddingLeft;
  41. int pright = mPaddingRight;
  42. int ptop = mPaddingTop;
  43. int pbottom = mPaddingBottom;
  44.  
  45. int widthSize;
  46. int heightSize;
  47.  
  48. if (resizeWidth || resizeHeight) {
  49. /* If we get here, it means we want to resize to match the
  50. drawables aspect ratio, and we have the freedom to change at
  51. least one dimension.
  52. */
  53.  
  54. // Get the max possible width given our constraints
  55. widthSize = resolveAdjustedSize(w + pleft + pright, mMaxWidth, widthMeasureSpec);
  56.  
  57. // Get the max possible height given our constraints
  58. heightSize = resolveAdjustedSize(h + ptop + pbottom, mMaxHeight, heightMeasureSpec);
  59.  
  60. if (desiredAspect != 0.0f) {
  61. // See what our actual aspect ratio is
  62. float actualAspect = (float)(widthSize - pleft - pright) /
  63. (heightSize - ptop - pbottom);
  64.  
  65. if (Math.abs(actualAspect - desiredAspect) > 0.0000001) {
  66.  
  67. boolean done = false;
  68.  
  69. // Try adjusting width to be proportional to height
  70. if (resizeWidth) {
  71. int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
  72. pleft + pright;
  73.  
  74. // Allow the width to outgrow its original estimate if height is fixed.
  75. if (!resizeHeight && !mAdjustViewBoundsCompat) {
  76. widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec);
  77. }
  78.  
  79. if (newWidth <= widthSize) {
  80. widthSize = newWidth;
  81. done = true;
  82. }
  83. }
  84.  
  85. // Try adjusting height to be proportional to width
  86. if (!done && resizeHeight) {
  87. int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
  88. ptop + pbottom;
  89.  
  90. // Allow the height to outgrow its original estimate if width is fixed.
  91. if (!resizeWidth && !mAdjustViewBoundsCompat) {
  92. heightSize = resolveAdjustedSize(newHeight, mMaxHeight,
  93. heightMeasureSpec);
  94. }
  95.  
  96. if (newHeight <= heightSize) {
  97. heightSize = newHeight;
  98. }
  99. }
  100. }
  101. }
  102. } else {
  103. /* We are either don't want to preserve the drawables aspect ratio,
  104. or we are not allowed to change view dimensions. Just measure in
  105. the normal way.
  106. */
  107. w += pleft + pright;
  108. h += ptop + pbottom;
  109.  
  110. w = Math.max(w, getSuggestedMinimumWidth());
  111. h = Math.max(h, getSuggestedMinimumHeight());
  112.  
  113. widthSize = resolveSizeAndState(w, widthMeasureSpec, 0);
  114. heightSize = resolveSizeAndState(h, heightMeasureSpec, 0);
  115. }
  116.  
  117. setMeasuredDimension(widthSize, heightSize);
  118. }

在onMeasure方法中,首先调用了resolveUri()这种方法。目的就是为了确定Drawable。

假设设置了drawableResource。那么Drawable就是其值;假设没有。那么就从ContentResolver获取一个Drawable。

  1. private void resolveUri() {
  2. if (mDrawable != null) {
  3. return;
  4. }
  5.  
  6. Resources rsrc = getResources();
  7. if (rsrc == null) {
  8. return;
  9. }
  10.  
  11. Drawable d = null;
  12.  
  13. if (mResource != 0) {
  14. try {
  15. d = rsrc.getDrawable(mResource);
  16. } catch (Exception e) {
  17. Log.w("ImageView", "Unable to find resource: " + mResource, e);
  18. // Don't try again.
  19. mUri = null;
  20. }
  21. } else if (mUri != null) {
  22. String scheme = mUri.getScheme();
  23. if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
  24. try {
  25. // Load drawable through Resources, to get the source density information
  26. ContentResolver.OpenResourceIdResult r =
  27. mContext.getContentResolver().getResourceId(mUri);
  28. d = r.r.getDrawable(r.id);
  29. } catch (Exception e) {
  30. Log.w("ImageView", "Unable to open content: " + mUri, e);
  31. }
  32. } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
  33. || ContentResolver.SCHEME_FILE.equals(scheme)) {
  34. InputStream stream = null;
  35. try {
  36. stream = mContext.getContentResolver().openInputStream(mUri);
  37. d = Drawable.createFromStream(stream, null);
  38. } catch (Exception e) {
  39. Log.w("ImageView", "Unable to open content: " + mUri, e);
  40. } finally {
  41. if (stream != null) {
  42. try {
  43. stream.close();
  44. } catch (IOException e) {
  45. Log.w("ImageView", "Unable to close content: " + mUri, e);
  46. }
  47. }
  48. }
  49. } else {
  50. d = Drawable.createFromPath(mUri.toString());
  51. }
  52.  
  53. if (d == null) {
  54. System.out.println("resolveUri failed on bad bitmap uri: " + mUri);
  55. // Don't try again.
  56. mUri = null;
  57. }
  58. } else {
  59. return;
  60. }
  61.  
  62. updateDrawable(d);
  63. }
  之后在resolveUri()这种方法的最后,调用了 updateDrawable(d)方法。这种方法代码例如以下:
  1. private void updateDrawable(Drawable d) {
  2. if (mDrawable != null) {
  3. mDrawable.setCallback(null);
  4. unscheduleDrawable(mDrawable);
  5. }
  6. mDrawable = d;
  7. if (d != null) {
  8. d.setCallback(this);
  9. if (d.isStateful()) {
  10. d.setState(getDrawableState());
  11. }
  12. d.setLevel(mLevel);
  13. d.setLayoutDirection(getLayoutDirection());
  14. d.setVisible(getVisibility() == VISIBLE, true);
  15. mDrawableWidth = d.getIntrinsicWidth();
  16. mDrawableHeight = d.getIntrinsicHeight();
  17. applyColorMod();
  18. configureBounds();
  19. } else {
  20. mDrawableWidth = mDrawableHeight = -1;
  21. }
  22. }
  能够看到就是为了Drawable宽高赋值的。回过头来继续看。假设Drawable的宽高不为空的话就分别赋值给w和h。假设为空的话值为-1。然后是一个if推断,mAdjustViewBounds作为推断的变量,它是在setAdjustViewBounds方法中设置的,默觉得false,所以必须设置为true,这个推断才会运行。当然这个变量的值也能够在xml文件里设置(android:adjustViewBounds)。

那这种方法是做什么用的呢?设置View的最大高度,单独使用无效,须要与setAdjustViewBounds一起使用。假设想设置图片固定大小,又想保持图片宽高比,须要例如以下设置:

1) 设置setAdjustViewBounds为true;
2) 设置maxWidth、MaxHeight;
3) 设置设置layout_width和layout_height为wrap_content。

  再看一下这个推断。
  1. if (mAdjustViewBounds) {
  2. resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
  3. resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
  4.  
  5. desiredAspect = (float) w / (float) h;
  6. }
  widthSpecMode假设不是指定大小的话。由于假设指定了固定大小就不须要又一次设置大小了。

然后接下来的推断也是基于 resizeWidth和resizeHeight 的值,假设不为true的情况下,会运行例如以下代码:

  1. w += pleft + pright;
  2. h += ptop + pbottom;
  3. w = Math.max(w, getSuggestedMinimumWidth());
  4. h = Math.max(h, getSuggestedMinimumHeight());
  5. widthSize = resolveSizeAndState(w, widthMeasureSpec, 0);
  6. heightSize = resolveSizeAndState(h, heightMeasureSpec, 0);
  7. }
  8. setMeasuredDimension(widthSize, heightSize);
  考虑了填充,最后设置ImageView的大小。

  最后看一下onDraw()方法,
  1. @Override
  2. protected void onDraw(Canvas canvas) {
  3. super.onDraw(canvas);
  4.  
  5. if (mDrawable == null) {
  6. return; // couldn't resolve the URI
  7. }
  8.  
  9. if (mDrawableWidth == 0 || mDrawableHeight == 0) {
  10. return; // nothing to draw (empty bounds)
  11. }
  12.  
  13. if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
  14. mDrawable.draw(canvas);
  15. } else {
  16. int saveCount = canvas.getSaveCount();
  17. canvas.save();
  18.  
  19. if (mCropToPadding) {
  20. final int scrollX = mScrollX;
  21. final int scrollY = mScrollY;
  22. canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
  23. scrollX + mRight - mLeft - mPaddingRight,
  24. scrollY + mBottom - mTop - mPaddingBottom);
  25. }
  26.  
  27. canvas.translate(mPaddingLeft, mPaddingTop);
  28.  
  29. if (mDrawMatrix != null) {
  30. canvas.concat(mDrawMatrix);
  31. }
  32. mDrawable.draw(canvas);
  33. canvas.restoreToCount(saveCount);
  34. }
  35. }
  在onDraw()方法中,实现方式比較简单,假设mDrawMatrix为空,那么就直接绘制出图片;假设不为空,那么还须要绘制矩阵。这就涉及到mDrawMatrix矩阵了。它是在哪赋值的呢,就是ScaleType。

这个是在configureBounds()方法中设置的,

  1. private void configureBounds() {
  2. if (mDrawable == null || !mHaveFrame) {
  3. return;
  4. }
  5.  
  6. int dwidth = mDrawableWidth;
  7. int dheight = mDrawableHeight;
  8.  
  9. int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
  10. int vheight = getHeight() - mPaddingTop - mPaddingBottom;
  11.  
  12. boolean fits = (dwidth < 0 || vwidth == dwidth) &&
  13. (dheight < 0 || vheight == dheight);
  14.  
  15. if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
  16. /* If the drawable has no intrinsic size, or we're told to
  17. scaletofit, then we just fill our entire view.
  18. */
  19. mDrawable.setBounds(0, 0, vwidth, vheight);
  20. mDrawMatrix = null;
  21. } else {
  22. // We need to do the scaling ourself, so have the drawable
  23. // use its native size.
  24. mDrawable.setBounds(0, 0, dwidth, dheight);
  25.  
  26. if (ScaleType.MATRIX == mScaleType) {
  27. // Use the specified matrix as-is.
  28. if (mMatrix.isIdentity()) {
  29. mDrawMatrix = null;
  30. } else {
  31. mDrawMatrix = mMatrix;
  32. }
  33. } else if (fits) {
  34. // The bitmap fits exactly, no transform needed.
  35. mDrawMatrix = null;
  36. } else if (ScaleType.CENTER == mScaleType) {
  37. // Center bitmap in view, no scaling.
  38. mDrawMatrix = mMatrix;
  39. mDrawMatrix.setTranslate((int) ((vwidth - dwidth) * 0.5f + 0.5f),
  40. (int) ((vheight - dheight) * 0.5f + 0.5f));
  41. } else if (ScaleType.CENTER_CROP == mScaleType) {
  42. mDrawMatrix = mMatrix;
  43.  
  44. float scale;
  45. float dx = 0, dy = 0;
  46.  
  47. if (dwidth * vheight > vwidth * dheight) {
  48. scale = (float) vheight / (float) dheight;
  49. dx = (vwidth - dwidth * scale) * 0.5f;
  50. } else {
  51. scale = (float) vwidth / (float) dwidth;
  52. dy = (vheight - dheight * scale) * 0.5f;
  53. }
  54.  
  55. mDrawMatrix.setScale(scale, scale);
  56. mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
  57. } else if (ScaleType.CENTER_INSIDE == mScaleType) {
  58. mDrawMatrix = mMatrix;
  59. float scale;
  60. float dx;
  61. float dy;
  62.  
  63. if (dwidth <= vwidth && dheight <= vheight) {
  64. scale = 1.0f;
  65. } else {
  66. scale = Math.min((float) vwidth / (float) dwidth,
  67. (float) vheight / (float) dheight);
  68. }
  69.  
  70. dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);
  71. dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f);
  72.  
  73. mDrawMatrix.setScale(scale, scale);
  74. mDrawMatrix.postTranslate(dx, dy);
  75. } else {
  76. // Generate the required transform.
  77. mTempSrc.set(0, 0, dwidth, dheight);
  78. mTempDst.set(0, 0, vwidth, vheight);
  79.  
  80. mDrawMatrix = mMatrix;
  81. mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));
  82. }
  83. }
  84. }
  能够看到在if推断中,对各个ScaleType的类型都进行了推断。依据不同的ScaleType设置不同的矩阵mDrawMatrix。然后通过矩阵对图像进行变换,从而显示出不同的效果。

  除了这一点经常使用到之外,还有就是怎样设置图片资源了,有下面几个方法:setImageResource(int resId)、setImageURI(Uri uri)、setImageDrawable(Drawable drawable)、setImageBitmap(Bitmap bm)等。或者也能够在xml文件里设置。

可是这样直接使用会有一个隐形的弊端,假设显示的图片过多或者单张显示的图片像素过大,就easy出现OOM问题。因此就应该依据需求对图片进行预处理,经常用法有下面几种:

1、缩放、边界压缩
     在内存中载入图片时直接在内存中做处理。

关于图片压缩有非常多方法,这里仅仅是列举一个简单的样例,实际使用价值不大。如有需求能够自行參考其它资料。

  1. InputStream is = this.getResources().openRawResource(R.drawable.xx);
  2. BitmapFactory.Options options=new BitmapFactory.Options();
  3. options.inJustDecodeBounds = false;
  4. options.inSampleSize = 10; //width。hight设为原来的十分一
  5. Bitmap btp =BitmapFactory.decodeStream(is,null,options);
2、直接调用JNI
     当使用像 imageView.setBackgroundResource,imageView.setImageResource, 或者 BitmapFactory.decodeResource 这种方法来设置一张大图片的时候,这些函数在完毕decode后,终于都是通过java层的createBitmap来完毕的,须要消耗很多其它内存。

因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap。再将其设为ImageView的 source,decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完毕decode。无需再使用java层的createBitmap,从而节省了java层的空间。

假设在读取时加上图片的Config參数,能够跟有效降低载入的内存。从而跟有效阻止抛out of Memory异常。
  另外,须要特别注意:decodeStream是直接读取图片资料的字节码了, 不会依据机器的各种分辨率来自己主动适应。使用了decodeStream之后。须要在hdpi和mdpi,ldpi中配置对应的图片资源,否则在不同分辨率机器上都是相同大小(像素点数量)。显示出来的大小就不正确了。

  1. public static Bitmap readBitMap(Context context, int resId){
  2. BitmapFactory.Options opt = new BitmapFactory.Options();
  3. opt.inPreferredConfig = Bitmap.Config.RGB_565;
  4. opt.inPurgeable = true;
  5. opt.inInputShareable = true;
  6. InputStream is = context.getResources().openRawResource(resId);
  7. return BitmapFactory.decodeStream(is,null,opt);
  8. }
3、手动收回占用资源
     尽管虚拟机会自己主动回收垃圾资源,可是有时候不是那么及时,这时候能够手动回收。

  1. if(!bmp.isRecycle() ){
  2. bmp.recycle() //回收图片所占的内存
  3. system.gc() //提醒系统及时回收
  4. }
4、优化Dalvik虚拟机的堆内存分配
     使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法能够增强程序堆内存的处理效率。
  1. private final static float TARGET_HEAP_UTILIZATION = 0.75f;

在程序onCreate时就能够调用

  1. VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
 就可以。

     除了 优化Dalvik虚拟机的堆内存分配 外,还能够强制定义自己软件的对内存大小。使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例:Dalvik.VMRuntime类,提供对虚拟机全局,Dalvik的特定功能的接口。

Android为每一个程序分配的内存能够通过Runtime类的 totalMemory() 、freeMemory() 两个方法获取VM的一些内存信息。

  1. private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
  2. VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。
  
  下面解说一下怎样自己定义一个类继承于ImageView。首先以CircleButton为例,这是github上一个项目,实现一个圆形有点击效果的按钮。例如以下:
   实现思路是这种。先画两个圆形图案,一个是实心的圆。一个是圆环。圆环半径小于实心圆半径。这样默认就看不到圆环,然后再画出设置的图片,覆盖在二者之上。

最后在按下的时候启动一个属性动画,将圆环放大显示,关于具体的分析能够看android-circlebutton介绍 这篇文章。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

Android ImageView分析并展开的更多相关文章

  1. Android多线程分析之五:使用AsyncTask异步下载图像

    Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...

  2. Android多线程分析之三:Handler,Looper的实现

    Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...

  3. Android多线程分析之一:使用Thread异步下载图像

    Android多线程分析之一:使用Thread异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处   打算整理一下对 Android F ...

  4. Android群英传笔记——第五章:Android Scroll分析

    Android群英传笔记--第五章:Android Scroll分析 滑动事件算是Android比较常用的效果了,而且滑动事件他本身也是有许多的知识点,今天,我们就一起来耍耍Scroll吧 一.滑动效 ...

  5. Android Launcher分析和修改11——自定义分页指示器(paged_view_indicator)

    Android4.0的Launcher自带了一个简单的分页指示器,就是Hotseat上面那个线段,这个本质上是一个ImageView利用.9.png图片做,效果实在是不太美观,用测试人员的话,太丑了. ...

  6. Android Launcher分析和修改12——Widget列表信息收集

    很久没写Launcher分析的文章,最近实在太忙.今天七夕本来是想陪女朋友逛街 ,碰巧打台风呆在家里,就继续写一篇文章.今天主要是讲一下Launcher里面的Widget列表,这方面信息比较多,今天重 ...

  7. [转] Android 性能分析案例

    Android 系统的一个工程师(Romain Guy)针对Falcon Pro  应用,撰写了一个Android性能分析的文章.该文章介绍了如何分析一个应用哪里出现了性能瓶颈,导致该应用使用起来不流 ...

  8. Android多线程分析之中的一个:使用Thread异步下载图像

    Android多线程分析之中的一个:使用Thread异步下载图像 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可.转载请注明出处 打算整理一下对 Android Fr ...

  9. [转]Android ImageView的scaleType属性与adjustViewBounds属性

    Android ImageView的scaleType属性与adjustViewBounds属性   ImageView的scaleType的属性有好几种,分别是matrix(默认).center.c ...

随机推荐

  1. iOS得知1_初体验

    UIView:父类的所有控件,所有的UIView它是一个容器.可容纳其他UIView UIController:用于控制UIView,责创建/销毁自己的UIView,显示/隐藏UIView.处理UIV ...

  2. dell服务器从硬盘导入阵列信息

    前几天去南京客户那里更新新的业务系统,客户要求将服务器上的旧的硬盘拆下来,换上新的硬盘,重新做raid,客户自己要插入旧的硬盘读取旧数据,昨天做了几个实验,两台Dell R710服务器各4块硬盘,一台 ...

  3. java解析String类型t复杂xml,多级节点,最好的例子

    需要用jar包 dom4j-1.6.1.jar 字符串xml如下: <root> <flw> <name>aa</name> <age>22 ...

  4. 2 WAN 和1 Evo/3g Routeros PCC 方法负载平衡

    陕西中际现代包装科技:Routeros  2 WAN 和1 Evo/3g PCC 方法负载平衡 (Routeros多线负载平衡) 我们将要讨论2Wan和1个Evo/3G 的负载平衡.负载平衡就是在不同 ...

  5. Spring实战笔记2---Bean的装配

    创建应用对象之间协作关系的行为通常成为装配,该篇的主要内容有两个,一个Spring装配Bean的几种方式以及Spring表达式,事实上这两者是分不开的,在Spring中,对象无需自己负责查找或者创建与 ...

  6. 逆向 Framework.jar

    Ref:http://www.addictivetips.com/mobile/what-is-odex-and-deodex-in-android-complete-guide/ Ref:http: ...

  7. Java流读写

    写: package com.wjy.write; import java.io.BufferedWriter; import java.io.FileOutputStream; import jav ...

  8. UVA 10404 Bachet's Game(dp + 博弈?)

    Problem B: Bachet's Game Bachet's game is probably known to all but probably not by this name. Initi ...

  9. HTML5特性检測

    HTML5特性检測:    1.检測全局对象:诸如window或navigator是否拥有特定的属性    2.创建元素:检測该元素的DOM对象是否拥有特定的属性    3.创建元素:检測该元素的DO ...

  10. XP下採用DirectShow採集摄像头

    转载请标明是引用于 http://blog.csdn.net/chenyujing1234 欢迎大家提出意见,一起讨论! 须要演示样例源代码的请独自联系我. 前提: 摄像头能正常工作.摄像头有创建di ...