三句话适配android设备
①将(https://github.com/wenzb/ScreenAdaptive/tree/master/app/src/main/res)的values-sw320dp、values-sw360dp、values-sw431dp、values-sw480dp、values-sw540dp文件夹copy到项目res文件夹下。
②在布局文件用到dp时改成使用"@dimen/dp_**"形式,如:android:layout_width="200dp"改成android:layout_width="@dimen/dp_200"。
③在布局文件下Design选用Nexus4(4.7,768x1280,xhdpi)查看布局基准调整布局
适配原理
屏幕适配有多种方案这里选用dp适配方案,即使用不同values-sw**dp命名
sw指的是最小屏幕宽度即是手机屏幕宽度的dp值
在values的dimens.xml定义变量值引用如:<dimen name="dp_1">1.3dp</dimen>,android系统会根据屏幕的相关信息去取对应变量值
假设屏幕是属于sw360dp取出dp_1为1dp,假设屏幕属于480dp取出dp_1为1.3dp,通过这种方式从而实现屏幕适配
如何根据原理适配
android中各种单位的含义:
px:(像素) 屏幕上的小灯泡,假设是1920x1080可以理解为横向有1080个小灯泡排列
sp: scaled pixels(放大像素). 用于字体显示,会根据系统字体大小设置改变
dp(dip): (设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关
dpi:屏幕密度,每英寸(2.54cm)所含像素点,相当于ios的ppi,
density:概念跟dpi是一样,都是屏幕密度只是数值上等于dpi/160,余数不足时进0.5,假设148dpi/160 density=1 假设220dpi/160 density=1.5
dp跟dip是一样的,这个单位比较难理解但是根据运算公式:dp=px/(dpi/160) 或者是dp=px/density,dp跟像素还有屏幕密度有关,假设屏幕密度一定,当然屏幕越长或者说越多的像素dp值就增大
假设像素一定,分辨率越小dp就越大,同是假设1920x1080的6寸屏幕跟1920x1080的14寸平板,他们的屏幕长度不一样导致dpi不一样,所以根据公式可以知道这个1920x1080的14寸平板比1920x1080的6寸手机dp值大得多
谷歌提供的方案
核心是根据设备相关信息去取不同的res文件夹,如上面的例子,是根据不同sw取不同的资源文件,文件夹命名如下:
values-mcc310-en-sw320dp-w720dp-h720dp-large-long-port-car-night-ldpi-notouch-keysexposed-nokeys-navexposed-nonav-v7
属性是按优先级匹配先后排列出来的,各种含义:
values-mcc310(sim卡运营商)-en(语言)-sw320dp(屏幕最小宽度)-w720dp(屏幕最佳宽度)-h720dp(屏幕最佳高度)-large(屏幕尺寸)-long(屏幕长短边模式)-port(当前屏幕横竖屏显示模式)-car(dock模式)-night(白天或夜晚)-ldpi(屏幕最佳dpi)-notouch(触摸屏模类型)-keysexposed(键盘类型)-nokey(硬按键类型)-navexposed(方向键是否可用)-nonav(方向键类型)-v7(android版本)
假设我是横屏,屏幕是1920x1080 android系统就会去解析values-1920x1080-prot文件
同理layout文件夹也适用,所以在你开发项目的时候一定要知道你的app是会适用在哪些屏幕,如果你App运行在values-sw480dp的设备,但是你没有定义values-sw480dp文件,就会去解析相近sw-480dp的,最后都没有就会去匹配默认values
生成适配文件
public class MainActivity extends AppCompatActivity {
DecimalFormat df = new DecimalFormat("0.0");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
saveDimens(320);
saveDimens(360);
saveDimens(431);
saveDimens(480);
saveDimens(540);
saveDimens(768);
saveDimens(1080);
}
}).start();
}
/**
* 以sw360dp为基准在sd卡根目录生成对应dimens.xml 文件
*/
private void saveDimens(int swDp){
String str="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n";
for (int i = 1; i <= 640; i++) {
double a=i;
String b=df.format(a*swDp/360);
str+="<dimen name=\"dp_"+i+"\">"+b+"dp</dimen>\n";
}
str+="</resources>";
File file=new File(Environment.getExternalStorageDirectory()+"/"+"values-sw"+swDp+"dp");
if (!file.exists()){
file.mkdirs();
}
byte[] buff=str.getBytes();
try {
FileOutputStream out=new FileOutputStream(file.getPath()+"/dimens.xml");
out.write(buff, 0, buff.length);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行上面的代码,几秒后进入手机根目录copy出来放到项目。
生成文件后,布局文件如下在各个手机屏幕上的效果
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<TextView
android:id="@+id/textView"
android:layout_width="@dimen/dp_300"
android:layout_height="@dimen/dp_200"
android:background="#f4546a"
android:gravity="center"
android:text="你好 世界"
android:textColor="#ffffff"
android:textSize="30sp" />
</LinearLayout>
授之于渔
是否有疑问这个320 360 431 480 540 是怎么来的?
这是目前市面上的主流手机dp值多去算算就知道了
假设android后面发展有其他奇葩或者更高清的屏幕,只需要改一下生成适配代码重新生成就可以了
同理如果要用px方案适配,生成类似values-1920x1080是一样的做法
为什么不使用px方案不是更精准吗?市面上的手机之间的px相差太大,比如480x800跟1440x2560,px适配方案可能在在不同的设备相差会几倍 ,如果处理不好布局就会大乱,而且很多奇葩分辨率,但dp就算是有问题相差也少看起来问题不大,总的来说dp设配比较稳