Android kotlin+anko自定义view进阶篇(二)

上一篇:kotlin+anko自定义view进阶篇(一)

开篇

  继上篇,本篇教你如何用 Kotlin+Anko 更简洁地自定义控件。假如我们需要定义效果如下的控件:



一个横向的LinearLayout包含三个子控件:ImageView、TextView、ImageView。

  • 1、自定义控件,代码很简单,MyItemLayout.kt
open class MyItemLayout : LinearLayout {
    private lateinit var iconView: ImageView
    private lateinit var labelView: TextView
    private lateinit var arrowView: ImageView

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init()
    }

    private fun init() = apply{
        orientation = LinearLayout.HORIZONTAL
        gravity = Gravity.CENTER_VERTICAL

        //icon
        iconView = imageView(){
            imageResource = R.drawable.kit_ic_assignment_blue_24dp
        }
        iconView.layoutParams = LayoutParams(wrapContent, wrapContent)

        //label
        labelView = textView {
            textSize = 14f
            textColor = 0xFF333333.toInt()
            leftPadding = dip(12)
            rightPadding = dip(12)
        }
        labelView.layoutParams = LayoutParams(0, wrapContent, 1.0f)

        //arrow
        arrowView = imageView(){
            imageResource = R.drawable.kit_ic_chevron_right_gray_24dp
        }
        arrowView.layoutParams = LayoutParams(wrapContent, wrapContent)
    }

    fun getIconView(): ImageView {
        return iconView
    }

    fun getLabelView(): TextView {
        return labelView
    }

    fun getArrowView(): ImageView {
        return arrowView
    }
}

说明:

        private lateinit var iconView: ImageView
        private lateinit var labelView: TextView
        private lateinit var arrowView: ImageView

我们并不希望外部使用者替换我们这三个view,所以都设置成private访问权限。又因为是lateinit属性,所以我们不能在属性下面添加get和set方法。如果要提供外部直接访问这三个view,我们自行添加get方法。

lateinit' modifier is not allowed on properties with a custom getter or setter

  • 2、给MyItemLayout添加扩展内联方法,方便以Anko语法调用。MyItemLayoutExtend.kt
import android.content.Context
import android.view.ViewManager
import android.widget.ImageView
import android.widget.TextView
import jsc.kit.itemlayout.MyItemLayout
import org.jetbrains.anko.custom.ankoView
import org.jetbrains.anko.internals.AnkoInternals

inline fun ViewManager.myItemLayout(
        ctx: Context = AnkoInternals.getContext(this),
        theme: Int = 0,
        init: MyItemLayout.() -> Unit
): MyItemLayout {
    return ankoView({ MyItemLayout(ctx) }, theme, init)
}

//icon
inline fun  T.ilIcon(
        init: ImageView.() -> Unit
): T {
    getIconView().init()
    return this
}

//label
inline fun  T.ilLabel(
        init: TextView.() -> Unit
): T {
    getLabelView().init()
    return this
}

//arrow
inline fun  T.ilArrow(
        init: ImageView.() -> Unit
): T {
    getArrowView().init()
    return this
}

说明:

inline fun ViewManager.myItemLayout(
        ctx: Context = AnkoInternals.getContext(this),
        theme: Int = 0,
        init: MyItemLayout.() -> Unit
): MyItemLayout {
    return ankoView({ MyItemLayout(ctx) }, theme, init)
}

ctx ——Context 。我们初始化为AnkoInternals.getContext(this)返回的值
theme—— Int。我们初始化为0
init—— block块。我们把block的作用域限制在MyItemLayout的对象内
如果非block参数有初始化值,在调用时可以不传

同理我们再来看看上面的ilLabel扩展:

inline fun  T.ilLabel(
        init: TextView.() -> Unit
): T {
    getLabelView().init()
    return this
}

我们只定义了一个参数initblock,其作用域是TextView,我们用来配置MyItemLayout中的labelView
getLabelView().init()大概意思就是:让MyItemLayout中的labelView执行init这块代码。

我们可以这样写,让init没有作用域,仅仅是一个block块:

inline fun  T.ilLabel(
        init: () -> Unit
): T {
    init()
    return this
}
  • 3、在Anko中使用MyItemLayout
                myItemLayout {
                    leftPadding = dip(16)
                    rightPadding = dip(16)
                    topPadding = dip(8)
                    bottomPadding = dip(8)
                    backgroundResource = R.drawable.xxx
                }.ilIcon {
                    imageResource = R.drawable.xxx
                }.ilLabel {
                    text = "I'am JustinEoy"
                    textColor = Color.BLUE
                    textSize = 15f
                }.ilArrow {
                    imageResource= R.drawable.xxx
                    alpha = 0.4f
                }

源码

源码传送门——https://github.com/JustinRoom/MyKotlinAnko/blob/master/library/src/main/java/jsc/kit/itemlayout

篇尾

  如果觉得我写得不错的点个爱心吧,也顺便加个关注啦!我是JustinRoom, QQ:10063682252

你可能感兴趣的:(Android kotlin+anko自定义view进阶篇(二))