热门搜索 :
考研考公
您的当前位置:首页正文

Kotlin写Android界面适配问题

来源:东饰资讯网

前言


适配一直是手机开发亘古不变的话题,包含版本适配,界面适配等等。。咱们这里说的是关于界面适配的讨论。
写代码的时候咱们都希望一套代码通适配所有的机型,不需要额外的代码,额外的尺寸文件,大量的判断。因为这些都需要手去敲代码,累啊。希望解决问题就是要简单粗暴。

可是我用Anko写布局了,没有xml,那么适配怎么办?

思考


  • 适配是什么?
    就是界面在各种尺寸的手机上面长的都一样。界面是由很多个控件组成的,要求界面长的一样,其实就是要求里面的控件长的都一样。那什么叫控件长的都一样呢?是不是大小位置都写死就叫一样的,肯定不是的。这边我也解释不清,看图说话,控件要随着场景的变化等比变化。
Paste_Image.png
  • 决定控件变化的因素
    尺寸 & 坐标。有人说Material还有高度的概率,那个太细节,咱们不考虑。写好这些值,基本上控件在场景的区域就固定了。
  • 什么叫等比变化
    原来控件高度是屏幕的1/4,1280px高度的手机上,控件高度就是320px,720高度的手机,控件高度就是180px
  • 图片控件怎么处理
    上面说了控件的区域固定了,控件的样子就是内部问题。图的资源文件还是按照规则放相应的文件夹,能做.9处理的就做.9。一些图层效果,圆角图等等尽量别用美工切图,自己勤快点。有人说放到大尺寸手机上图片模糊怎么办? 换张清晰的图片。

代码实现 ( ps:下面是我个人思路 )


首先我抛弃了dip,dp,px,sp的概念,在我认为映射到手机屏幕上都是最终换算成像素px。
所以我所有控件的相关的尺寸都是px。
首先得到场景的宽高度, 这里有需要改动的地方,有的手机下面有屏幕操作的bottombar,要减去那个高度

val Any.kDisplay: DisplayMetrics by lazy {
    KApp.app.provideDisplay
}

/**
 * 相对屏幕的宽度
 */
fun Any.kWidth(rate:Float):Float {
    return kDisplay.widthPixels*rate
}

fun Any.kIntWidth(rate:Float):Int {
    return kWidth(rate).toInt()
}

/**
 * 屏幕的高度
 */
fun Any.kHeight(rate:Float):Float {
    return kDisplay.heightPixels*rate
}

fun Any.kIntHeight(rate:Float):Int {
    return kHeight(rate).toInt()
}

定义控件的时候,例如:下图的TextView,宽度是屏幕的1/5 高度是屏幕的1/2,不管你什么手机,都那么大。

textView( "我是控件" ){    
    textColor = Color.WHITE
    textSize = DimensAdapter.textSpSize(CustomTSDimens.NORMAL)
    backgroundColor = getResColor(R.color.transparent)
    onMyClick { toastLongShow("功能没实现!") }
}.lparams( kIntWidth(0.2f) , kIntHeight(0.5f) ) {
   topMargin = kIntHeight(0.03f) 
}

那控件位置怎么办?这个需要写布局的时候去控制,细微的例如 边距,padding.这些可以通过像素区控制,例如

margin = kIntHeight(0.03f) 

说完控件的外部,在讲讲内部渲染,字体大小呢?也是通过像素,当然不是。我的处理是获取系统默认的字体,然后相对系统的字体,放大缩小。

//获取系统的字体
val defTextSize:Float by lazy {
    val view = TextView(kApplication)
    view.textSize/kDisplay.scaledDensity
}

/**
 * 获得字体的大小
 */
fun textSpSize(tsType : CustomTSDimens = CustomTSDimens.NULL):Float {
    return defTextSize + tsType.offsetSP
}

fun textPxSize(tsType : CustomTSDimens = CustomTSDimens.NULL):Float {
    return (defTextSize + tsType.offsetSP) * kDisplay.scaledDensity
}

/**
 * 自定义字体大小
 */
enum class CustomTSDimens(val offsetSP:Float) {
    NAV_TITLE(5f),NORMAL(0f),SLIGHTLY_BIG(1f),BIG(2f),BIGGER(4f),SMALL(-2f),NULL(0f)
}

外面字体引用,例如下面比默认字体稍微大一号

textSize = DimensAdapter.textSpSize(CustomTSDimens.SLIGHTLY_BIG)

这样基本适配就解决了

Top