字体选择 自定义view
This commit is contained in:
parent
3c8b119a3a
commit
656826c41b
|
|
@ -0,0 +1,302 @@
|
||||||
|
package com.remax.visualnovel.ui.chat.ui
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.*
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import com.remax.visualnovel.R
|
||||||
|
import com.remax.visualnovel.utils.ResUtil
|
||||||
|
import com.remax.visualnovel.utils.spannablex.utils.dp
|
||||||
|
|
||||||
|
|
||||||
|
class LevelSeekBar @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : View(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private var totalLevels = 5
|
||||||
|
private var currentLevel = 2
|
||||||
|
|
||||||
|
// 尺寸
|
||||||
|
private var trackHeight = ResUtil.getPixelSize(R.dimen.dp_5).toFloat()
|
||||||
|
private var trackEndRadius = ResUtil.getPixelSize(R.dimen.dp_8).toFloat()
|
||||||
|
private var thumbRadius = ResUtil.getPixelSize(R.dimen.dp_9).toFloat()
|
||||||
|
private var nodeRadius = ResUtil.getPixelSize(R.dimen.dp_3).toFloat()
|
||||||
|
private val nodeWidth = ResUtil.getPixelSize(R.dimen.dp_5)
|
||||||
|
private val nodeHeight= ResUtil.getPixelSize(R.dimen.dp_11)
|
||||||
|
|
||||||
|
|
||||||
|
// 颜色
|
||||||
|
private var trackColor = ResUtil.getColor(R.color.seekbar_color)
|
||||||
|
private var thumbColor = ResUtil.getColor(R.color.white)
|
||||||
|
private var activeTrackColor = trackColor
|
||||||
|
private var thumbBorderColor = trackColor
|
||||||
|
private var nodeColor = trackColor
|
||||||
|
private var activeNodeColor = trackColor
|
||||||
|
|
||||||
|
|
||||||
|
// 画笔
|
||||||
|
private val trackPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||||
|
private val thumbPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||||
|
private val thumbBorderPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||||
|
private val nodePaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||||
|
|
||||||
|
// 监听器
|
||||||
|
private var onLevelChangeListener: OnLevelChangeListener? = null
|
||||||
|
private var isDragging = false
|
||||||
|
|
||||||
|
|
||||||
|
// 触摸相关
|
||||||
|
private var lastTouchX = 0f
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface OnLevelChangeListener {
|
||||||
|
fun onLevelChanged(seekBar: LevelSeekBar, level: Int, fromUser: Boolean)
|
||||||
|
fun onStartTrackingTouch(seekBar: LevelSeekBar)
|
||||||
|
fun onStopTrackingTouch(seekBar: LevelSeekBar)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
setupAttributes(attrs)
|
||||||
|
setupPaints()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupAttributes(attrs: AttributeSet?) {
|
||||||
|
attrs?.let {
|
||||||
|
val typedArray = context.obtainStyledAttributes(it, R.styleable.CustomLevelSeekBar)
|
||||||
|
|
||||||
|
totalLevels = typedArray.getInt(R.styleable.CustomLevelSeekBar_totalLevels, totalLevels)
|
||||||
|
currentLevel = typedArray.getInt(R.styleable.CustomLevelSeekBar_currentLevel, currentLevel)
|
||||||
|
.coerceIn(0, totalLevels - 1)
|
||||||
|
|
||||||
|
trackColor = typedArray.getColor(R.styleable.CustomLevelSeekBar_trackColor, trackColor)
|
||||||
|
activeTrackColor = typedArray.getColor(R.styleable.CustomLevelSeekBar_activeTrackColor, activeTrackColor)
|
||||||
|
thumbColor = typedArray.getColor(R.styleable.CustomLevelSeekBar_thumbColor, thumbColor)
|
||||||
|
thumbBorderColor = typedArray.getColor(R.styleable.CustomLevelSeekBar_thumbBorderColor, thumbBorderColor)
|
||||||
|
nodeColor = typedArray.getColor(R.styleable.CustomLevelSeekBar_nodeColor, nodeColor)
|
||||||
|
activeNodeColor = typedArray.getColor(R.styleable.CustomLevelSeekBar_activeNodeColor, activeNodeColor)
|
||||||
|
|
||||||
|
trackHeight = typedArray.getDimension(R.styleable.CustomLevelSeekBar_trackHeight, trackHeight)
|
||||||
|
trackEndRadius = typedArray.getDimension(R.styleable.CustomLevelSeekBar_trackEndRadius, trackEndRadius)
|
||||||
|
thumbRadius = typedArray.getDimension(R.styleable.CustomLevelSeekBar_thumbRadius, thumbRadius)
|
||||||
|
nodeRadius = typedArray.getDimension(R.styleable.CustomLevelSeekBar_nodeRadius, nodeRadius)
|
||||||
|
|
||||||
|
typedArray.recycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupPaints() {
|
||||||
|
trackPaint.style = Paint.Style.FILL
|
||||||
|
|
||||||
|
thumbBorderPaint.style = Paint.Style.STROKE
|
||||||
|
//thumbBorderPaint.strokeWidth = 1F.dp.toFloat()
|
||||||
|
thumbBorderPaint.color = thumbBorderColor
|
||||||
|
|
||||||
|
thumbPaint.style = Paint.Style.FILL
|
||||||
|
thumbPaint.color = thumbColor
|
||||||
|
|
||||||
|
nodePaint.style = Paint.Style.FILL
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
super.onDraw(canvas)
|
||||||
|
drawTrack(canvas)
|
||||||
|
drawNodes(canvas)
|
||||||
|
drawThumb(canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawTrack(canvas: Canvas) {
|
||||||
|
val centerY = height / 2f
|
||||||
|
val trackTop = centerY - trackHeight / 2
|
||||||
|
val trackBottom = centerY + trackHeight / 2
|
||||||
|
|
||||||
|
trackPaint.color = trackColor
|
||||||
|
val trackRect = RectF(0f + nodeWidth/2, trackTop, width.toFloat(), trackBottom - nodeWidth/2)
|
||||||
|
canvas.drawRoundRect(trackRect, trackEndRadius, trackEndRadius, trackPaint)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawNodes(canvas: Canvas) {
|
||||||
|
if (totalLevels <= 1) return
|
||||||
|
|
||||||
|
val centerY = height / 2f
|
||||||
|
|
||||||
|
for (i in 0 until totalLevels) {
|
||||||
|
val x = calculatePositionForLevel(i)
|
||||||
|
|
||||||
|
nodePaint.color = if (i <= currentLevel) activeNodeColor else nodeColor
|
||||||
|
//canvas.drawCircle(x, centerY, nodeRadius, nodePaint)
|
||||||
|
val trackRect = RectF(x - thumbRadius/2, centerY - nodeHeight/2 + 6, x + thumbRadius/2, centerY + nodeHeight/2)
|
||||||
|
canvas.drawRoundRect(trackRect, trackEndRadius, trackEndRadius, nodePaint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawThumb(canvas: Canvas) {
|
||||||
|
if (totalLevels <= 1) return
|
||||||
|
|
||||||
|
val centerY = height / 2f
|
||||||
|
val thumbX = calculatePositionForLevel(currentLevel)
|
||||||
|
|
||||||
|
canvas.drawCircle(thumbX, centerY, thumbRadius, thumbBorderPaint)
|
||||||
|
canvas.drawCircle(thumbX, centerY, thumbRadius - 1F.dp.toFloat(), thumbPaint)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun calculatePositionForLevel(level: Int): Float {
|
||||||
|
if (totalLevels <= 1) return width / 2f
|
||||||
|
|
||||||
|
val availableWidth = width - 2 * thumbRadius
|
||||||
|
return thumbRadius + (availableWidth * level.toFloat() / (totalLevels - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
when (event.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
if (isPointInThumb(event.x, event.y) || isPointInTrack(event.x, event.y)) {
|
||||||
|
isDragging = true
|
||||||
|
lastTouchX = event.x
|
||||||
|
onLevelChangeListener?.onStartTrackingTouch(this)
|
||||||
|
handleTouch(event.x)
|
||||||
|
parent?.requestDisallowInterceptTouchEvent(true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
if (isDragging) {
|
||||||
|
lastTouchX = event.x
|
||||||
|
handleTouch(event.x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||||
|
if (isDragging) {
|
||||||
|
isDragging = false
|
||||||
|
snapToNearestLevel(lastTouchX)
|
||||||
|
onLevelChangeListener?.onStopTrackingTouch(this)
|
||||||
|
parent?.requestDisallowInterceptTouchEvent(false)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isPointInThumb(x: Float, y: Float): Boolean {
|
||||||
|
val thumbX = calculatePositionForLevel(currentLevel)
|
||||||
|
val centerY = height / 2f
|
||||||
|
val distance = Math.sqrt(
|
||||||
|
(x - thumbX) * (x - thumbX) + (y - centerY) * (y - centerY).toDouble()
|
||||||
|
)
|
||||||
|
return distance <= thumbRadius
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isPointInTrack(x: Float, y: Float): Boolean {
|
||||||
|
val centerY = height / 2f
|
||||||
|
val trackTop = centerY - trackHeight / 2 - thumbRadius // 扩大触摸区域
|
||||||
|
val trackBottom = centerY + trackHeight / 2 + thumbRadius
|
||||||
|
return x in 0f..width.toFloat() && y in trackTop..trackBottom
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleTouch(x: Float) {
|
||||||
|
if (totalLevels <= 1) return
|
||||||
|
|
||||||
|
val newLevel = calculateLevelForPosition(x)
|
||||||
|
if (newLevel != currentLevel) {
|
||||||
|
currentLevel = newLevel
|
||||||
|
invalidate()
|
||||||
|
onLevelChangeListener?.onLevelChanged(this, currentLevel, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun snapToNearestLevel(x: Float) {
|
||||||
|
if (totalLevels <= 1) return
|
||||||
|
|
||||||
|
val exactLevel = calculateExactLevelForPosition(x)
|
||||||
|
val newLevel = (exactLevel + 0.5f).toInt().coerceIn(0, totalLevels - 1)
|
||||||
|
|
||||||
|
if (newLevel != currentLevel) {
|
||||||
|
currentLevel = newLevel
|
||||||
|
invalidate()
|
||||||
|
onLevelChangeListener?.onLevelChanged(this, currentLevel, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun calculateLevelForPosition(x: Float): Int {
|
||||||
|
if (totalLevels <= 1) return 0
|
||||||
|
|
||||||
|
val availableWidth = width - 2 * thumbRadius
|
||||||
|
val progress = ((x - thumbRadius) / availableWidth).coerceIn(0f, 1f)
|
||||||
|
return (progress * (totalLevels - 1)).toInt().coerceIn(0, totalLevels - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun calculateExactLevelForPosition(x: Float): Float {
|
||||||
|
if (totalLevels <= 1) return 0f
|
||||||
|
|
||||||
|
val availableWidth = width - 2 * thumbRadius
|
||||||
|
val progress = ((x - thumbRadius) / availableWidth).coerceIn(0f, 1f)
|
||||||
|
return progress * (totalLevels - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------- public 设置方法 ---------------------------------//
|
||||||
|
fun setLevel(level: Int, fromUser: Boolean = false) {
|
||||||
|
val newLevel = level.coerceIn(0, totalLevels - 1)
|
||||||
|
if (newLevel != currentLevel) {
|
||||||
|
currentLevel = newLevel
|
||||||
|
invalidate()
|
||||||
|
onLevelChangeListener?.onLevelChanged(this, currentLevel, fromUser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLevel(): Int = currentLevel
|
||||||
|
|
||||||
|
fun setTotalLevels(levels: Int) {
|
||||||
|
if (levels > 0 && levels != totalLevels) {
|
||||||
|
totalLevels = levels
|
||||||
|
currentLevel = currentLevel.coerceIn(0, totalLevels - 1)
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTotalLevels(): Int = totalLevels
|
||||||
|
|
||||||
|
fun setOnLevelChangeListener(listener: OnLevelChangeListener) {
|
||||||
|
this.onLevelChangeListener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setOnLevelChangeListener(
|
||||||
|
onLevelChanged: (LevelSeekBar, Int, Boolean) -> Unit = { _, _, _ -> },
|
||||||
|
onStartTrackingTouch: (LevelSeekBar) -> Unit = {},
|
||||||
|
onStopTrackingTouch: (LevelSeekBar) -> Unit = {}
|
||||||
|
) {
|
||||||
|
this.onLevelChangeListener = object : OnLevelChangeListener {
|
||||||
|
override fun onLevelChanged(seekBar: LevelSeekBar, level: Int, fromUser: Boolean) {
|
||||||
|
onLevelChanged(seekBar, level, fromUser)
|
||||||
|
}
|
||||||
|
override fun onStartTrackingTouch(seekBar: LevelSeekBar) {
|
||||||
|
onStartTrackingTouch(seekBar)
|
||||||
|
}
|
||||||
|
override fun onStopTrackingTouch(seekBar: LevelSeekBar) {
|
||||||
|
onStopTrackingTouch(seekBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
val minWidth = suggestedMinimumWidth + paddingLeft + paddingRight
|
||||||
|
val minHeight = (thumbRadius * 2 + paddingTop + paddingBottom).toInt()
|
||||||
|
|
||||||
|
val width = resolveSizeAndState(minWidth, widthMeasureSpec, 1)
|
||||||
|
val height = resolveSizeAndState(minHeight, heightMeasureSpec, 1)
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
package com.remax.visualnovel.utils
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.util.TypedValue
|
||||||
|
import androidx.annotation.*
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.remax.visualnovel.configs.NovelApplication
|
||||||
|
|
||||||
|
object ResUtil {
|
||||||
|
|
||||||
|
private val appContext = NovelApplication.appContext()
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Dimen相关 ====================
|
||||||
|
/**
|
||||||
|
* 获取dp值对应的像素值
|
||||||
|
*/
|
||||||
|
fun dp(dpValue: Float): Float {
|
||||||
|
return dpValue * appContext.resources.displayMetrics.density
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dp(dpValue: Int): Float {
|
||||||
|
return dp(dpValue.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取dp值对应的像素值(取整)
|
||||||
|
*/
|
||||||
|
fun dpToPx(dpValue: Float): Int {
|
||||||
|
return (dp(dpValue) + 0.5f).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dpToPx(dpValue: Int): Int {
|
||||||
|
return dpToPx(dpValue.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取sp值对应的像素值
|
||||||
|
*/
|
||||||
|
fun sp(spValue: Float): Float {
|
||||||
|
return spValue * appContext.resources.displayMetrics.scaledDensity
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sp(spValue: Int): Float {
|
||||||
|
return sp(spValue.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从dimen资源获取像素值
|
||||||
|
*/
|
||||||
|
fun getPixelSize(@DimenRes dimenRes: Int): Int {
|
||||||
|
return appContext.resources.getDimensionPixelSize(dimenRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDimension(@DimenRes dimenRes: Int): Float {
|
||||||
|
return appContext.resources.getDimension(dimenRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 颜色相关 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从颜色资源获取颜色值
|
||||||
|
*/
|
||||||
|
fun getColor(@ColorRes colorRes: Int): Int {
|
||||||
|
return ContextCompat.getColor(appContext, colorRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从颜色资源获取颜色值(带透明度)
|
||||||
|
*/
|
||||||
|
fun getColor(@ColorRes colorRes: Int, alpha: Float): Int {
|
||||||
|
val color = getColor(colorRes)
|
||||||
|
return applyAlphaToColor(color, alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析颜色字符串
|
||||||
|
*/
|
||||||
|
fun parseColor(colorString: String): Int {
|
||||||
|
return try {
|
||||||
|
Color.parseColor(colorString)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
Color.BLACK // 默认颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给颜色应用透明度
|
||||||
|
*/
|
||||||
|
fun applyAlphaToColor(color: Int, alpha: Float): Int {
|
||||||
|
val alphaValue = (alpha.coerceIn(0f, 1f) * 255).toInt()
|
||||||
|
return color and 0x00FFFFFF or (alphaValue shl 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主题颜色属性
|
||||||
|
*/
|
||||||
|
fun getColorAttr(@AttrRes attrRes: Int): Int {
|
||||||
|
val typedValue = TypedValue()
|
||||||
|
appContext.theme.resolveAttribute(attrRes, typedValue, true)
|
||||||
|
return typedValue.data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==================== 扩展函数 ====================
|
||||||
|
/**
|
||||||
|
* Float的扩展函数:转换为dp像素值
|
||||||
|
*/
|
||||||
|
val Float.dp: Float
|
||||||
|
get() = ResUtil.dp(this)
|
||||||
|
|
||||||
|
val Float.dpToPx: Int
|
||||||
|
get() = ResUtil.dpToPx(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Int的扩展函数:转换为dp像素值
|
||||||
|
*/
|
||||||
|
val Int.dp: Float
|
||||||
|
get() = ResUtil.dp(this)
|
||||||
|
|
||||||
|
val Int.dpToPx: Int
|
||||||
|
get() = ResUtil.dpToPx(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Float的扩展函数:转换为sp像素值
|
||||||
|
*/
|
||||||
|
val Float.sp: Float
|
||||||
|
get() = ResUtil.sp(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串的扩展函数:解析颜色
|
||||||
|
*/
|
||||||
|
val String.colorInt: Int
|
||||||
|
get() = ResUtil.parseColor(this)
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -233,6 +233,7 @@
|
||||||
android:id="@+id/font_set_view"
|
android:id="@+id/font_set_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="@dimen/dp_5"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<com.remax.visualnovel.ui.chat.ui.expandableSelector.ExpandChatModeSelectView
|
<com.remax.visualnovel.ui.chat.ui.expandableSelector.ExpandChatModeSelectView
|
||||||
|
|
@ -298,14 +299,15 @@
|
||||||
|
|
||||||
<!-- Delete related -->
|
<!-- Delete related -->
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout
|
<com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout
|
||||||
|
android:id="@+id/ll_delete"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_marginTop="28dp"
|
android:layout_marginTop="28dp"
|
||||||
app:strokeColorToken="@string/color_outline_normal"
|
app:advStrokeWidth="@dimen/dp_3"
|
||||||
app:strokeWidthToken="@string/border_s"
|
app:advStrokeColor="@color/red_ff3b30"
|
||||||
app:backgroundColorToken="@string/color_background_specialmap"
|
app:advRadius="@dimen/dp_25"
|
||||||
app:radiusToken="@string/radius_round" >
|
>
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenTextView
|
<com.remax.visualnovel.widget.uitoken.view.UITokenTextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -316,7 +318,7 @@
|
||||||
android:drawablePadding="@dimen/dp_10"
|
android:drawablePadding="@dimen/dp_10"
|
||||||
app:drawableLeftCompat="@mipmap/setting_delete"
|
app:drawableLeftCompat="@mipmap/setting_delete"
|
||||||
android:textSize="@dimen/sp_26"
|
android:textSize="@dimen/sp_26"
|
||||||
android:textColor="@color/glo_color_red_40"
|
android:textColor="@color/red_ff3b30"
|
||||||
/>
|
/>
|
||||||
</com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout>
|
</com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout>
|
||||||
|
|
||||||
|
|
@ -324,4 +326,4 @@
|
||||||
|
|
||||||
</com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout>
|
</com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
@ -1,75 +1,96 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenRelativeLayout
|
<com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/titleLayout"
|
android:id="@+id/titleLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:backgroundColorToken="@string/color_chat_setting_item_bg"
|
app:backgroundColorToken="@string/color_chat_setting_item_bg"
|
||||||
|
android:orientation="vertical"
|
||||||
app:radiusToken="@string/radius_m"
|
app:radiusToken="@string/radius_m"
|
||||||
android:paddingVertical="@dimen/dp_12"
|
android:paddingVertical="@dimen/dp_12"
|
||||||
android:paddingHorizontal="@dimen/dp_17"
|
android:paddingHorizontal="@dimen/dp_17"
|
||||||
>
|
>
|
||||||
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout
|
<com.remax.visualnovel.widget.uitoken.view.UITokenRelativeLayout
|
||||||
android:id="@+id/left_container"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
|
||||||
android:id="@+id/iv_left_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:src="@mipmap/setting_font_icon"/>
|
|
||||||
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenTextView
|
|
||||||
android:id="@+id/tv_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/dp_10"
|
|
||||||
android:layout_marginEnd="@dimen/dp_50"
|
|
||||||
android:textSize="@dimen/sp_14"
|
|
||||||
android:textColor="@color/gray6"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:text="@string/font_size"
|
|
||||||
/>
|
|
||||||
</com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content" >
|
||||||
android:layout_toEndOf="@+id/left_container">
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
<com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout
|
||||||
android:id="@+id/iv_font_plus"
|
android:id="@+id/left_container"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerVertical="true"
|
android:gravity="center_vertical"
|
||||||
android:src="@mipmap/setting_font_plus"/>
|
android:orientation="horizontal">
|
||||||
|
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
||||||
|
android:id="@+id/iv_left_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@mipmap/setting_font_icon"/>
|
||||||
|
|
||||||
|
<com.remax.visualnovel.widget.uitoken.view.UITokenTextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/dp_10"
|
||||||
|
android:layout_marginEnd="@dimen/dp_50"
|
||||||
|
android:textSize="@dimen/sp_14"
|
||||||
|
android:textColor="@color/gray6"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@string/font_size"
|
||||||
|
/>
|
||||||
|
</com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout>
|
||||||
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenTextView
|
<com.remax.visualnovel.widget.uitoken.view.UITokenTextView
|
||||||
android:id="@+id/tv_font_value"
|
android:id="@+id/tv_font_value"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toEndOf="@id/iv_font_plus"
|
|
||||||
android:layout_toStartOf="@+id/iv_font_add"
|
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
android:textSize="@dimen/sp_14"
|
android:textSize="@dimen/sp_14"
|
||||||
android:textColor="@color/gray6"
|
android:textColor="@color/gray9"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="20"
|
android:text="20"
|
||||||
/>
|
/>
|
||||||
|
</com.remax.visualnovel.widget.uitoken.view.UITokenRelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toEndOf="@+id/left_container"
|
||||||
|
android:layout_marginTop="@dimen/dp_10">
|
||||||
|
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
||||||
|
android:id="@+id/iv_font_plus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginStart="@dimen/dp_10"
|
||||||
|
android:src="@mipmap/setting_font_plus"/>
|
||||||
|
|
||||||
|
|
||||||
|
<com.remax.visualnovel.ui.chat.ui.LevelSeekBar
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/dp_20"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_toEndOf="@id/iv_font_plus"
|
||||||
|
android:layout_toStartOf="@+id/iv_font_add"
|
||||||
|
android:layout_marginHorizontal="@dimen/dp_10"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
<com.remax.visualnovel.widget.uitoken.view.UITokenImageView
|
||||||
android:id="@+id/iv_font_add"
|
android:id="@+id/iv_font_add"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginEnd="@dimen/dp_10"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:src="@mipmap/setting_font_add"/>
|
android:src="@mipmap/setting_font_add"/>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</com.remax.visualnovel.widget.uitoken.view.UITokenRelativeLayout>
|
</com.remax.visualnovel.widget.uitoken.view.UITokenLinearLayout>
|
||||||
|
|
@ -1530,23 +1530,29 @@
|
||||||
<attr name="dividerColor" format="color"/>
|
<attr name="dividerColor" format="color"/>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="LevelSeekBar">
|
<declare-styleable name="CustomLevelSeekBar">
|
||||||
<!-- 档位数量 -->
|
<!-- 档位数量 -->
|
||||||
<attr name="totalLevels" format="integer" />
|
<attr name="totalLevels" format="integer" />
|
||||||
<!-- 当前档位 -->
|
<!-- 当前档位 -->
|
||||||
<attr name="currentLevel" format="integer" />
|
<attr name="currentLevel" format="integer" />
|
||||||
|
|
||||||
<!-- 轨道颜色 -->
|
<!-- 轨道颜色 -->
|
||||||
<attr name="trackColor" format="color" />
|
<attr name="trackColor" format="color" />
|
||||||
<attr name="activeTrackColor" format="color" />
|
<attr name="activeTrackColor" format="color" />
|
||||||
<!-- 拇指颜色 -->
|
|
||||||
|
<!-- 滑块颜色 -->
|
||||||
<attr name="thumbColor" format="color" />
|
<attr name="thumbColor" format="color" />
|
||||||
<!-- 档位标记颜色 -->
|
<attr name="thumbBorderColor" format="color" />
|
||||||
<attr name="levelMarkerColor" format="color" />
|
|
||||||
<attr name="activeLevelMarkerColor" format="color" />
|
<!-- 节点颜色 -->
|
||||||
|
<attr name="nodeColor" format="color" />
|
||||||
|
<attr name="activeNodeColor" format="color" />
|
||||||
|
|
||||||
<!-- 尺寸 -->
|
<!-- 尺寸 -->
|
||||||
<attr name="trackHeight" format="dimension" />
|
<attr name="trackHeight" format="dimension" />
|
||||||
|
<attr name="trackEndRadius" format="dimension" />
|
||||||
<attr name="thumbRadius" format="dimension" />
|
<attr name="thumbRadius" format="dimension" />
|
||||||
<attr name="levelMarkerRadius" format="dimension" />
|
<attr name="nodeRadius" format="dimension" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,8 @@
|
||||||
<color name="grayf6">#fff6f6f6</color>
|
<color name="grayf6">#fff6f6f6</color>
|
||||||
<color name="gray28">#ff282828</color>
|
<color name="gray28">#ff282828</color>
|
||||||
|
|
||||||
|
<color name="red_ff3b30">#ffff3b30</color>
|
||||||
|
|
||||||
<!-- chat settings -->
|
<!-- chat settings -->
|
||||||
<color name="glo_color_chat_setting_item_bg">#F6F6F6</color>
|
<color name="glo_color_chat_setting_item_bg">#F6F6F6</color>
|
||||||
<color name="glo_color_switchview_normal">#FFFFFF</color>
|
<color name="glo_color_switchview_normal">#FFFFFF</color>
|
||||||
|
|
@ -211,6 +213,10 @@
|
||||||
<color name="male_bg">#ffc7dbff</color>
|
<color name="male_bg">#ffc7dbff</color>
|
||||||
<color name="chat_call_voice_text_color">#66eaeeff</color>
|
<color name="chat_call_voice_text_color">#66eaeeff</color>
|
||||||
|
|
||||||
|
<!-- Font seekbar -->
|
||||||
|
<color name="seekbar_color">#ffa4a8b7</color>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue