Android智能平板应用,界面适配的另一种轻量级方法

简介: Android智能平板应用,界面适配的另一种轻量级方法

Android的界面适配,很常见的需求。


各种设备种类和尺寸那么多,基于一种原型设计好的界面,换到另一种设备上去若不适配全乱套了。好在还是有很多方案的,这减少了不少的开发工作量。最流行的就是头条的方案了,使用也超级简单。然而,如果不想引入,还可以简单的一个工具类实现,原理类似于头条的方案。


这里简单介绍下,使用起来也很简单。


原理就是转换设备的显示像素密度Density。


头条的UI适配的低成本方案AndroidAutoSize也是基于这个原理,只是它封装的更好,稳定性也更好。



就是智能平板UI尺寸虽然不一样,但是长宽比例差不多。比如基于1920*1080的界面尺寸设计的应用,现在新的设备屏幕是1366x768。若不加适配肯定显示不全,若能等比例缩小0.71倍就好了,那么方法是有的。就一个类文件Density.java


package com.newcapec.visitorsystem.utils;
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
public class Density {
    /**
     * 设置屏幕像素密度
     * 思路讲解,计算 B601的老固件像素密度1.5 ,新固件像素密度1 600*32/48 = 400
     * 首先我们需要获取当前机型的屏幕密度信息:appDensity,appScaleDensity
     *
     * 我们的设计尺寸会根据默认机型计算出一个固定的以dp为单位的宽度:WIDTH
     *
     * 比如:默认机型的宽高为1080*1920,该设备的屏幕密度为3
     * 那么WIDTH = 1080/3 = 360dp;因此所有适配机型的宽也就等于360dp。
     * 根据 屏幕宽度 / 屏幕密度=WIDTH公式,现在知道屏幕宽度和WIDTH,也就能求出:屏幕密度=屏幕宽度 / WIDHT;
     *
     * 现在屏幕宽度(dp):targetDensity = displayMetrics.widthPixels / WIDTH 求出。
     *
     * 接下来,就需要求出适配机型的scaleDensity
     *
     * appScaleDensity / appDensity = targetScaleDensity / targetDensity ;
     *
     * targetScaleDensity = targetDensity * (appScaleDensity / appDensity) ;
     *
     * densityDpi = density * 160 ;
     *
     * 最后,把获取到的数据,设置到activity的displayMetrics中。
     *
     * 计算出来后,我们需要在绘制view之前先设置好
     *
     * 在onCreate中的setContentView之前添加
     * ———————————————
     * 原文链接:https://blog.csdn.net/weixin_45365889/article/details/102660467
     */
    private final static float WIDTH = 1920;//适配机型的宽为1920dp,屏幕宽/屏幕密度=1920/1=1920
    private static float appDensity;
    private static float appScaleDensity;
    public static void setDensity(Context appcontx, Context contx) {
        //获取当前app的屏幕显示信息
        WindowManager wm = (WindowManager)appcontx.getSystemService(Context.WINDOW_SERVICE);
        int width = wm.getDefaultDisplay().getWidth();
        Log.d("Utils","app width:"+width);
        DisplayMetrics displayMetrics = appcontx.getResources().getDisplayMetrics();
        appDensity = displayMetrics.density;
        appScaleDensity = displayMetrics.scaledDensity;
        Log.d("Utils","appDensity:"+appDensity+",appScaleDensity:"+appScaleDensity);
        //计算等比缩放后的density和scaleDensity
        //WIDTH相对于所有屏幕宽度都是相等的,它是用dp作为单位,所以 屏幕宽度/屏幕密度=WIDTH
        //targetDensity = targetWidht/WIDTH
        float targetDensity = displayMetrics.widthPixels / WIDTH;
        //appScaleDensity/appDensity=targetScaleDensity/targetDensity;
        float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);
        int targetDensityDpi = (int) (targetDensity * 160);
        //替换activity的density,appdensity,densityDpi
        DisplayMetrics aDisplayMertics = contx.getResources().getDisplayMetrics();
        Log.d("Utils","presentDensity:"+aDisplayMertics.density+",presentScaleDensity:"+aDisplayMertics.scaledDensity);
        aDisplayMertics.density = targetDensity;
        aDisplayMertics.scaledDensity = targetScaleDensity;
        aDisplayMertics.densityDpi = targetDensityDpi;
        Log.d("Utils","targetDensity:"+targetDensity+",targetScaleDensity:"+targetScaleDensity);
    }
}


注意把里面的WIDTH配置为原设计模型的宽度。


原理介绍



首先我们需要获取当前机型的屏幕密度信息:appDensity,appScaleDensity


我们的设计尺寸会根据默认机型计算出一个固定的以dp为单位的宽度:WIDTH


比如:默认机型的宽高为1080*1920,该设备的屏幕密度为3


那么WIDTH = 1080/3 = 360dp;因此所有适配机型的宽也就等于360dp。


根据 屏幕宽度 / 屏幕密度=WIDTH公式,现在知道屏幕宽度和WIDTH,也就能求出:屏幕密度=屏幕宽度 / WIDHT;


现在屏幕宽度(dp):targetDensity = displayMetrics.widthPixels / WIDTH 求出。


接下来,就需要求出适配机型的scaleDensity


appScaleDensity / appDensity = targetScaleDensity / targetDensity ;


targetScaleDensity = targetDensity * (appScaleDensity / appDensity) ;


densityDpi = density * 160 ;


最后,把获取到的数据,设置到activity的displayMetrics中。


计算出来后,我们需要在绘制view之前先设置好。


使用方法


在BaseActivity的onCreate中调用一下就可以了。


Utils.setDensity(App.getContext(),this);


package com.newcapec.visitorsystem.activity.frontscreen;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.Nullable;
import com.newcapec.visitorsystem.app.App;
import com.newcapec.visitorsystem.threads.ReadCardThread;
import com.newcapec.visitorsystem.utils.Utils;
public class BaseActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Utils.setDensity(App.getContext(),this);
    }
    /*
     * 隐藏系统键盘
     */
    public void hideXtView(){
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        View view = this.getCurrentFocus();
        if (view != null) {
            InputMethodManager inputMethodManager = (InputMethodManager) this.getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }
}


以上只是一个简单的方法,可作为一个学习界面适配原理的例子。但是对于自定义view和listview,RecyclerView是失效的。


这里再介绍下基于头条的UI适配的低成本方案AndroidAutoSize:


AndroidAutoSize对于自定义view,listview,和RecyclerView适配也完全没问题,原理类似。


对于RecyclerView只需在Adapter 的onCreateViewHolder里,调用一下:


AutoSizeCompat.autoConvertDensityOfGlobal(context.getResources());


即可完美适配RecyclerView的UI显示。


AndroidAutoSize:


github地址


https://github.com/JessYanCoding/AndroidAutoSize


gradle引入


implementation 'me.jessyan:autosize:1.1.2'


manifase配置


如果只使用副单位 (pt、in、mm) 就可以直接以像素作为单位填写设计图的尺寸, 不需再把像素转化为 dp


<!-- 如果只使用副单位 (pt、in、mm) 就可以直接以像素作为单位填写设计图的尺寸, 不需再把像素转化为 dp-->
<!-- 用mm副单位开发,这里配置和设计稿一样的尺寸px , 1920 x 1080px -->
<manifest>
    <application>            
        <meta-data
            android:name="design_width_in_dp"
            android:value="1080"/>
        <meta-data
            android:name="design_height_in_dp"
            android:value="1920"/>           
     </application>           
</manifest>


注意上面的meta-data是原始设计尺寸的宽,高。可不用设置成新设备的屏幕尺寸了。


以上基本满足你的基本需求了,若还有问题,可以参见这个贴,汇总了常见问题的解决办法:


https://github.com/JessYanCoding/AndroidAutoSize/issues/13


还有一种屏幕适配方案,原理跟上述的差不多,是AndroidScreenAdaptation。


AndroidScreenAdaptation:


地址:https://github.com/yatoooon/AndroidScreenAdaptation


AndroidScreenAdaptation库特点:


完全不用改变自己的布局编写习惯,你原先是怎么写布局,就怎么写布局.不用去继承适配类,不用在最外层包裹适配布局,不用新建茫茫多的分辨率适配文件夹,不要求强制使用px为单位,可以实时预览布局,全面屏或带虚拟按键手机适配也没问题。


使用:


1.添加依赖


implementation 'me.yatoooon:screenadaptation:1.1.1'


2.初始化工具类


(1)创建自己的application继承Application


public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        ScreenAdapterTools.init(this);
    }
//如果应用屏幕固定了某个方向不旋转的话(比如qq和微信),下面可不写.
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        ScreenAdapterTools.getInstance().reset(this);
    }
}


(2)在AndroidManifest.xml文件中声明使用你自己创建的application并且添加meta-data数据,例子上标明了这些数据的代表的意义


<application
        android:name=".App"
        .....
        <meta-data
            android:name="designwidth"
            android:value="1080" />  //设计图的宽,单位是像素,推荐用markman测量,量出来如果是750px那么请尽量去找ui设计师要一份android的设计图.
        <meta-data
            android:name="designdpi"
            android:value="480" />   //设计图对应的标准dpi,根据下面的那张图找到对应的dpi,比如1080就对应480dpi,如果拿到的是其他宽度的设计图,那么选择一个相近的dpi就好了
        <meta-data
            android:name="fontsize"
            android:value="1.0" />   //全局字体的大小倍数,有时候老板会觉得你的所有的字小了或者大了,你总不能一个一个去改吧
        <meta-data
            android:name="unit"
            android:value="px" />   //你的布局里面用的是px这就写px,你的布局里面用的是dp这就写dp,要统一,不要一会儿px一会儿dp,字体也用px或者dp,不要用sp,微信qq用的肯定不是sp.
</application>    



3. 开始使用


(1)在Activity中,找到setcontentview(R.layout.xxxxxx)


public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_dp);
        //在setContentView();后面加上下面这句话
        ScreenAdapterTools.getInstance().loadView((ViewGroup) getWindow().getDecorView());
    }
}


注: 自定义view的话,在 ScreenAdapterTools.getInstance().loadView((ViewGroup) view); 外面包裹一层判断如下,不然在使用自定义view编写布局文件时预览xml会有问题!但不影响真机运行效果.


       if (!isInEditMode()) {
            ScreenAdapterTools.getInstance().loadView((ViewGroup) view);
        }    


原理


1. px是分辨率的单位 比如现在主流手机分辨率1080*1920.


2. dp是安卓开发专有的单位 在 不同的手机下 1dp = 不同的 px.


3. sp是字体大小(前面清单文件中要求字体也用dp或者px),sp随系统字体大小变化而变化,但据我观察,像微信qq这些app的字体是不随系统显示字体大小变化的.


### 本库是按照设计图的宽度和对应标准dpi来适配的(宽度增加或减少,高度同比例增加或减少),在不同的分辨率,不同ppi(手机屏幕密度,又称为dpi),不同最小宽度(有的人喜欢去调开发者选项下面的最小宽度,主流手机默认为360dp)的手机下都做到了适配。


引用:


今日头条屏幕适配方案终极版 AndroidAutoSize-玩Android - wanandroid.com


安卓适配AutoSize详解_xxdw1992的博客-CSDN博客_me.jessyan:autosize


Android安卓中最棒的屏幕适配AndroidScreenAdaptation_快乐李同学的博客-CSDN博客_android screen


屏幕适配:修改屏幕像素密度,随便设dp_Android架构师丨小熊的博客-CSDN博客


Andoid屏幕适配终极手段(小编用过最得劲的dp适配)_奋斗的IT青年-CSDN博客_最小宽度多少dp让手机流畅


Android AutoLayout全新的适配方式 堪称适配终结者_Hongyang-CSDN博客_autolayout

相关文章
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
691 64
|
12月前
|
Android开发 开发者
Android自定义view之利用drawArc方法实现动态效果
本文介绍了如何通过Android自定义View实现动态效果,重点使用`drawArc`方法完成圆弧动画。首先通过`onSizeChanged`进行测量,初始化画笔属性,设置圆弧相关参数。核心思路是不断改变圆弧扫过角度`sweepAngle`,并调用`invalidate()`刷新View以实现动态旋转效果。最后附上完整代码与效果图,帮助开发者快速理解并实践这一动画实现方式。
269 0
|
12月前
|
Android开发 数据安全/隐私保护 开发者
Android自定义view之模仿登录界面文本输入框(华为云APP)
本文介绍了一款自定义输入框的实现,包含静态效果、hint值浮动动画及功能扩展。通过组合多个控件完成界面布局,使用TranslateAnimation与AlphaAnimation实现hint文字上下浮动效果,支持密码加密解密显示、去除键盘回车空格输入、光标定位等功能。代码基于Android平台,提供完整源码与attrs配置,方便复用与定制。希望对开发者有所帮助。
242 0
|
12月前
|
XML Java Android开发
Android自定义view之网易云推荐歌单界面
本文详细介绍了如何通过自定义View实现网易云音乐推荐歌单界面的效果。首先,作者自定义了一个圆角图片控件`MellowImageView`,用于绘制圆角矩形图片。接着,通过将布局放入`HorizontalScrollView`中,实现了左右滑动功能,并使用`ViewFlipper`添加图片切换动画效果。文章提供了完整的代码示例,包括XML布局、动画文件和Java代码,最终展示了实现效果。此教程适合想了解自定义View和动画效果的开发者。
489 65
Android自定义view之网易云推荐歌单界面
|
10月前
|
安全 数据库 Android开发
在Android开发中实现两个Intent跳转及数据交换的方法
总结上述内容,在Android开发中,Intent不仅是活动跳转的桥梁,也是两个活动之间进行数据交换的媒介。运用Intent传递数据时需注意数据类型、传输大小限制以及安全性问题的处理,以确保应用的健壯性和安全性。
631 11
|
12月前
|
Android开发 开发者
Android企业级实战-界面篇-3
本文是《Android企业级实战-界面篇》系列的第三篇,主要介绍分割线和条形跳转框的实现方法,二者常用于设置和个人中心界面。文章通过具体代码示例展示了如何实现这两种UI组件,并提供了效果图。实现前需准备`dimens.xml`、`ids.xml`、`colors.xml`等文件,部分资源可参考系列第一、二篇文章。代码中详细说明了布局文件的配置,如分割线的样式定义和条形跳转框的组件组合,帮助开发者快速上手并应用于实际项目中。
145 1
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
950 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
12月前
|
XML Android开发 数据格式
Android企业级实战-界面篇-2
本文为《Android企业级实战-界面篇》系列第二篇,主要介绍三个UI模块的实现:用户资料模块、关注与粉丝统计模块以及喜欢和收藏功能模块。通过详细的XML代码展示布局设计,包括dimens、ids、colors配置文件的使用,帮助开发者快速构建美观且功能齐全的界面。文章结合实际效果图,便于理解和应用。建议配合第一篇文章内容学习,以获取完整工具类支持。
180 0
|
12月前
|
算法 Java Android开发
Android企业级实战-界面篇-1
本文详细介绍了Android企业级开发中界面实现的过程,涵盖效果展示、实现前准备及代码实现。作者通过自身经历分享了Android开发经验,并提供了`dimens.xml`、`ids.xml`、`colors.xml`和`strings.xml`等配置文件内容,帮助开发者快速构建规范化的UI布局。文章以一个具体的用户消息界面为例,展示了如何使用线性布局(LinearLayout)和相对布局(RelativeLayout)实现功能模块排列,并附带注意事项及使用方法,适合初学者和进阶开发者参考学习。
256 0
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
479 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex

热门文章

最新文章