Android屏幕适配实例教程「今日头条,AutoSize」

Android屏幕适配实例教程

即使只是练习项目,仍然要使用屏幕适配,这样我们就可以跟着设计图上的单位参数敲,效率会快很多

项目的示范代码使用kt语言,但没有用到什么高级特性,完全不懂的参考这个链接,文章参考代码已经上传到Github,本篇相关的设计图链接戳这里

这里提供一个App的UI设计图小白日记,仅供参考

前期与UI之间的沟通

1)确定设计图基准

=可以简单理解为以某个尺寸为基准,然后通过改变对应的比例的方式去设置真实的单位数值,这就意味了我们在开发之前要和UI设计师沟通好基准设计图的宽高尺寸,单位是px或dp有,通常Android是以360*640dp为基准

2)标注方式

推荐使用蓝湖(https://lanhuapp.com/?home),切图统一使用上传蓝湖的形式,避免微信,U盘传输带来的版本混乱问题,拿到UI给的分享链接后,就可以查看需要的数据了

而且它自带转换功能,所以如果UI设计是以某一px尺寸为单位设计,它也可以帮你转换成相应的dp数值

今日头条屏幕适配方案

1)配置

基于头条屏幕方案的AndroidAutoSize,使用方式,先在module下的build.gradle下添加依赖

 implementation 'me.jessyan:autosize:1.1.2'

然后在module的AndroidManifest权限菜单下添加基本设计图的尺寸,这里我们是使用360*630dp作为基本尺寸单位,这样配置工作就完成了

<manifest>
    <application>            
        <meta-data
            android:name="design_width_in_dp"
            android:value="360"/>
        <meta-data
            android:name="design_height_in_dp"
            android:value="640"/>           
     </application>           
</manifest>

一般来说,只要我们按照基准设计图的尺寸写AutoSize就可以为我们进行适配了,当在一些特殊情况下我们还要进行一些配置。

头条的适配方案是选择高度或宽度两者之一为基准进行适配(姑且不管原理),在该库的AutoSizeConfig类的源码中我们可以看到isBaseOnWidth默认就是true,也就是说改库默认就是以宽度进行适配的

《Android屏幕适配实例教程「今日头条,AutoSize」》 isBaseOnWidth.png

2)宽度适配,高度适配,取消适配

那什么样的页面是用高度适配比较合适,什么样的页面是用宽度适配比较合适呢

比如我们使用ScrollView包裹着线性布局,这种页面就使用宽度适配比较合适,因为它宽度是确定的了,高度是不确定的,所以就使用宽度适配


    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <!-- 省略代码-->
        </LinearLayout>
    </ScrollView>

框架默认是使用宽度适配的,因此我们不需要对Activity进行操作,而如果是HorizontalScrollView,宽度是不确定的,高度是确定的,就适合以高度为基准进行适配

在HeightActivity中实现CustomAdapt接口,实现isBaseOnWidth方法,返回false表示不要以宽度为基本适配,然后在getSizeInDp方法中填写基准设计图高度的尺寸

/**
 * Created by 舍长
 * describe:
 */
class HeightActivity : AppCompatActivity() , CustomAdapt {

    //取消以宽度为基准进行适配
    override fun isBaseOnWidth(): Boolean {
        return false
    }

    //返回高度的单位尺寸
    override fun getSizeInDp(): Float {
        return 640f
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_height)
    }
}

如果我们应用绝大多页面都是适合用高度来进行适配的,我们不希望创建的Activty默认使用宽度进行适配,那么我们就可以在Application的onCreate方法中进行全局的适配

/**
 * Created by 舍长 on 2019/5/9
 * describe:
 */
class App: Application() {
    override fun onCreate() {
        super.onCreate()
        //默认使用宽度适配
        AutoSizeConfig.getInstance().isBaseOnWidth = false
    }
}

最后在权限菜单中引用这个Application就可以了,这个时候创建出来的Activity就默认是使用高度适配了,如果我们想在某个类中再次使用宽度适配,就再次继承CustomAdapt接口实现上面的两个方法就可以了

    override fun isBaseOnWidth() = true
    override fun getSizeInDp() = 360F//基本宽度的尺寸

我们如果想取消屏幕适配,就让Activity实现CancelAdapt接口。

3)沉浸式页面的配置

我们经常会有需要使用沉浸式页面的需求,这里的沉浸式不是指状态栏换一个颜色,而是页面没有状态栏,也就是全屏页面,如闪屏页,视频播放,游戏等等

《Android屏幕适配实例教程「今日头条,AutoSize」》 闪屏页面.png

我们可以通过设置主题来让Activity全屏化

<!-- 无标题栏 -->
<style name="NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

<!--无标题,全屏-->
<style name="AppFullTheme" parent="NoActionBar">
    <!-- 设置全屏 -->
    <item name="android:windowFullscreen">true</item>
</style>

然后让Activity继承于该主题就可以了,但是当我们把页面写好后,却发现页面的内容好像比实际的距离总要往上那么一点?这是怎么回事?

我们看看设计图,并仔细观察紫色圆点的位置

《Android屏幕适配实例教程「今日头条,AutoSize」》 ui.png

然而我们按照UI设计图的尺寸在dpi为440的机器上添加出来的圆点效果却是这样的,明显比我们预期的往左和往上了一些(如果你运行出来觉得效果没错,其实是碰巧,换多几个dpi的机型就不行了)

《Android屏幕适配实例教程「今日头条,AutoSize」》 mobile.png

这是因为AutoSize默认的适配范围是不包括状态栏那块位置,当你使用全屏后他不知道,所以我们可以在Activity中这样配置一下,让他将状态栏的位置也算上去

/**
 * Created by 舍长 
 * describe:当使用全屏主题时,我们要使用设备的真实尺寸
 */
class Full2Activity : AppCompatActivity(), CustomAdapt {
    override fun isBaseOnWidth(): Boolean {
        return false
    }

    override fun getSizeInDp(): Float {
        return 640f
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        AutoSizeConfig.getInstance().isUseDeviceSize = true//使用设备的完整尺寸
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_full2)
    }
}

但是如果我们进入源码中看会发现他默认好像是就是true啊!其实是他在InitProvider类中有重新赋值为false了

    @Override
    public boolean onCreate() {
        AutoSizeConfig.getInstance()
                .setLog(true)
                .init((Application) getContext().getApplicationContext())
                .setUseDeviceSize(false);
        return true;
    }

这里使用竖屏适配的页面是为了方便测试,因为如果是普通的页面会出现图片宽高比不同,图片要经过裁剪才能全屏显示,这就无法直观的看到效果

AutoSize开源库的单位数值转换

在自定义控件总,因为绘图类的单位总是px,所以我们经常使用到单位数值转换,也就是dp,px,sp之间的转换,

我们使用该开源库后,它里面就有很多单位转换工具类了,我们可以进行充分的利用

我们先来看看用法吧


    /**
     * sp转px
     */
    fun sp2px(context:Context,value:Float){
        AutoSizeUtils.sp2px(context, value)
    }

但是这样用好像挺麻烦的,在kotlin中,一个方法在整个模块都是可以用到的,所以我们在Application中封装个全局的context

/**
 * Created by 舍长 on 2019/4/9
 * describe:
 */
class App : BaseApplication() {
    companion object {
        var _context: Application? = null
        fun getContext(): Context {
            return _context!!
        }

    }

    override fun onCreate() {
        super.onCreate()
        _context = this
    }
}

然后新建一个Screen的kt文件来封装方法,具体实现后就是这样的

/**
 * Created by 舍长 on 2019/4/25
 * describe:屏幕单位获取,转换扩展扩展kt文件
 */
//dp转px
fun dp2px(value: Float) {
    AutoSizeUtils.dp2px(App.getContext(), value)
}

//sp转px
fun sp2px(value: Float) {
    AutoSizeUtils.sp2px(App.getContext(), value)
}

//获取屏幕宽度
fun screenWidth(): Int {
    val screenSize = ScreenUtils.getScreenSize(App.getContext())
    return screenSize[0]//宽度
}

//获取屏幕高度
fun screenHeight(): Int {
    val screenSize = ScreenUtils.getScreenSize(App.getContext())
    return screenSize[1]//高度
}

后面我们需要用到时就直接在类里调相应的方法名字就可以了

dp2px(20f) //dp转px
sp2px(20f) //sp转px

图片的适配

如果UI已经将图切好并上传到蓝湖,我们只需要拿到xxhdpi文件夹下的图片,并放置到自己的xxhdpi文件夹就可以了,mipmap-xxhdpi是默认就有的,我们也可以自己创建一个drawable-xxhdpi

《Android屏幕适配实例教程「今日头条,AutoSize」》 xxhdpi库.png
《Android屏幕适配实例教程「今日头条,AutoSize」》 微信截图_20190515133328.png

就可以适配所有手机App了,这样我们就不需要再将每个图片都写大小,只要wrap_content就可以了,Android小太高了会自动帮我们完成适配的过程

      <ImageView
                    android:layout_marginTop="313dp"
                    android:layout_marginLeft="470dp"
                    android:src="@drawable/circle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>

到这里,我们基本上就可以完成适配的工作了,本篇文章只是为了后面的实战文章做铺垫,虽然没有涉及原理,但是在实现上还是没有任何问题的

当然除了今日头条这种适配方案外,也有使用多套px文件来进行适配的项目,可以去鸿洋大佬的博客看看

    原文作者:舍长III
    原文地址: https://www.jianshu.com/p/e874d3dece5d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞