Android kotlin自定义圆角RelativeLayout、Imageview
在界面布局时想要界面更加美观,希望将控件变为圆角,如果只是单纯写一个圆角背景,然后在布局中通过backgroud引入,控件实际上还是方形的,这一点在想实现点击控件出现水波纹效果时,波纹动画结束时最终还不是呈现圆角(相当于没有圆角),要想真正实现控件变为圆角还是需要重写控件的onDraw()方法,使用canvas进行裁剪形成圆角
效果图如下:
点击水波纹动画结束圆角效果:
这里如果想实现这个点击波纹效果只需要在布局文件控件属性中加入以下属性,且需要为该控件设置点击监听
android:foreground="?android:attr/selectableItemBackground"
先准备一个创建attrs.xml写入样式
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RoundView">
<attr name="radius" format="dimension"/>
<attr name="leftTopRadius" format="dimension"/>
<attr name="rightTopRadius" format="dimension"/>
<attr name="leftBottomRadius" format="dimension"/>
<attr name="rightBottomRadius" format="dimension"/>
</declare-styleable>
</resources>
重写
这里其实对于不同的控件重写的内容是一样的,继承的对象换为不同的即可
如想重写ImageView就写继承
class RoundImageView: AppCompatImageView{
...
}
这里由于我的布局是用RelativeLayout里面有一个imageView和一个TextView,要想实现效果需要重写外部的RelativeLayout作为边框
class RoundRectLayout: RelativeLayout {
var rightBottomRadius: Int
var leftBottomRadius: Int
var rightTopRadius: Int
var leftTopRadius: Int
var radius = 0
constructor(context: Context): this(context, null)
constructor(context: Context, attributeSet: AttributeSet?): this(context, attributeSet, 0)
constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int)
:super(context, attributeSet, defStyleAttr) {
val typeArray = context.obtainStyledAttributes(attributeSet, R.styleable.RoundView)
val defaultRadius = 0
radius = typeArray.getDimensionPixelOffset(R.styleable.RoundView_radius, defaultRadius)
leftTopRadius = typeArray.getDimensionPixelOffset(
R.styleable.RoundView_leftTopRadius,
defaultRadius
)
rightTopRadius = typeArray.getDimensionPixelOffset(
R.styleable.RoundView_rightTopRadius,
defaultRadius
)
leftBottomRadius = typeArray.getDimensionPixelOffset(
R.styleable.RoundImageView_leftBottomRadius,
defaultRadius
)
rightBottomRadius = typeArray.getDimensionPixelOffset(
R.styleable.RoundView_rightBottomRadius,
defaultRadius
)
if (radius != 0) {
if (leftTopRadius == 0) {
leftTopRadius = radius
}
if (rightTopRadius == 0) {
rightTopRadius = radius
}
if (leftBottomRadius == 0) {
leftBottomRadius = radius
}
if (rightBottomRadius == 0) {
rightBottomRadius = radius
}
}
typeArray.recycle()
}
override fun onDraw(canvas: Canvas?) {
// 图片宽高大于圆角宽高, 获取圆角的宽高
// 横向长度
val maxLeft = Math.max(leftTopRadius, leftBottomRadius)
val maxRight = Math.max(rightTopRadius, rightBottomRadius)
val minWidth = maxLeft + maxRight
// 竖纵向长度
val maxTop = Math.max(leftTopRadius, rightTopRadius)
val maxBottom = Math.max(leftBottomRadius, rightBottomRadius)
val minHeight = maxTop + maxBottom
if (width > minWidth && height > minHeight) {
val path = Path()
path.moveTo(leftTopRadius.toFloat(), 0F)
path.lineTo((width - rightTopRadius).toFloat(), 0F)
path.quadTo(width.toFloat(), 0F, width.toFloat(), rightTopRadius.toFloat())
path.lineTo(width.toFloat(), (height - rightBottomRadius).toFloat())
path.quadTo(
width.toFloat(),
height.toFloat(),
(width - rightBottomRadius).toFloat(),
height.toFloat()
)
path.lineTo(leftBottomRadius.toFloat(), height.toFloat())
path.quadTo(0F, height.toFloat(), 0F, (height - leftBottomRadius).toFloat())
path.lineTo(0F, leftTopRadius.toFloat())
path.quadTo(0F, 0F, leftTopRadius.toFloat(), 0F)
canvas!!.clipPath(path)
}
super.onDraw(canvas)
}
}
在布局文件中使用:
这里控件用完整的包名
<com.android.view.RoundRectLayout
android:id="@+id/xxx"
android:layout_width="70dp"
android:layout_height="70dp"
//设置圆角弧度
app:radius="20dp"
//设置点击波纹效果
android:foreground="?android:attr/selectableItemBackground">
...