Android设备上,我们一般适配图片的常用方案,都基本是在较大分辨率的条件下准备一张较大的图片。比如设计图是1920*1080下的100*100的图片,我们一般可以在xxhdpi,xhdpi,hdpi,mdpi屏幕密度下的mipmap下放入300*300,200*200,150*150,100*100的图片。通常我们一般都是选取较大的的那个密度下的图片(也就是xxhdpi下的300*300这张图片)。这样不管是小分辨率,还是任意屏幕密度下的Android设备,只要ImageView宽度,高度都不大于100px,图片一般都不会失真。不过有些情况,限制不了控件大小的时候,可能会放大到失真(缩小不考虑)(比如一些自定义控件属性或者drawble文件下的某些xml自定义图案的时候引用图片有可能限制不了宽高)。

先上代码和图片

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical">

android:id="@+id/iv"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@mipmap/test960_540" />

android:id="@+id/tv"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="像素密度信息" />

public class MainActivity extends AppCompatActivity {

private ImageView iv;

private TextView tv;

private String strInfo = "";

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initView();

BitmapDrawable bitmapDrawable = (BitmapDrawable) iv.getDrawable();//layout 中获取图片信息

final Bitmap bitmap = bitmapDrawable.getBitmap();

final float density = getResources().getDisplayMetrics().density * 160;

//java中获取图片信息

BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.mipmap.test960_540);

final Bitmap bitmap2 = drawable.getBitmap();

iv.post(new Runnable() {

@Override

public void run() {

strInfo += "屏幕像素密度=" + density + "dpi\n";

strInfo += "图片:width=" + bitmap.getWidth() + "px\n";

strInfo += "图片:height=" + bitmap.getHeight() + "px\n";

strInfo += "图片1:width=" + bitmap2.getWidth() + "px\n";

strInfo += "图片1:height=" + bitmap2.getHeight() + "px\n";

strInfo += "iv:width=" + iv.getWidth() + "px\n";

strInfo += "iv:height=" + iv.getHeight() + "px\n";

tv.setText(strInfo);

tv.setTextSize(50 / getResources().getDisplayMetrics().density);

}

});

// 密度范围 比例

// ldpi 0dpi -120dpi 0.75

// mdpi 120dpi-160dpi 1

// hdpi 160dpi-240dpi 1.5

// xhdpi 240dpi-320dpi 2

// xxhdpi 320dpi-480dpi 3

// xxxhdpi 480dpi-640dpi 4

}

private void initView() {

iv = (ImageView) findViewById(R.id.iv);

tv = (TextView) findViewById(R.id.tv);

}

}

资源目录

d48152b3f24a

截图2.PNG

xxhdpi和mdp设备下的运行效果

d48152b3f24a

截图1.PNG

最后再看图片在xxdpi文件下的情况

资源目录

d48152b3f24a

截图4.PNG

xxhdpi和mdp设备下的运行效果

d48152b3f24a

截图3_图片只在xxhdpi文件夹的情况.PNG

从代码和图片中可以看到,只是放了一张960*540的图片在mdpi情况下,ImageView宽高设置成自适应了。然后xxhdpi设备中不管是从layout中还是用java动态获取图片信息,发现bitmap大小都是960*540。mdpi的设备也是一样。

现在我们来分析一下,为什么会这样?

我们知道960*540的图片,我们放在了mdpi文件夹下,

第一种:在mdpi设备的环境下,设备会优先找mdpi下的图片(如果mdpi文件夹下没找到相应图片,会按顺序找xhdpi->xxhdpi->xxxhdpi,此时如果还没找到图片,会往下接着找ldpi以此类推找到这张图片),此时在mdpi中直接发现了这张图且和设备自身屏幕密度一样160dpi(mdpi),所以iv和bitmap不会进行放缩。此时读出的图片就是960*540的。

第二种:xxhdpi的设备中,我们也只能在mdpi中找到图片,此时由于设备密度大于资源文件下的密度,而且设备会认为我们已经做好图片的适配,所以直接给我们iv宽高各放大了3倍,但bitmap还是960*540。

从代码和图片中可以看到,只是放了一张960*540的图片在xxhdpi情况下,ImageView宽高设置成自适应了。然后mdpi设备中不管是从layout中还是用java动态获取图片信息,发现bitmap大小在小密度的设备(mdpi)中宽高各缩小了1/3。xxhdpi的设备读取都完全正常。

现在我们来分析一下,为什么会这样?

我们知道960*540的图片,我们放在了xxhdpi文件夹下,

第一种:在mdpi设备的环境下,设备在xxhdpi的文件夹下找到了图片,此时在xxhdpi中直接发现了这张图且和设备自身屏幕密度差了3倍(mdpi),所以bitmap会缩放1/3。此时读出的图片就是320*180。

第二种:xxhdpi的设备中,我们就不讨论了,因为对应自己资源文件夹下有图片就不会进行缩放。

总结

如果图片在低密度资源文件夹,在高密度设备上访问,iv如果设置成自适应,会自动放大。但是不管是在通过layout,还是直接java中直接访问这个图片文件,这个图片读出来的宽高还是真实大小。(记忆的话就当bitmap想放大,但不会超过自身真实宽高)。

如果图片在高密度资源文件夹,在低密度设备上访问,iv如果设置成自适应,会自动缩小(由于bitmap缩小导致)。而且不管是在通过layout,还是直接java中直接访问这个图片文件,这个图片读出来的宽高是缩小过后的。(记忆的话就当bitmap想缩小,且不会超过自身真实宽高)。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐