<com.koolearn.android.view.RedDotView
android:id="@+id/unread_cover"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:dotColor="@color/c_fa5740"
app:dotHeight="@dimen/x14"
app:dotTextColor="@color/white"
app:dotTextSize="8sp"
app:dotDiameter="@dimen/x10"
app:dotShowRing="true"
app:dotRingColor="@color/white"
app:dotRingWidth="@dimen/x5"
/>
复制代码
xml中配置介绍java
1.dotColor 显示圆点时是圆点的颜色,显示数字气泡时是数字气泡的颜色
2.dotHeight 显示数字气泡的的高度
3.dotTextColor 数字气泡中数字的颜色
4.dotTextSize 数字气泡中文字的size
5.dotDiameter 圆点的直径
6.dotShowRing 布尔类型 是否显示外圈圆环
7.dotRingColor 外圈圆环的颜色
8.dotRingWidth 外圈圆环的粗细、
复制代码
1) fun setText(text:Int)
2) fun setOnlyDotMode(onlyDot:Boolean)
3) fun setOffset(view:View)
4) fun setOffset(view:View,x:Int,y:Int,x1:Int,y1:Int)
复制代码
2.使用说明android
因为此view在定位到指定view的右上角时有特殊要求,因此此view和指定view须要在同一个parent布局中。
复制代码
package com.koolearn.android.view
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import com.koolearn.android.R
import com.koolearn.android.utils.Utils
class RedDotView(context: Context, attr: AttributeSet) : View(context,attr),IRedDotView {
private val threeDot:String="···"
private var attrBean = DotViewAttr(context,attr)
private var mOnlyDot:Boolean=false
private var mText:Int=0
private var paint = Paint()//画笔
private val rect= Rect()//计算文字宽高的矩形
private var textWidth = 0
private var textHeight = 0
private var viewWidth = 0
private var viewHeight = 0
private var widthOffSet = 0 //文字在x轴上的偏移量,为负表示向左移动。由于数字1在圆点放在中心时显示过于靠右,因此设置此字段。让数字1时能在中心
override fun draw(canvas: Canvas?) {
super.draw(canvas)
if (visibility==GONE){
return
}
paint.isAntiAlias=true//设置抗锯齿
if(mOnlyDot){//只画一个圆点 半径的一半为中心点
paint.color = attrBean.dotColor
if(attrBean.dotShowRing){
paint.color=attrBean.dotRingColor
canvas?.drawCircle(viewWidth.toFloat()/2,viewHeight.toFloat()/2,attrBean.dotDiameter.toFloat()/2,paint)
paint.color=attrBean.dotColor
canvas?.drawCircle(viewWidth.toFloat()/2,viewHeight.toFloat()/2,attrBean.dotDiameter.toFloat()/2-attrBean.dotRingWidth,paint)
}else{
paint.color=attrBean.dotColor
canvas?.drawCircle(viewWidth.toFloat()/2,viewHeight.toFloat()/2,attrBean.dotDiameter.toFloat()/2,paint)
}
}else{
if(mText==0){//等于0不显示此view因此不执行任何代码
visibility = GONE
return
}
if(mText in 1..9){//画圆
//画圆
if(attrBean.dotShowRing){
paint.color=attrBean.dotRingColor
canvas?.drawCircle(viewWidth.toFloat()/2,viewHeight.toFloat()/2,viewHeight.toFloat()/2,paint)
paint.color=attrBean.dotColor
canvas?.drawCircle(viewWidth.toFloat()/2,viewHeight.toFloat()/2,viewHeight.toFloat()/2-attrBean.dotRingWidth,paint)
}else{
paint.color=attrBean.dotColor
canvas?.drawCircle(viewWidth.toFloat()/2,viewHeight.toFloat()/2,viewHeight.toFloat()/2,paint)
}
//写字
paint.color = attrBean.dotTextColor
paint.textSize = attrBean.dotTextSize.toFloat()
canvas?.drawText(mText.toString(),(viewWidth-textWidth).toFloat()/2+widthOffSet,(viewHeight+textHeight).toFloat()/2-1,paint)
}else{//画圆角矩形
//计算文字宽高
//画圆角矩形
if(attrBean.dotShowRing){
paint.color = attrBean.dotRingColor
val oval = RectF(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat())// 设置个新的长方形
canvas?.drawRoundRect(oval, viewHeight.toFloat()/2, viewHeight.toFloat()/2, paint)//第二个参数是x半径,第三个参数是y半径
paint.color = attrBean.dotColor
val oval2 = RectF(attrBean.dotRingWidth.toFloat(), attrBean.dotRingWidth.toFloat(), viewWidth.toFloat()-attrBean.dotRingWidth, viewHeight.toFloat()-attrBean.dotRingWidth)// 设置个新的长方形
canvas?.drawRoundRect(oval2, viewHeight.toFloat()/2-attrBean.dotRingWidth, viewHeight.toFloat()/2-attrBean.dotRingWidth, paint)//第二个参数是x半径,第三个参数是y半径
}else{
paint.color = attrBean.dotColor
val oval = RectF(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat())// 设置个新的长方形
canvas?.drawRoundRect(oval, viewHeight.toFloat()/2, viewHeight.toFloat()/2, paint)//第二个参数是x半径,第三个参数是y半径
}
//写字
paint.color = attrBean.dotTextColor
paint.textSize = attrBean.dotTextSize.toFloat()
if(mText>99){
canvas?.drawText(threeDot,(viewWidth-textWidth).toFloat()/2-5,(viewHeight+textHeight).toFloat()/2+6,paint)
}else{
canvas?.drawText(mText.toString(),(viewWidth-textWidth).toFloat()/2+widthOffSet,(viewHeight+textHeight).toFloat()/2-1,paint)
}
}
}
}
override fun setText(text:Int){
if (text==0){
visibility = GONE
}else{
visibility = VISIBLE
if(text==1){
widthOffSet=-4
}else{
widthOffSet=-1
}
}
mText = text
initWidthAHeight()
setOnlyDotMode(false)//设置数量时让只是红点模式为false
}
private fun initWidthAHeight(){
paint.textSize = attrBean.dotTextSize.toFloat()
if(mText>99){
paint.getTextBounds(threeDot,0,threeDot.length,rect)
}else{
paint.getTextBounds(mText.toString(),0,"$mText".length,rect)
}
textWidth = rect.width()
textHeight = rect.height()
if(mText >9){
viewWidth = attrBean.dotHeight+textWidth
}else if(mText in 1..9){
viewWidth = attrBean.dotHeight
}
viewHeight = attrBean.dotHeight
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
initParams()
}
override fun setOnlyDotMode(onlyDot:Boolean){
mOnlyDot = onlyDot
initParams()
invalidate()
}
/**
* 默认,
*/
override fun setOffset(view:View){
view.viewTreeObserver.addOnGlobalLayoutListener {
var x=0
var y=0
if (mOnlyDot){
x=Utils.dp2px(-5f)
y= Utils.dp2px(5f)
}else{
x=Utils.dp2px(-6f)
y=Utils.dp2px(7f)
}
setX(view.right.toFloat()-viewWidth/2+x)
setY(view.top.toFloat()-viewHeight/2+y)
}
}
//特殊定制,首页底部消息显示红点须要
override fun setOffset(view:View,x:Int,y:Int,x1:Int,y1:Int){
view.viewTreeObserver.addOnGlobalLayoutListener {
var w=0
var h=0
if (mOnlyDot){
w=Utils.dp2px(x.toFloat())
h=Utils.dp2px(y.toFloat())
}else{
w=Utils.dp2px(x1.toFloat())
h=Utils.dp2px(y1.toFloat())
}
setX(view.right.toFloat()-viewWidth/2+w)
setY(view.top.toFloat()-viewHeight/2+h)
}
}
private fun initParams(){
if(mOnlyDot){
visibility = VISIBLE
layoutParams.width = attrBean.dotDiameter
layoutParams.height = attrBean.dotDiameter
viewHeight = attrBean.dotDiameter
viewWidth = attrBean.dotDiameter
}else{
if(mText >9){
layoutParams.width = attrBean.dotHeight+textWidth
layoutParams.height = attrBean.dotHeight
}else{
layoutParams.width = attrBean.dotHeight
layoutParams.height = attrBean.dotHeight
}
}
requestLayout()
}
}
class DotViewAttr(context:Context,attrs:AttributeSet){
val dotColor: Int //绘制的圆圈颜色
val dotTextSize: Int //绘制的文本颜色
val dotHeight: Int //绘制的圆环view高度 ,由于宽度是自适应的,因此不须要写
var dotDiameter:Int=0 //当只显示小红点时绘制的点的直径
val dotTextColor: Int //绘制的文本的颜色
val dotShowRing:Boolean //当须要外部显示边时,设置此项为true
val dotRingColor:Int//要显示边的颜色
val dotRingWidth:Int//外圆环粗细程度 默认4像素
init {
val ta = context.obtainStyledAttributes(attrs, R.styleable.RedDotView)
dotColor = ta.getColor(R.styleable.RedDotView_dotColor,Color.RED)
dotTextSize = ta.getDimensionPixelSize(R.styleable.RedDotView_dotTextSize, 15)
dotDiameter = ta.getDimensionPixelSize(R.styleable.RedDotView_dotDiameter, 10)
dotHeight = ta.getDimensionPixelSize(R.styleable.RedDotView_dotHeight, 10)
dotTextColor = ta.getColor(R.styleable.RedDotView_dotTextColor, Color.WHITE)
dotRingColor = ta.getColor(R.styleable.RedDotView_dotRingColor, Color.WHITE)
dotShowRing = ta.getBoolean(R.styleable.RedDotView_dotShowRing,false)
dotRingWidth = ta.getDimensionPixelSize(R.styleable.RedDotView_dotRingWidth,4)
ta.recycle()
}
}
/**
* 红点显示接口,
*/
interface IRedDotView{
fun setText(text:Int)
fun setOnlyDotMode(onlyDot:Boolean)
fun setOffset(view:View)
fun setOffset(view:View,x:Int,y:Int,x1:Int,y1:Int)
}
复制代码
把此段代码直接放到attrs.xml文件中便可canvas
<declare-styleable name="RedDotView">
<attr name="dotColor" format="color"/>
<attr name="dotHeight" format="dimension"/>
<attr name="dotShowRing" format="boolean"/>
<attr name="dotTextSize"/>
<attr name="dotRingWidth" format="dimension"/>
<attr name="dotDiameter" format="dimension"/>
<attr name="dotTextColor" format="color"/>
<attr name="dotRingColor" format="color"/>
</declare-styleable>
复制代码