Drawable的getIntrinsicHeight()和getIntrinsicWidth()

今天遇到一个问题,一个Bitmap封装到BitmapDrawable中 ,BitmapDrawable drawable = new BitmapDrawable(bmp),

Bitmap.getWidth() != BitmapDrawable.getIntrinsicWidth().导致一些问题:

查看源代码,问题如下:

在BitmapDrawable中,给mBitmapWidth赋值时,要根据density缩放,其默认值是160,mdpi的情况:

 mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;

而在Bitmap的density是240情况下,将缩放:

公式约等于为:drawableDensity * bmpWidth / bmpDensity  ======>>  160 * 72 / 240  ,所以getIntrinsicHeight()为48

在BitmapDrawable中:

  1. private void computeBitmapSize() {  
  2.       mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity);  
  3.       mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity);  
  4.   }  
  private void computeBitmapSize() {
        mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity);
        mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity);
    }
  1. @Override  
  2.    public int getIntrinsicWidth() {  
  3.        return mBitmapWidth;  
  4.    }  
  5.   
  6.    @Override  
  7.    public int getIntrinsicHeight() {  
  8.        return mBitmapHeight;  
  9.    }  
 @Override
    public int getIntrinsicWidth() {
        return mBitmapWidth;
    }

    @Override
    public int getIntrinsicHeight() {
        return mBitmapHeight;
    }

  1. private BitmapDrawable(BitmapState state, Resources res) {  
  2.         mBitmapState = state;  
  3.         if (res != null) {  
  4.             mTargetDensity = res.getDisplayMetrics().densityDpi;  
  5.         } else if (state != null) {  
  6.             mTargetDensity = state.mTargetDensity;  
  7.         } else {  
  8.             mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;  
  9.         }  
  10.         setBitmap(state.mBitmap);  
  11.     }  
private BitmapDrawable(BitmapState state, Resources res) {
        mBitmapState = state;
        if (res != null) {
            mTargetDensity = res.getDisplayMetrics().densityDpi;
        } else if (state != null) {
            mTargetDensity = state.mTargetDensity;
        } else {
            mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
        }
        setBitmap(state.mBitmap);
    }

在ButtonState中,mTargetDensity的值默认为:

int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;

注意:res == null时,且state != null时,mTargetDensity = state.mTargetDensity;

  1. /** 
  2.     * Create an empty drawable, setting initial target density based on 
  3.     * the display metrics of the resources. 
  4.     */  
  5.    public BitmapDrawable(Resources res) {  
  6.        mBitmapState = new BitmapState((Bitmap) null);  
  7.        mBitmapState.mTargetDensity = mTargetDensity;  
  8.    }  
  9.   
  10.    /** 
  11.     * Create drawable from a bitmap, not dealing with density. 
  12.     * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure 
  13.     * that the drawable has correctly set its target density. 
  14.     */  
  15.    @Deprecated  
  16.    public BitmapDrawable(Bitmap bitmap) {  
  17.        this(new BitmapState(bitmap), null);  
  18.    }  
 /**
     * Create an empty drawable, setting initial target density based on
     * the display metrics of the resources.
     */
    public BitmapDrawable(Resources res) {
        mBitmapState = new BitmapState((Bitmap) null);
        mBitmapState.mTargetDensity = mTargetDensity;
    }

    /**
     * Create drawable from a bitmap, not dealing with density.
     * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure
     * that the drawable has correctly set its target density.
     */
    @Deprecated
    public BitmapDrawable(Bitmap bitmap) {
        this(new BitmapState(bitmap), null);
    }
  1.     /** 
  2.      * Create drawable from a bitmap, setting initial target density based on 
  3.      * the display metrics of the resources. 
  4.      */  
  5.     public BitmapDrawable(Resources res, Bitmap bitmap) {  
  6.         this(new BitmapState(bitmap), res);  
  7.         mBitmapState.mTargetDensity = mTargetDensity;  
  8.     }  
    /**
     * Create drawable from a bitmap, setting initial target density based on
     * the display metrics of the resources.
     */
    public BitmapDrawable(Resources res, Bitmap bitmap) {
        this(new BitmapState(bitmap), res);
        mBitmapState.mTargetDensity = mTargetDensity;
    }

其中,BitmapDrawable(Bitmap bmp)已经被弃用,如果使用 BitmapDrawable(Bitmap bmp,Resources res)构造函数

在DisplayMetrics:

  1.  public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;  
 public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;

在Bitmap中:

  1. /** 
  2.   * Convenience method that returns the width of this bitmap divided 
  3.   * by the density scale factor. 
  4.   * 
  5.   * @param targetDensity The density of the target canvas of the bitmap. 
  6.   * @return The scaled width of this bitmap, according to the density scale factor. 
  7.   */  
  8.  public int getScaledWidth(int targetDensity) {  
  9.      return scaleFromDensity(getWidth(), mDensity, targetDensity);  
  10.  }  
  11.   
  12.  /** 
  13.   * Convenience method that returns the height of this bitmap divided 
  14.   * by the density scale factor. 
  15.   * 
  16.   * @param targetDensity The density of the target canvas of the bitmap. 
  17.   * @return The scaled height of this bitmap, according to the density scale factor. 
  18.   */  
  19.  public int getScaledHeight(int targetDensity) {  
  20.      return scaleFromDensity(getHeight(), mDensity, targetDensity);  
  21.  }  
  22.    
  23.  /** 
  24.   * @hide 
  25.   */  
  26.  static public int scaleFromDensity(int size, int sdensity, int tdensity) {  
  27.      if (sdensity == DENSITY_NONE || sdensity == tdensity) {  
  28.          return size;  
  29.      }  
  30.        
  31.      // Scale by tdensity / sdensity, rounding up.  
  32.      return ( (size * tdensity) + (sdensity >> 1) ) / sdensity;  
  33.  }  
   /**
     * Convenience method that returns the width of this bitmap divided
     * by the density scale factor.
     *
     * @param targetDensity The density of the target canvas of the bitmap.
     * @return The scaled width of this bitmap, according to the density scale factor.
     */
    public int getScaledWidth(int targetDensity) {
        return scaleFromDensity(getWidth(), mDensity, targetDensity);
    }

    /**
     * Convenience method that returns the height of this bitmap divided
     * by the density scale factor.
     *
     * @param targetDensity The density of the target canvas of the bitmap.
     * @return The scaled height of this bitmap, according to the density scale factor.
     */
    public int getScaledHeight(int targetDensity) {
        return scaleFromDensity(getHeight(), mDensity, targetDensity);
    }
    
    /**
     * @hide
     */
    static public int scaleFromDensity(int size, int sdensity, int tdensity) {
        if (sdensity == DENSITY_NONE || sdensity == tdensity) {
            return size;
        }
        
        // Scale by tdensity / sdensity, rounding up.
        return ( (size * tdensity) + (sdensity >> 1) ) / sdensity;
    }

如此,只有做如下改动:

方法一:

BitmapDrawable bmpDrawable = new BitmapDrawable(bmp,getResources);

方法二:

BitmapDrawable bmpDrawable = new BitmapDrawable(bmp);

bmpDrawable.setTargetDensity(getResources().getResources().getDisplayMetrics());

借鉴: http://blog.csdn.net/jason_wks/article/details/8283224

原文地址:https://www.cnblogs.com/ldq2016/p/5377670.html