您的位置:首页 > 移动开发 > Android开发

Android在java代码中实现图片屏幕适配

2015-02-02 20:16 656 查看
在PC端界面布局适配时,我们只需关注分辨率,也就是像素(px),通常来说分辨率越高,屏幕尺寸也越大。但在手机上,考虑到人手的操作体验,不会过分的放大屏幕的尺寸。但是屏幕也有不断提高视觉细腻效果的需求,也就是提高分辨率。所以同样5英寸的屏幕大小,分辨率有1280x720(720P)的,也有1980x1080(1080P)的,甚至2560x1440(2K)的。

这时单靠像素(px)已经不能描述了,所以在手机屏幕上引入了点数(dp)的概念:即“一个英寸范围内的像素个数”,所以如果我们仍然以像素(px)来描述一张图片的大小,在同样5英寸屏幕大小下,dp值低(分辨率也低)的屏幕下显的很大,而在 dp值高(相应的分辨率也很高)的屏幕下反而很小,这样就不能得到一致的视觉效果了。

通常一个控件尺寸如果不是根据math_parent或wrap_content进行自适应,我们会通过dp值设定一个具体尺寸。而在设计UI界面图片时,一个好的做法,通常我们会先针对某个具体机型的屏幕进行设计确定图片的尺寸大小。然后根据这个机型的屏幕尺寸值来确定具体的资源目录。比如我们的app项目按照小米2s的尺寸(720p)进行UI设计,然后将切割好的图片放到res/drawable-xhdpi中,android系统会根据运行机器的屏幕分辨率和ppi值进行自行缩放。

所以如果图片是放在项目的资源目录(res下的某个drawable前缀的目录)里,只要我们放对目录,android系统会帮我们进行屏幕适配。但有的时候图片是从sd卡或者assets目录中,或者网络上加载的,这时候需要在java代码中进行图片加载,而不是从xml配置文件中加载图片,会是怎样的情况呢?我们先看下面的代码:

private void displayFigure(ImageView imageView){
Bitmap bm = null;
try{
//从assets目录中读取图片
InputStream is = getAssets().open("mm08.png");
bm = BitmapFactory.decodeStream(is);

if(bm != null)
imageView.setImageBitmap(bm);
}catch (OutOfMemoryError err){
System.gc();
} catch (IOException e) {
e.printStackTrace();
}
}


运行结果如下:


(上面同样是5寸屏幕,左边是720p,右边是1080p)

我们发现在java代码中加载图片,是按照图片的像素尺寸来设定大小的。这里我们需要的是将像素(px)转换成点数(dp)。android中工具类TypedValue中提供了相应的方法:
public static float applyDimension(int unit, float value, android.util.DisplayMetrics metrics)

unit 参数是TypedValue类的一个常量,指需要将像素转化为哪个单位类型,我们需要将像素转换成点数,所以使用TypedValue.COMPLEX_UNIT_DIP常量;
value 参数指需要转换的具体像素值;
metrics 参数对象中保存当前机器屏幕信息,在进行单位转换时需要依赖其中的屏幕信息。

我们把代码调整如下:
private void displayFigure(ImageView imageView){
Bitmap bm = null;
try{
//从assets目录中读取图片
InputStream is = getAssets().open("mm08.png");
bm = BitmapFactory.decodeStream(is);

if(bm != null) {
imageView.setImageBitmap(bm);

//将px转换成dp,并重新设置ImageView的布局尺寸
DisplayMetrics metrics = getResources().getDisplayMetrics();
int width = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, bm.getWidth(), metrics);
int height = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, bm.getHeight(), metrics);

imageView.getLayoutParams().width = width;
imageView.getLayoutParams().height = height;
}
}catch (OutOfMemoryError err){
System.gc();
} catch (IOException e) {
e.printStackTrace();
}
}


这时我们再看看效果:



这样在同样屏幕大小下,我们所得到的视觉效果是一致的(不受分辨率和ppi值的影响)。

最后我们看看applyDimension方法的原代码:

public static float applyDimension(int unit, float value,
DisplayMetrics metrics)
{
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}


其中一目了然,同样我们也可以在代码中设定字体sp值,以保证各个屏幕之间的适配。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐