直播視頻app源碼,自定義可點擊可滑動的通用RatingBar實現(xiàn)的相關代碼
繪制ratingbar
?
繪制未選中的背景
?
/**
?* 未選中Bitmap
?*/
private val starBgBitmap: Bitmap by lazy {
? ? val bitmap = Bitmap.createBitmap(starSize, starSize, Bitmap.Config.ARGB_8888)
? ? val canvas = Canvas(bitmap)
? ? val starDrawable = ContextCompat.getDrawable(context, starBgDrawable)
? ? starDrawable?.setBounds(0, 0, starSize, starSize)
? ? starDrawable?.draw(canvas)
? ? bitmap
}
/**
?* 繪制星星默認未選中背景
?*/
private fun drawStar(canvas: Canvas) {
? ? for (i in 0 until starCount) {
? ? ? ? val starLeft = i * (starSize + starPadding)
? ? ? ? canvas.drawBitmap(starBgBitmap, starLeft, 0f, starBgPaint)
? ? }
}
?
繪制選中圖標
這里bitmap寬度使用starSize + starPadding,配合BitmapShader的repeat模式,可以方便繪制出高亮的圖標
?
/**
?* 選中icon的Bitmap
?*/
private val starBitmap: Bitmap by lazy {
? ? val bitmap = Bitmap.createBitmap(starSize + starPadding.toInt(), starSize, Bitmap.Config.ARGB_8888)
? ? val canvas = Canvas(bitmap)
? ? val starDrawable = ContextCompat.getDrawable(context, starDrawable)
? ? starDrawable?.setBounds(0, 0, starSize, starSize)
? ? starDrawable?.draw(canvas)
? ? bitmap
}
/**
?* 繪制高亮圖標
?*/
private fun drawStarDrawable(canvas: Canvas) {
? ? starDrawablePaint.shader = BitmapShader(starBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)
? ? canvas.drawRect(0f, 0f, getStarProgressWidth(), height.toFloat(), starDrawablePaint)
}
?
繪制純色的選中效果
使用離屏緩沖,純色矩形與未選中背景相交的地方進行顯示。具體使用可以參考扔物線大佬的文章
?
/**
?* 星星純色畫筆
?*/
private val starPaint = Paint().apply {
? ? isAntiAlias = true
? ? xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
}
canvas?.let {
? ? // xfermode需要使用離屏緩存
? ? val saved = it.saveLayer(null, null)
? ? drawStar(it)
? ? if (starDrawable == -1) {
? ? ? ? drawStarBgColor(it)
? ? } else {
? ? ? ? drawStarDrawable(it)
? ? }
? ? it.restoreToCount(saved)
}
/**
?* 繪制高亮純顏色
?*/
private fun drawStarBgColor(canvas: Canvas) {
? ? canvas.drawRect(0f, 0f, getStarProgressWidth(), height.toFloat(), starPaint)
}
?
繪制進度
?
根據(jù)type更正顯示效果,是取半,取整還是任意取進度。open方法,可以方便修改
?
/**
?* 獲取星星繪制寬度
?*/
private fun getStarProgressWidth(): Float {
? ? val percent = progress / 100f
? ? val starDrawCount = percent * starCount
? ? return when (starType) {
? ? ? ? StarType.HALF.ordinal -> {
? ? ? ? ? ? ceilHalf(starDrawCount) * starSize + starDrawCount.toInt() * starPadding
? ? ? ? }
? ? ? ? StarType.WHOLE.ordinal -> {
? ? ? ? ? ? ceilWhole(starDrawCount) * starSize + starDrawCount.toInt() * starPadding
? ? ? ? }
? ? ? ? else -> {
? ? ? ? ? ? starDrawCount * starSize + starDrawCount.toInt() * starPadding
? ? ? ? }
? ? }
}
/**
?* 取整規(guī)則
?*/
private fun ceilWhole(x: Float): Float {
? ? return ceil(x)
}
/**
?* 取半規(guī)則
?*/
private fun ceilHalf(x: Float): Float {
? ? // 四舍五入 1.3->1+0.5->1.5 1.7->2
? ? val round = round(x)
? ? return when {
? ? ? ? round < x -> round + 0.5f
? ? ? ? round > x -> round
? ? ? ? else -> x
? ? }
}
?
點擊+滑動
?
點擊+滑動就是重寫onTouchEvent事件:
?
判斷點擊位置是否在范圍內
/**
?* 點擊的point是否在view范圍內
?*/
private fun pointInView(x: Float, y: Float): Boolean {
? ? return Rect(0, 0, width, height).contains(x.toInt(), y.toInt())
}
?
記錄按下位置,抬起位置。
?
MotionEvent.ACTION_DOWN -> {
? ? downX = event.x
? ? downY = event.y
}
MotionEvent.ACTION_UP -> {
? ? if (starClickable && abs(event.y - downY) <= touchSlop && abs(event.x - downX) <= touchSlop && pointInView(event.x, event.y)) {
? ? ? ? parent.requestDisallowInterceptTouchEvent(true)
? ? ? ? val progress = (event.x / width * 100).toInt()
? ? ? ? setProgress(progress)
? ? ? ? listener?.onClickProgress(progress)
? ? } else {
? ? ? ? parent.requestDisallowInterceptTouchEvent(false)
? ? }
}
?
滑動記錄手指move
?
MotionEvent.ACTION_MOVE -> {
? ? if (starScrollable && abs(event.x - downX) - abs(event.y - downY) >= touchSlop && pointInView(event.x, event.y)) {
? ? ? ? parent.requestDisallowInterceptTouchEvent(true)
? ? ? ? val progress = (event.x / width * 100).toInt()
? ? ? ? setProgress(progress)
? ? ? ? listener?.onScrollProgress(progress)
? ? } else {
? ? ? ? parent.requestDisallowInterceptTouchEvent(false)
? ? }
}
?
以上就是 直播視頻app源碼,自定義可點擊可滑動的通用RatingBar實現(xiàn)的相關代碼,更多內容歡迎關注之后的文章
?
本文摘自 :https://www.cnblogs.com/