<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>
複製代碼