前言
适配一直是手机开发亘古不变的话题,包含版本适配,界面适配等等。。咱们这里说的是关于界面适配的讨论。
写代码的时候咱们都希望一套代码通适配所有的机型,不需要额外的代码,额外的尺寸文件,大量的判断。因为这些都需要手去敲代码,累啊。希望解决问题就是要简单粗暴。
说说关于Android的适配,无论是官网还是外面的技术帖子都有相应的介绍。写布局文件该注意什么,图片放不同的文件夹,dip,sp,px这些尺寸单位使用等等。这让我想到寒战里面李文彬说过的一句话:" 每一个机构,每一个部门,每一个岗位,都有自己的游戏规则,不管暗也好,明也好,第一步,学会它。" ,很有道理,咱们用android SDK开发,要做好适配工作,按照它的规则做就好了。官网传送门
可是我用Anko写布局了,没有xml,那么适配怎么办?
思考
- 适配是什么?
就是界面在各种尺寸的手机上面长的都一样。界面是由很多个控件组成的,要求界面长的一样,其实就是要求里面的控件长的都一样。那什么叫控件长的都一样呢?是不是大小位置都写死就叫一样的,肯定不是的。这边我也解释不清,看图说话,控件要随着场景的变化等比变化。
- 决定控件变化的因素
尺寸 & 坐标。有人说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)
这样基本适配就解决了
网友评论