Android和Pixels与设备指标

时间:2013-09-17 17:46:32

标签: android

我有一个让我疯狂的问题。

我有4个函数可以使用密度(1.5)和视图,位图,屏幕等报告的宽度/高度值,在UI之间正确调整图像大小。

这在SG II上表现非常出色。但是在报道密度为0.75的HTC Wildfire上...... 一些图像在屏幕上看起来太小了25%......但是当我决定将密度覆盖到1.0时,这些图像突然变得合适而其他图像突然变得合适清脆,但不再正确的大小......它让我疯狂......

我只能参与帽子我比较苹果和梨子(像素和DIPs),但我不能让我的测试符合我的阅读,所以努力100%肯定一些事情:< / p>

...

我会在这里获得像素吗?还是DIP? :

int bitmapWidth = bitmap.getWidth();

假设underneat是包含位图的imageview。像素或DIP?

int widthParent = view.getWidth();      

下面实际上是DIP,对吧?

getContext().getResources().getDisplayMetrics().widthPixels;

...

这是我的代码无法正常工作(此代码提供的位图在视觉上可能需要2 / 3s宽度,应该占用100%)如果检查注释,像素值显然是正确的,但最终结果不正确:

vto.addOnGlobalLayoutListener(
  new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
      mainLogo.getViewTreeObserver().removeGlobalOnLayoutListener(this);                                                                 
      mainLogo.setScaleType(ImageView.ScaleType.CENTER_INSIDE); // mainLogo = ImageView
      SharedCode.sharedUtilScaleImage_Width(mainLogo, false);              
    }
  }                        
);                                   

// ...

public static void sharedUtilScaleImage_Width(ImageView view, boolean tryBackground)
  {
    Drawable drawing = null;
    boolean useBackground = false;         
    if (drawing == null) {    
      drawing = view.getDrawable();
    }          
    if (drawing == null) {    
      if (tryBackground) {
        drawing = view.getBackground();
        useBackground = true;
      }
    }      
    if (drawing == null) {
      return; 
    }        
    if (!(drawing instanceof BitmapDrawable)) {
      return; 
    }                      
    Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
    if (bitmap == null) {
      return;
    }
    //--                               
    int bitmapWidth = bitmap.getWidth(); // returns 770 (which is correct checking on disk)
    int bitmapHeight = bitmap.getHeight();                
    // float density = 1;
    // density = MicApp.getContext().getResources().getDisplayMetrics().density; // 1.5          
    float widthScreen = MicApp.getContext().getResources().getDisplayMetrics().widthPixels; // returns 480              
    int widthParent = view.getWidth(); // returns 480, should be same as screen      
    //--
    float xScale = ( (float) widthParent / (float) bitmapWidth); 
    Matrix matrix = new Matrix();
    matrix.postScale(xScale, xScale);
    //--
    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, true);
    int bitmapWidth2 = scaledBitmap.getWidth(); // 480
    int bitmapHeight2 = scaledBitmap.getHeight();      
    //--          
    BitmapDrawable result = new BitmapDrawable(scaledBitmap);          
    //--          
    if (useBackground) {
      LayoutParams layoutparams = new LayoutParams(bitmapWidth, bitmapHeight);
      view.setLayoutParams(layoutparams);
      view.setBackgroundDrawable(result);
    }
    else {
      view.setImageDrawable(result);
    }            
  }

1 个答案:

答案 0 :(得分:1)

解码图像和显示图像之间有几个步骤。这些步骤通常用于以正确的比例显示来自资源的图像。如果您将图像放在/res/drawable-mdpi/中而不放在其他文件夹中,则它仍然可以在具有其他密度的设备上以正确的尺寸显示。

如果您要在mdpi(320dpi)设备上加载适用于x-hdpi(160dpi)的图像,并希望它以相同的尺寸显示,则需要将其加倍像素大小有效。例如。 100x100像素的图像需要以200x200像素显示。

参与缩放的地方是

  • 解码图像(参见例如BitmapFactory.Options#inDensity)。 BitmapFactory已经可以将100x100 png图像解码为200x200图像。
  • Bitmap自己的密度。这是每个位图的属性,它用于存储图像的密度。如果BitmapFactory将100x100 mdpi图像解码为200x200,那么densitiy基本上会说“我是x-hdpi”。您还可以在解码时禁用缩放,并获得具有mdpi密度的100x100图像。显示该图像需要绘制以2x缩放的图像。
  • BitmapDrawable的目标密度,通常是设备的密度。如果BitmapDrawable必须绘制密度不匹配的Bitmap,则会绘制缩放版本。

来自BitmapDrawable的代码,mTargetDensity应为设备密度。

private void computeBitmapSize() {
    mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity);
    mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity);
}

来自BitmapmDensity的相关内容是位图的密度

public int getScaledWidth(int targetDensity) {
    return scaleFromDensity(getWidth(), mDensity, targetDensity);
}

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;
}
  • 缩放选项,例如ImageView。如果要显示一个ImageDrawable,表示ImageView内部(由于缩放或实际)200x200像素在屏幕上实际为400x300像素的图像,则需要再次缩放图像。 / LI>

使用ImageView.ScaleType.CENTER_INSIDE会以200x200像素绘制图像,因为CENTER_INSIDE仅在图像大于视图时缩放图像。 FIT_CENTER会将其扩展到300x300。只有CENTER根本无法扩展。它只是中心。

CENTER_INSIDE +上面的100x100 mdpi图像仍会将其绘制为200x200px,因为BitmapDrawable / Bitmap中存储了所有比例因子。

BitmapFactory&gt;中还有其他几个地方。 Bitmap&gt; BitmapDrawable&gt; ImageView链就像{/ 1}}构造函数那样

  

在API级别4中不推荐使用此构造函数。使用BitmapDrawable(Resources,Bitmap)确保drawable已正确设置其目标密度。

可能会以不希望的方式影响图像缩放。

- &GT;防止所有缩放

  • 无缩放解码
  • 确保您的位图密度是当前设备密度或仅BitmapDrawable(Bitmap bitmap)
  • 通过Bitmap#setDensity(Bitmap.DENSITY_NONE)进行绘制时不要应用缩放。