是时候放弃shape、selector XML写法,一行代码搞定基本UI需求

5,616
我们在写项目的时候,总是会写很多的shape.xml文件、selector.xml文件,虽然不难,但是有时候还是挺烦的,有很多很多的xml文件,增大apk不说,主要是写起来还是挺烦的(个人觉得)。所以写了个代码方式去实现。


1.shape

先上张图,看一下效果


1.1 矩形

rectFill.rect(getResColor(R.color.fillColor))

1.2 带边框的矩形

rectFillAndStroke.rect(getResColor(R.color.fillColor), dpToPx(3f),getResColor(R.color.strokeColor))

1.3 圆角矩形

roundRectWithStroke.roundRect(getResColor(R.color.fillColor),cornerRadius = dpToPx2(10f),    strokeWidth = dpToPx(3f),strokeColor = getResColor(R.color.strokeColor))

1.4 圆角矩形(四个角不同)

roundRect5.roundRect(getResColor(R.color.fillColor),dpToPx(3f),getResColor(R.color.strokeColor),    
leftTopCornerRadiusX = dpToPx2(10f),leftTopCornerRadiusY = dpToPx2(5f),    
rightTopCornerRadiusX = dpToPx2(5f),rightTopCornerRadiusY = dpToPx2(10f),    
leftBottomCornerRadiusX = dpToPx2(10f),leftBottomCornerRadiusY = dpToPx2(20f),    
rightBottomCornerRadiusX = dpToPx2(8f),rightBottomCornerRadiusY = dpToPx2(14f))

1.5 椭圆

ovelRect1.ovel(getResColor(R.color.fillColor))

1.6 渐变

val gradientColors = intArrayOf(Color.YELLOW,Color.BLUE,Color.GREEN)
gradient.gradient(gradientColors)
gradient1.gradient(gradientColors,GradientDrawable.Orientation.LEFT_RIGHT)
gradient2.gradient(gradientColors,GradientDrawable.Orientation.BL_TR)

2.selector

selector一般都是一些状态类的ui变化,常见的就是点击,选中

先上张图,看一下效果




2.1 点击状态

背景

val pressedDrawable = buildDrawable(Color.parseColor("#8B9EB3"), dpToPx2(5f))
val normalDrawable = buildDrawable(Color.parseColor("#4498F2"), dpToPx2(5f))
btnPressed.pressed(normalDrawable,pressedDrawable)

文字颜色

btnPressed.pressedTextColor(Color.WHITE,Color.GRAY)

2.2 enable状态

背景

val normalDrawable = buildDrawable(Color.parseColor("#4498F2"), dpToPx2(5f))
val unenableDrawable = buildDrawable(Color.parseColor("#A8A9AC"), dpToPx2(10f))
btnUnenable.enable(normalDrawable,unenableDrawable,false)

文字颜色

btnUnenable.enabledTextColor(Color.WHITE,Color.GRAY,false)

2.3 多状态叠加

背景

val pressedDrawable = buildDrawable(Color.parseColor("#8B9EB3"), dpToPx2(5f))
val normalDrawable = buildDrawable(Color.parseColor("#4498F2"), dpToPx2(5f))
val unenableDrawable = buildDrawable(Color.parseColor("#A8A9AC"), dpToPx2(10f))
val sd = buildStateListDrawable()    
          .pressed(pressedDrawable)   
          .enable(unenableDrawable,false)   
          .normal(normalDrawable)
btnMuilti.setStateDrawable(sd)

文字颜色

val colorState = ColorStateBuilder()    
                    .enableTextColor(Color.GRAY,false)    
                    .pressedTextColor(Color.LTGRAY)    
                    .normalTextColor(Color.WHITE)    
                    .build()
btnMuilti.setTextColor(colorState)

2.4 imageview图标状态

点击变换不同图标

iv_back.pressed(R.drawable.back,R.drawable.back_pressed)

enable不同图标


iv_back.enable(R.drawable.back,R.drawable.back_pressed,false)

2.5 radiobutton、checkbox图标状态

radiobutton

radioButton.checkedTextColor(Color.parseColor("#bfbfbf"),Color.parseColor("#1296db"))
radioButton.leftCheckedCompoundDrawable(R.drawable.ic_radio_normal,R.drawable.ic_radiobutton_checked)

checkbox

checkBox2.checkedTextColor(Color.parseColor("#bfbfbf"),Color.parseColor("#1296db"))
checkBox2.leftCheckedCompoundDrawable(R.drawable.checkbox_unchecked,R.drawable.checkbox_checked)

3.水波纹效果

先上张图


3.1  无背景,但限制在控件范围之内

没有背景的情况下,加上一个mask就能限制在控件范围之内了

button1.ripple(rippleColor,maskFillColor = Color.parseColor("#FFE60D3E"))

3.2  无背景,不限制范围

不加contentDrawable,跟maskDrawable就限制不了范围了

button2.ripple(rippleColor)

3.3  常规的带个背景

加上contentDrawable就可以了

button3.ripple(rippleColor,fillColor = Color.parseColor("#1296db"),cornerRadius = dpToPx2(5f))

3.4  点击时候不同背景

contentDrawable弄成StateListDrawable即可

val normalDrawable = buildDrawable(fillColor = Color.parseColor("#1296db"),cornerRadius = dpToPx2(5f))
val pressedDrawable = buildDrawable(fillColor = Color.parseColor("#FFE60D3E"),cornerRadius = dpToPx2(5f))
val sd = buildStateListDrawable()    
.pressed(pressedDrawable)    
.normal(normalDrawable)
button6.ripple(rippleColor,sd)

3.5  边框背景

边框背景的时候常规contentDrawable是个边框shape,需要加个maskDrawable,这样点击效果才会在整个控件上,不然就只有边框有效果

button4.ripple(rippleColor,fillColor = Color.TRANSPARENT,cornerRadius = dpToPx2(5f),    strokeWidth = dpToPx(2f),strokeColor = Color.parseColor("#1296db"),    maskFillColor = Color.parseColor("#FFE60D3E"),maskCornerRadius = dpToPx2(5f))

3.6  水波纹限制在圆形范围内

弄一个圆形背景,设置成contentDrawable,

val circleDrawable = buildDrawable(Color.parseColor("#1296db"), dpToPx2(100f),gradientType = GradientDrawable.OVAL)

circle_ripple.ripple(rippleColor,circleDrawable )

3.7  图标的波形背景

这里其实就是上面的不限制范围

circle_ripple3.ripple(rippleColor)

3.8  限制在图标之内

circle_ripple4.rippleSrc(rippleColor,R.drawable.ic_back_blue)

3.9  兼容5.0以下

fun View?.ripple(rippleColor:Int,contentDrawable:Drawable? = null,maskDrawable:Drawable? = null){    
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ){        
       val colorStateList = ColorStateList(arrayOf(intArrayOf()), intArrayOf(rippleColor)) 
       val rippleDrawable = RippleDrawable(colorStateList,contentDrawable,maskDrawable)        
       this?.let {            
            it.background = rippleDrawable        
       }    
}else{        
    this?.let { view->            
       contentDrawable?.let {                
          view.background = it            
          }       
 }    }}


4.总结

       代码本身没什么技术难度,我也就不瞎逼逼什么原理了,主要就是封装一下使用而已,简化工作流程。唯一要注意的是使用前要先注入application,ApplactionInject.inject(this)  其实也就是获得一个全局的Context,大家都懂,省得很多方法都要加Context参数 。
       总体使用还是很方便的,基本上一行代码就能搞定基本的UI需求,在也不需要像以前一样需要写烦人的xml了,大大减少xml的文件数量

5.源码

github地址:github.com/JiangW01/Sa…