转载请标明出处:
http://blog.csdn.net/xuehuayous/article/details/51671937
本文出自:【Kevin.zhou的博客】

前言:在《Android 关于屏幕的一些事儿》中最后提到了开发中我们比较头疼的问题--屏幕适配,本文将提供一种比较简单粗暴并且行之有效的解决方案。

一、问题回顾

《Android 关于屏幕的一些事儿》中详细分析了android开发中关于适配的一些常识,如果之前没有了解过建议先阅读下。
我们提出的问题在OPPO 1107上想要达到屏幕宽度的一半我们要写160dp,而在MI3中我们却要写180dp,那么我们到底要写多少才是真正的一半呢?

当然是具体的写多少都是有问题的,由于一般开发中都是默认屏幕的宽度是320dp的,那么能不能我写160px在所有的设备上都是显示占屏幕宽度的一半呢?
    基于这个想法,我们来开启今天的讨论。

二、解决思路

由于不同的设备并不是都以320dp为基准的,为什么会出现这种状况就要讨论屏幕分辨率以及屏幕ppi等概念,由于之前博客中有详细说明,这里就不再赘述。
    那么我们可以进行一次缩放适配,屏幕宽度以320dp为基准,屏幕真实的dp数目 / 320 就是缩放比例系数,用这个系数对布局中精确值定义的控件进行缩放就可以达到适配的目的。
    比如:在MI3中,竖屏时真实宽度dp数目为360dp,除以 320dp的基准得到的缩放比例为 1.125,那么将宽度为160dp 的乘以 1.125 得到 180dp。

三、代码编写

1. 获取屏幕真实dp数

/*** 获取屏幕可操作区域宽度dp数目** @param activity* @return*/
private float getScreenWidthDp(Activity activity) {DisplayMetrics displayMetrics = new DisplayMetrics();activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);return displayMetrics.widthPixels / displayMetrics.density;
}

2. 计算缩放比例

scale = getScreenWidthDp(activity) / 320.0f;

3. 遍历布局

/*** 缩放View* @param view
*/
public void scaleView(View view) {if(null != view && scale != 1.0f) {// TODO:重新设置View大小if(view instanceof ViewGroup) {scaleView((ViewGroup) view);}}
}/*** 缩放ViewGroup* @param viewGroup
*/
public void scaleView(ViewGroup viewGroup) {
if(null != viewGroup && scale != 1.0f) {
for (int i = 0; i < viewGroup.getChildCount(); i++) {scaleView(viewGroup.getChildAt(i));
}}
}

4. 重新设置View大小

/*** 重新设置View大小* @param view*/
private void resetViewSize(View view) {ViewGroup.LayoutParams layoutParams = view.getLayoutParams();if(null != layoutParams) {if(layoutParams instanceof ViewGroup.MarginLayoutParams) {// TODO:对margin进行缩放}if(layoutParams.width != ViewGroup.LayoutParams.MATCH_PARENT&& layoutParams.width != ViewGroup.LayoutParams.WRAP_CONTENT) {// TODO:宽度为精确值时进行缩放}if(layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT&& layoutParams.height != ViewGroup.LayoutParams.WRAP_CONTENT) {// TODO:高度为精确值时进行缩放}view.setLayoutParams(layoutParams);}// TODO:对padding进行缩放// TODO:对字体进行缩放
}

5. 缩放函数

private int resetWidth(int width) {return (int) (width * scale);
}private int resetHeight(int height) {return (int) (height * scale);
}private float resetTextSize(float textSize) {return textSize * scale;
}

经过以上几个步骤,我们简单粗暴的屏幕适配就完成啦。

四、完整代码

/*** 版权所有:XXX有限公司** ScaleHelper** @author zhou.wenkai ,Created on 2016-6-14 11:17:54*           Major Function:<b>布局适配帮助类</b>**         注:如果您修改了本类请填写以下内容作为记录,如非本人操作劳烦通知,谢谢!!!* @author mender,Modified Date Modify Content:*/
public class ScaleHelper {// 默认屏幕宽度基准private float screenWidthDp = 320.0f;// 缩放比例private float scale;public ScaleHelper(Activity activity) {if(null == activity) {throw new IllegalArgumentException("activity must`t be null!");}scale = getScreenWidthDp(activity) / screenWidthDp;}/*** 获取屏幕可操作区域宽度dp数目** @param activity* @return*/private float getScreenWidthDp(Activity activity) {DisplayMetrics displayMetrics = new DisplayMetrics();activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);return displayMetrics.widthPixels / displayMetrics.density;}/*** 缩放View* @param view*/public void scaleView(View view) {if(null != view && scale != 1.0f) {resetViewSize(view);if(view instanceof ViewGroup) {scaleView((ViewGroup) view);}}}/*** 缩放ViewGroup* @param viewGroup*/public void scaleView(ViewGroup viewGroup) {if(null != viewGroup && scale != 1.0f) {for (int i = 0; i < viewGroup.getChildCount(); i++) {scaleView(viewGroup.getChildAt(i));}}}/*** 重新设置View大小* @param view*/private void resetViewSize(View view) {ViewGroup.LayoutParams layoutParams = view.getLayoutParams();if(null != layoutParams) {// 对margin进行缩放if(layoutParams instanceof ViewGroup.MarginLayoutParams) {ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) layoutParams;marginLayoutParams.leftMargin = resetWidth(marginLayoutParams.leftMargin);marginLayoutParams.topMargin = resetHeight(marginLayoutParams.topMargin);marginLayoutParams.rightMargin = resetWidth(marginLayoutParams.rightMargin);marginLayoutParams.bottomMargin = resetHeight(marginLayoutParams.bottomMargin);}// 宽度为精确值时进行缩放if(layoutParams.width != ViewGroup.LayoutParams.MATCH_PARENT&& layoutParams.width != ViewGroup.LayoutParams.WRAP_CONTENT) {layoutParams.width = resetWidth(layoutParams.width);}// 高度为精确值时进行缩放if(layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT&& layoutParams.height != ViewGroup.LayoutParams.WRAP_CONTENT) {layoutParams.height = resetHeight(layoutParams.height);}view.setLayoutParams(layoutParams);}// 对padding进行缩放view.setPadding(resetWidth(view.getPaddingLeft()),resetHeight(view.getPaddingTop()),resetWidth(view.getPaddingRight()),resetHeight(view.getPaddingBottom()));// 对字体大小进行缩放if(view instanceof TextView) {((TextView)view).setTextSize(0, resetTextSize(((TextView) view).getTextSize()));}}private int resetWidth(int width) {return (int) (width * scale);}private int resetHeight(int height) {return (int) (height * scale);}private float resetTextSize(float textSize) {return textSize * scale;}}

五、使用步骤

1. 初始化ScaleHelper

ScaleHelper scaleHelper = new ScaleHelper(MainActivity.this);

2. 对需要适配的布局进行适配

scaleHelper.scaleView(view);

六、效果预览

布局分为上下两部分,以上部分为参照,下部分进行布局适配,在OPPO 1107上屏幕宽度dp和宽度基准320dp相同不做处理,在MI3上进行适配后就达到了和OPPO 1107上相同的效果。

想到以前做项目布局要求极其严格,那些设计测试恨不得1px都能看得出来,所以不得已又大段大段的代码适配布局,看下用了该工具的效果:

对比上下两张卡,在MI3的设备时使用布局适配后,效果还是非常明显的!!!

七、源码及示例

给大家提供一个github的地址: Android-ScaleHelper

另外,欢迎 star or f**k me on github!  

八、一行引入库

如果您的项目使用 Gradle 构建, 只需要在您的build.gradle文件添加下面一行到 dependencies :

compile 'com.kevin:scalehelper:1.0.0'

Android 屏幕适配的一种方案相关推荐

  1. Android屏幕适配的两种方式

    ScreenHelper github 地址:github.com/bugyun/Scre- 欢迎 star 和 提问. 第一种适配方式 - sw 方式 插件版本: 使用方法 在项目的根 build. ...

  2. Android屏幕适配(网易云音乐方案)

    简单高效无侵入式Android屏幕适配 最近在学习网易的Android课程,网易的老师提供了网易云音乐的屏幕适配解决方案,主要有两种,17年前是采用自定义缩放布局,17年后是采用的是工具类发方案,现在 ...

  3. android屏幕适配的五种方式_讲一讲Android 9.0系统的新特性,对刘海屏设备进行适配...

    黑客技术点击右侧关注,了解黑客的世界! Java开发进阶点击右侧关注,掌握进阶之路! Python开发点击右侧关注,探讨技术话题!作者丨郭霖来源丨郭霖(guolin_blog) 其实Android 9 ...

  4. android屏幕适配的五种方式,价值2000元的学习资源泄露,附答案

    开头 作为一个40的人,能有面试机会是格外的珍惜,也分外的诚恳.没什么豪言壮语,雄心大志.没有狼性,社会把中年人打磨成了听话的舔狗. 感谢马爸爸旗下公司,给了我为数不多机会中一个,而且还是个相当好的位 ...

  5. android屏幕适配教程,Android屏幕适配方案,android屏幕适配

    Android屏幕适配方案,android屏幕适配 文章转载禁止用于商业用途,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处莫高雷草原以及作者@JiongBull. Android屏幕适配方 ...

  6. 2021年最详细的Android屏幕适配方案汇总

    1 Android屏幕适配的度量单位和相关概念 建议在阅读本文章之前,可以先阅读快乐李同学写的文章<Android屏幕适配的度量单位和相关概念>,这篇文章包含了阅读本文的一些基础知识,推荐 ...

  7. Android屏幕适配方案

    一. 手机适配的应用和使用场景 使android应用程序适用于不同的国家语言.型号.尺寸和SDK版本等手机环境中,其主要功能和界面风格保持不变. 手机适配主要包括三个方面:语言适配.屏幕适配.SDK平 ...

  8. Android 屏幕适配方案(七)

    原文地址为: Android 屏幕适配方案(七) 一. 手机适配的应用和使用场景 使android应用程序适用于不同的国家语言.型号.尺寸和SDK版本等手机环境中,其主要功能和界面风格保持不变. 手机 ...

  9. android屏幕适配的目的,剖析Android屏幕适配及各方案

    最近陆陆续续被一些android屏幕适配的文章刷屏了,我发现有些问题在看别人写的文章时候还是比较不容易理解的,在这里我们把这些东西捋一捋,来讲讲android屏幕适配的原理,还有之前用过的屏幕适配框架 ...

最新文章

  1. 业务工作流平台设计(七)
  2. 国内代码托管平台(Git)
  3. 未能加载文件或程序集“Antlr3.Runtime”或它的某一个依赖项。参数错误。 (异常来自 HRESULT:0x80070057 (E_INVALIDARG))解决方法。...
  4. 未能加载包studio package_Xrepo:一个现代化的跨平台 C/C++ 包管理器
  5. [MEGA DEAL] Ultimate Java开发和认证指南(59%折扣)
  6. ASP正则表达式方面小笔记
  7. python智慧树判断题_智慧树_大数据分析的python基础_判断题答案
  8. 解决Mac App Store下载软件一直转圈无法完成的问题,黑白苹果均有效
  9. 哈工大同义词词林 python 使用范例
  10. PHP中MySQLi的配置PHP使用mysqli连接mysql的方法
  11. ICCV 2017:训练GAN的16个技巧,2400+星(PPT)
  12. win11共享打印机无法连接怎么办
  13. 专科大学计算机基础,2013-2014大学计算机基础教学大纲含AB专科.doc
  14. 一瓶纯粮酱香型白酒的成本是多少?
  15. 如何对复杂网络建模所需要的数据进行预处理
  16. 云服务器和vps二者的区别
  17. Java-pdf无限压缩方案-优化内存问题
  18. 微信公众号流量入口-搜索排名
  19. 导入excel并返回失败清单
  20. Agile-bpm工作流

热门文章

  1. 数据结构与算法之倒推算法
  2. Leetcode377(力扣377):组合总和
  3. ImmunoChemistry艾美捷高级钙素AM细胞活力试剂盒方案
  4. 从Matlab .fig文件中读取数据,并重新绘图
  5. 27.大数据---Hive的数据库和表的基本操作;脚本化运行;内部表;外部表;分区表
  6. successful sensing probability
  7. 后端人眼中的Vue(三)
  8. 二叉搜索树--基础篇
  9. 数据分析05:数据建模及模型评估
  10. Unity 游戏实例开发集合 之 Circus (马戏团) 休闲小游戏快速实现