美文网首页
TriangleLabelView

TriangleLabelView

作者: CentForever | 来源:发表于2020-12-30 23:57 被阅读0次
    
    
    import android.annotation.TargetApi
    import android.content.Context
    import android.graphics.*
    import android.os.Build
    import android.util.AttributeSet
    import android.view.View
    import androidx.annotation.ColorInt
    import androidx.annotation.ColorRes
    import androidx.annotation.IntDef
    import androidx.annotation.StringRes
    import androidx.core.content.ContextCompat
    import com.tencent.wemeet.sdk.R
    import kotlin.math.sqrt
    
    class TriangleLabelView : View {
        private class PaintHolder {
            var text = ""
            var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
            var color = 0
            var size = 0f
            var height = 0f
            var width = 0f
            @PrimaryTextStyle
            var style = NORMAL
            fun initPaint() {
                paint.color = color
                paint.textAlign = Paint.Align.CENTER
                paint.textSize = size
                when (style) {
                    SANS_SERIF -> {
                        paint.typeface = Typeface.SANS_SERIF
                    }
                    DEFAULT_BOLD -> {
                        paint.typeface = Typeface.DEFAULT_BOLD
                    }
                    else -> {
                        paint.typeface = Typeface.MONOSPACE
                    }
                }
            }
    
            fun resetStatus() {
                val rectText = Rect()
                paint.getTextBounds(text, 0, text.length, rectText)
                width = rectText.width().toFloat()
                height = rectText.height().toFloat()
            }
        }
    
        private val primary = PaintHolder()
        private val secondary = PaintHolder()
        private var topPadding = 0f
        private var bottomPadding = 0f
        private var centerPadding = 0f
        private var trianglePaint: Paint? = null
        var triangleBackGroundColor = 0
            private set
        private var width = 0f
        private var height = 0f
        private var corner: Corner? = null
    
        enum class Corner(private val type: Int) {
            TOP_LEFT(1), TOP_RIGHT(2), BOTTOM_LEFT(3), BOTTOM_RIGHT(4);
    
            fun top(): Boolean {
                return this == TOP_LEFT || this == TOP_RIGHT
            }
    
            fun left(): Boolean {
                return this == TOP_LEFT || this == BOTTOM_LEFT
            }
    
            companion object {
                fun from(type: Int): Corner {
                    for (c in values()) {
                        if (c.type == type) return c
                    }
                    return TOP_LEFT
                }
            }
        }
    
        @JvmOverloads
        constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : super(context, attrs, defStyleAttr) {
            init(context, attrs)
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
            init(context, attrs)
        }
    
        private fun init(context: Context, attrs: AttributeSet?) {
            val ta = context.obtainStyledAttributes(attrs, R.styleable.TriangleLabelView)
            topPadding = ta.getDimension(R.styleable.TriangleLabelView_labelTopPadding, dp2px(7f).toFloat())
            centerPadding = ta.getDimension(R.styleable.TriangleLabelView_labelCenterPadding, dp2px(3f).toFloat())
            bottomPadding = ta.getDimension(R.styleable.TriangleLabelView_labelBottomPadding, dp2px(3f).toFloat())
            triangleBackGroundColor = ta.getColor(R.styleable.TriangleLabelView_backgroundColor, Color.parseColor("#66000000"))
            primary.color = ta.getColor(R.styleable.TriangleLabelView_primaryTextColor, Color.WHITE)
            secondary.color = ta.getColor(R.styleable.TriangleLabelView_secondaryTextColor, Color.WHITE)
            primary.size = ta.getDimension(R.styleable.TriangleLabelView_primaryTextSize, sp2px(11f))
            secondary.size = ta.getDimension(R.styleable.TriangleLabelView_secondaryTextSize, sp2px(8f))
            val primary = ta.getString(R.styleable.TriangleLabelView_primaryText)
            if (primary != null) {
                this.primary.text = primary
            }
            val secondary = ta.getString(R.styleable.TriangleLabelView_secondaryText)
            if (secondary != null) {
                this.secondary.text = secondary
            }
            this.primary.style = ta.getInt(R.styleable.TriangleLabelView_primaryTextStyle, 2)
            this.secondary.style = ta.getInt(R.styleable.TriangleLabelView_secondaryTextStyle, 0)
            corner = Corner.from(ta.getInt(R.styleable.TriangleLabelView_corner, 1))
            ta.recycle()
            this.primary.initPaint()
            this.secondary.initPaint()
            trianglePaint = Paint(Paint.ANTI_ALIAS_FLAG)
            trianglePaint?.color = triangleBackGroundColor
            this.primary.resetStatus()
            this.secondary.resetStatus()
        }
    
        var labelTopPadding: Float
            get() = topPadding
            set(dp) {
                topPadding = dp2px(dp).toFloat()
            }
    
        var labelCenterPadding: Float
            get() = centerPadding
            set(dp) {
                centerPadding = dp2px(dp).toFloat()
                relayout()
            }
    
        var labelBottomPadding: Float
            get() = bottomPadding
            set(dp) {
                bottomPadding = dp2px(dp).toFloat()
                relayout()
            }
    
        fun setPrimaryText(@StringRes textRes: Int) {
            primary.text = context.getString(textRes)
            primary.resetStatus()
            relayout()
        }
    
        var primaryText: String
            get() = primary.text
            set(text) {
                primary.text = text
                primary.resetStatus()
                relayout()
            }
    
        fun setSecondaryText(@StringRes textRes: Int) {
            secondary.text = context.getString(textRes)
            secondary.resetStatus()
            relayout()
        }
    
        var secondaryText: String
            get() = secondary.text
            set(smallText) {
                secondary.text = smallText
                secondary.resetStatus()
                relayout()
            }
    
        fun setPrimaryTextColor(@ColorInt color: Int) {
            primary.color = color
            primary.initPaint()
            primary.resetStatus()
            relayout()
        }
    
        fun setPrimaryTextColorResource(@ColorRes colorResource: Int) {
            primary.color = ContextCompat.getColor(context, colorResource)
            primary.initPaint()
            primary.resetStatus()
            relayout()
        }
    
        fun setSecondaryTextColor(@ColorInt color: Int) {
            secondary.color = color
            secondary.initPaint()
            secondary.resetStatus()
            relayout()
        }
    
        fun setSecondaryTextColorResource(@ColorRes colorResource: Int) {
            secondary.color = ContextCompat.getColor(context, colorResource)
            secondary.initPaint()
            secondary.resetStatus()
            relayout()
        }
    
        var primaryTextSize: Float
            get() = primary.size
            set(sp) {
                primary.size = sp2px(sp)
                relayout()
            }
    
        var secondaryTextSize: Float
            get() = secondary.size
            set(sp) {
                secondary.size = sp2px(sp)
                relayout()
            }
    
        fun setTriangleBackgroundColor(@ColorInt color: Int) {
            triangleBackGroundColor = color
            trianglePaint?.color = triangleBackGroundColor
            relayout()
        }
    
        fun setTriangleBackgroundColorResource(@ColorRes colorResource: Int) {
            triangleBackGroundColor = ContextCompat.getColor(context, colorResource)
            trianglePaint?.color = triangleBackGroundColor
            relayout()
        }
    
        fun setCorner(corner: Corner?) {
            this.corner = corner
            relayout()
        }
    
        fun getCorner(): Corner? {
            return corner
        }
    
        override fun onDraw(canvas: Canvas) {
            super.onDraw(canvas)
            canvas.save()
    
            // translate
            if (corner?.top() == true) {
                canvas.translate(0f, (height * sqrt(2.0) - height).toFloat())
            }
    
            // rotate
            if (corner?.top() == true) {
                if (corner?.left() == true) {
                    canvas.rotate(DEGREES_LEFT.toFloat(), 0f, height.toFloat())
                } else {
                    canvas.rotate(DEGREES_RIGHT.toFloat(), width.toFloat(), height.toFloat())
                }
            } else {
                if (corner?.left() == true) {
                    canvas.rotate(DEGREES_RIGHT.toFloat(), 0f, 0f)
                } else {
                    canvas.rotate(DEGREES_LEFT.toFloat(), width.toFloat(), 0f)
                }
            }
    
            // draw triangle
            val path = Path()
            if (corner?.top() == true) {
                path.moveTo(0f, height.toFloat())
                path.lineTo(width / 2.toFloat(), 0f)
                path.lineTo(width.toFloat(), height.toFloat())
            } else {
                path.moveTo(0f, 0f)
                path.lineTo(width / 2.toFloat(), height.toFloat())
                path.lineTo(width.toFloat(), 0f)
            }
            path.close()
            if (trianglePaint != null) {
                canvas.drawPath(path, trianglePaint!!)
            }
    
            // draw secondaryText
            if (corner?.top() == true) {
                canvas.drawText(secondary.text, width / 2.toFloat(), topPadding + secondary.height, secondary.paint)
                canvas.drawText(primary.text, width / 2.toFloat(), topPadding + secondary.height + centerPadding + primary.height, primary.paint)
            } else {
                canvas.drawText(secondary.text, width / 2.toFloat(), bottomPadding + secondary.height + centerPadding + primary.height, secondary.paint)
                canvas.drawText(primary.text, width / 2.toFloat(), bottomPadding + primary.height, primary.paint)
            }
            canvas.restore()
        }
    
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
            height = (topPadding + centerPadding + bottomPadding + secondary.height + primary.height).toInt().toFloat()
            width = 2 * height
            val realHeight = (height * sqrt(2.0)).toInt()
            setMeasuredDimension(width.toInt(), realHeight)
        }
    
        fun dp2px(dpValue: Float): Int {
            val scale = context.resources.displayMetrics.density
            return (dpValue * scale + 0.5f).toInt()
        }
    
        fun sp2px(spValue: Float): Float {
            val scale = context.resources.displayMetrics.scaledDensity
            return spValue * scale
        }
    
        /**
         * Should be called whenever what we're displaying could have changed.
         */
        private fun relayout() {
            invalidate()
            requestLayout()
        }
    
        companion object {
            private val TAG = TriangleLabelView::class.java.simpleName
            private const val DEGREES_LEFT = -45
            private const val DEGREES_RIGHT = 45
    
            const val NORMAL = 0
            const val SANS_SERIF = 1
            const val DEFAULT_BOLD = 2
        }
    
        @IntDef(NORMAL, SANS_SERIF, DEFAULT_BOLD)
        annotation class PrimaryTextStyle
    }
    
    
    <declare-styleable name="TriangleLabelView">
            <attr name="backgroundColor" format="color" />
            <attr name="primaryTextColor" format="color" />
            <attr name="secondaryTextColor" format="color" />
            <attr name="primaryText" format="string" />
            <attr name="secondaryText" format="string" />
            <attr name="primaryTextSize" format="dimension" />
            <attr name="secondaryTextSize" format="dimension" />
            <attr name="labelTopPadding" format="dimension" />
            <attr name="labelCenterPadding" format="dimension" />
            <attr name="labelBottomPadding" format="dimension" />
            <attr name="primaryTextStyle">
                <enum name="normal" value="0" />
                <enum name="italic" value="1" />
                <enum name="bold" value="2" />
            </attr>
            <attr name="secondaryTextStyle">
                <enum name="normal" value="0" />
                <enum name="italic" value="1" />
                <enum name="bold" value="2" />
            </attr>
            <attr name="corner">
                <enum name="leftTop" value="1" />
                <enum name="rightTop" value="2" />
                <enum name="leftBottom" value="3" />
                <enum name="rightBottom" value="4" />
            </attr>
        </declare-styleable>
    

    相关文章

      网友评论

          本文标题:TriangleLabelView

          本文链接:https://www.haomeiwen.com/subject/fgtnnktx.html