Android屏幕自适应2

简介: Android屏幕自适应

Android屏幕自适应1:https://developer.aliyun.com/article/1473627

3. Java代码中设置宽高

示例代码

activity_main.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <Button  
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#000000"
    android:text="按钮1"/>
  <Button  
    android:id="@+id/btn2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:text="btn2"/>
  <Button  
    android:id="@+id/btn3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#ff0000"
    android:text="btn3"/>
  <Button  
    android:id="@+id/btn4"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#ff00ff"
    android:text="btn4"/>   
</LinearLayout>

MainActivity.java 文件

// app启动时先获取当前屏幕的宽高
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
phoneWidth = displayMetrics.widthPixels;
phoneHeight = displayMetrics.heightPixels;

// 设置控件大小
// 第一个按钮,宽度100%,高度10%
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
    LayoutParams.MATCH_PARENT,(int) (phoneHeight * 0.1f + 0.5f));
btn1.setLayoutParams(params);

// 第二个按钮,宽度100%,高度30%
LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(
    LayoutParams.MATCH_PARENT,(int) (phoneHeight * 0.3f + 0.5f));
btn2.setLayoutParams(params2);

// 第三个按钮,宽度50%,高度20%
LinearLayout.LayoutParams params3 = new LinearLayout.LayoutParams(
    (int) (phoneWidth * 0.5f + 0.5f),(int) (phoneHeight * 0.2f + 0.5f));
btn3.setLayoutParams(params3);

// 第三个按钮,宽度70%,高度填满剩下的空间
LinearLayout.LayoutParams params4 = new LinearLayout.LayoutParams(
    (int) (phoneWidth * 0.7f + 0.5f),LayoutParams.MATCH_PARENT);
btn4.setLayoutParams(params4);

4. smallestWidth

sw限定符适配(需要安装 SmallestWidth Dimens 插件),依据最小宽度限定符,指的是 Android 会识别屏幕宽度最小尺寸的 dp 值(其实就是手机的宽度值),然后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。


这个可以使用 Android Studio 里的 SmallestWidth Dimens 插件来完成。

需要注意的是,如果没有 values-sw360dp 文件夹,系统会向下寻找,比如离 360dp 最近的只有 values-sw340dp,那么系统就会选择 values-sw340dp 文件夹下的资源文件;

5. 多layout适配

多layout适配主要是针对某个分辨率,新建一个layout文件夹

6. 今日头条适配方案

适配方案的核心原理在于根据dp和px的转换公式 :px = dp * density,不管我们设定的单位是什么, 最终我们都会将这些单位长度转化为px的。

density就是他们的转化比, 所以,动态改变这个转化比也是可以达到我们适配屏幕的目的。

通过修改density值,强行把所有不同尺寸分辨率的手机的宽度dp值改成一个统一的值(在清单文件中定义),这样就解决了所有的适配问题;


Density = 当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) ;

例:分辨率1080x1920,dpi为480,正常情况下计算density=dpi/160=480/160=3,此时屏幕总宽度dp=px/density=1080/3=360;


一般的应用场景就是在BaseActivity的onCreate方法中调用,即可达成全局适配;

/// 在Activity中的onCreate方法中调用,必须在setContentView()之前
CustomDensityUtil.setCustomDensity(MainActivity.this, getApplication());

今日头条适配方案工具类

public class CustomDensityUtil {
   // 系统的Density
   private static float sNoncompatDensity;
   // 系统的ScaledDensity
   private static float sNoncompatScaledDensity;

   /**
    * 今日头条适配方案
    *
    * @param activity
    * @param application
    */
   public static void setCustomDensity(Activity activity, final Application application) {
       //通过资源文件getResources类获取DisplayMetrics
       DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
       if (sNoncompatDensity == 0) {
           //保存之前density值
           sNoncompatDensity = appDisplayMetrics.density;
           //保存之前scaledDensity值,scaledDensity为字体的缩放因子,正常情况下和density相等,但是调节系统字体大小后会改变这个值
           sNoncompatScaledDensity = appDisplayMetrics.scaledDensity;
           //监听设备系统字体切换
           application.registerComponentCallbacks(new ComponentCallbacks() {

               public void onConfigurationChanged(Configuration newConfig) {
                   if (newConfig != null && newConfig.fontScale > 0) {
                       //调节系统字体大小后改变的值
                       sNoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity;
                   }
               }

               public void onLowMemory() {

               }
           });
       }

       //获取以设计图总宽度360dp下的density值
       float targetDensity = appDisplayMetrics.widthPixels / 360;
       //通过计算之前scaledDensity和density的比获得scaledDensity值
       float targetScaleDensity = targetDensity * (sNoncompatScaledDensity / sNoncompatDensity);
       //获取以设计图总宽度360dp下的dpi值
       int targetDensityDpi = (int) (160 * targetDensity);
       //设置系统density值
       appDisplayMetrics.density = targetDensity;
       //设置系统scaledDensity值
       appDisplayMetrics.scaledDensity = targetScaleDensity;
       //设置系统densityDpi值
       appDisplayMetrics.densityDpi = targetDensityDpi;

       //获取当前activity的DisplayMetrics
       final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
       //设置当前activity的density值
       activityDisplayMetrics.density = targetDensity;
       //设置当前activity的scaledDensity值
       activityDisplayMetrics.scaledDensity = targetScaleDensity;
       //设置当前activity的densityDpi值
       activityDisplayMetrics.densityDpi = targetDensityDpi;
   }
}

源码

     /**
    * @param unit 要转换的单位
    * @param value 单位对应的值
    * @param metrics 显示指标
    */
   public static float applyDimension(int unit, float value,DisplayMetrics metrics){
       switch (unit) {
       case COMPLEX_UNIT_PX://单位为px
           return value;
       case COMPLEX_UNIT_DIP://单位为dp
           return value * metrics.density;
       case COMPLEX_UNIT_SP://单位为sp
           return value * metrics.scaledDensity;
       case COMPLEX_UNIT_PT://单位为pt
           return value * metrics.xdpi * (1.0f/72);
       case COMPLEX_UNIT_IN://单位为in
           return value * metrics.xdpi;
       case COMPLEX_UNIT_MM://单位为mm
           return value * metrics.xdpi * (1.0f/25.4f);
       }
       return 0;
   }

7. AndroidAutoSize 框架(原鸿神 AndroidAutoLayout 框架改进版)

简书地址

目录
相关文章
|
算法 Shell 测试技术
Monkey 常用命令详解含高级参数应用
Monkey 常用命令详解含高级参数应用
Monkey 常用命令详解含高级参数应用
|
人工智能 语音技术 Android开发
|
Docker 容器 Ubuntu
docker container 设置编码为utf8
以Ubuntu 14.04 为例创建编码为utf8的container
6045 0
|
12月前
|
消息中间件 测试技术 数据库
吊打面试官!应用间交互如何设计?
【10月更文挑战第18天】设计应用间交互需从明确需求、选择合适方式、设计协议与数据格式、考虑安全性和权限管理、进行性能优化和测试五个方面入手。明确功能和用户需求,选择接口调用、消息队列、数据库共享或文件交换等方式,确保交互高效、安全、可靠。展示这些能力将在面试中脱颖而出。
155 1
|
网络安全
升级openssh版本
有网络情况下 1 下载包,编译 tar zxvf openssh-7.1p1.tar.gz cd openssh-7.1 ./configure --prefix=/usr --sysconfdir=/etc/ssh make make install 2 解决如下环境报错:    configure: error: *** zlib.
1634 0
|
缓存 Android开发 容器
android小技巧之不缓存的ViewPager
前言 在开发中我们会经常用到ViewPager这个类,比如引导页的啦,主页啦,等等之类的。 一般情况下,我在ViewPger中都是放的Framgnt,这样简单有方便,但是ViewPager却会默认的缓存当前页面的最近两个页面,于是问题就产生了,我们的需...
2310 0
CMake中使用vcpkg
vcpkg是一个微软开源的C++包管理器。 在以前的开发中,如果在项目中需要使用某个开源库,例如qt,我们需要取官网下载qt的源码,然后构建得到对应的库,然后在项目中链接这个库。对于自己熟悉的库还好说,若是不熟悉的库,如何拉取源码?如何构建?如何在项目中引用?等等这些问题通常会困扰我们,然而,大多数情况下,我们只是使用这个开源库,并不需要关心这个库的构建和编译等问题。如此,在以前的开发过程中,往往会花费不少的时间在引入开源库上。 vcpkg是在背景下开发出来的,通过vcpkg,我们可以在项目中很方便的引入开源库,不用再关心拉取代码、构建开源库的这些事情。 CMake构建的项目中引入开源库
375 0
|
小程序 API 开发工具
微信开放平台是干什么的?底层原理是什么?
微信开放平台是干什么的?底层原理是什么?
2651 0
|
自然语言处理 Cloud Native Java
SpringNative:把Spring项目编译成原生程序
Spring 发布了 Spring Native 的 beta 版本,该功能已经在 start.spring.io 上可用了。 Spring Native 是什么 Spring Native 可以通过 GraalVM 将 Spring 应用程序编译成原生镜像,提供了一种新的方式来部署 Spring 应用。Spring Native 支持 Java 和 Kotlin。 这个项目的目标是寻找 Spring JVM 的替代方案,提供一个能将应用程序打包,并运行在轻量级容器的方案。期望能够在 Spring Native 中支持所有的 Spring 应用程序(几乎不用修改代码)。