diff --git a/app/src/main/java/io/legado/app/help/config/ReadTipConfig.kt b/app/src/main/java/io/legado/app/help/config/ReadTipConfig.kt index 068b99282..2d57d0aba 100644 --- a/app/src/main/java/io/legado/app/help/config/ReadTipConfig.kt +++ b/app/src/main/java/io/legado/app/help/config/ReadTipConfig.kt @@ -22,10 +22,12 @@ object ReadTipConfig { const val chapterTitleArrow = 12 const val batteryInside = 13 const val batteryIcon = 14 + const val batteryClassic = 15 + const val timeBatteryClassic = 16 val tipValues = arrayOf( - none, bookName, chapterTitle, chapterTitleArrow, time, battery, batteryInside, batteryIcon, batteryPercentage, page, - totalProgress, totalProgress1, pageAndTotal, timeBattery, timeBatteryPercentage + none, bookName, chapterTitle, chapterTitleArrow, time, battery, batteryClassic, batteryInside, batteryIcon, batteryPercentage, page, + totalProgress, totalProgress1, pageAndTotal, timeBattery, timeBatteryClassic, timeBatteryPercentage ) val tipNames get() = appCtx.resources.getStringArray(R.array.read_tip).toList() diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt index f4432c6cc..87ab7ae7c 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt @@ -57,6 +57,9 @@ class PageView(context: Context) : FrameLayout(context) { private var tvTitleArrow: BatteryView? = null private var tvBatteryInside: BatteryView? = null private var tvBatteryIcon: BatteryView? = null + private var tvBatteryClassic: BatteryView? = null + private var tvTimeBatteryClassic: BatteryView? = null + private var isMainView = false var isScroll = false @@ -181,86 +184,92 @@ class PageView(context: Context) : FrameLayout(context) { } tvTitle = getTipView(ReadTipConfig.chapterTitle)?.apply { tag = ReadTipConfig.chapterTitle - isBattery = false typeface = ChapterProvider.typeface textSize = 12f + batteryMode = BatteryView.BatteryMode.NO_BATTERY } tvTitleArrow = getTipView(ReadTipConfig.chapterTitleArrow)?.apply { tag = ReadTipConfig.chapterTitleArrow - isBattery = false typeface = ChapterProvider.typeface textSize = 12f batteryMode = BatteryView.BatteryMode.ARROW } tvTime = getTipView(ReadTipConfig.time)?.apply { tag = ReadTipConfig.time - isBattery = false typeface = ChapterProvider.typeface textSize = 12f + batteryMode = BatteryView.BatteryMode.NO_BATTERY } tvBattery = getTipView(ReadTipConfig.battery)?.apply { tag = ReadTipConfig.battery - isBattery = true textSize = 11f batteryMode = BatteryView.BatteryMode.OUTER } + tvBatteryClassic = getTipView(ReadTipConfig.batteryClassic)?.apply { + tag = ReadTipConfig.batteryClassic + textSize = 11f + batteryMode = BatteryView.BatteryMode.CLASSIC + } tvBatteryInside = getTipView(ReadTipConfig.batteryInside)?.apply { tag = ReadTipConfig.batteryInside - isBattery = true textSize = 11f batteryMode = BatteryView.BatteryMode.INNER } tvBatteryIcon = getTipView(ReadTipConfig.batteryIcon)?.apply { tag = ReadTipConfig.batteryIcon - isBattery = true textSize = 11f batteryMode = BatteryView.BatteryMode.ICON } tvPage = getTipView(ReadTipConfig.page)?.apply { tag = ReadTipConfig.page - isBattery = false typeface = ChapterProvider.typeface textSize = 12f + batteryMode = BatteryView.BatteryMode.NO_BATTERY } tvTotalProgress = getTipView(ReadTipConfig.totalProgress)?.apply { tag = ReadTipConfig.totalProgress - isBattery = false + batteryMode = BatteryView.BatteryMode.NO_BATTERY typeface = ChapterProvider.typeface textSize = 12f } tvTotalProgress1 = getTipView(ReadTipConfig.totalProgress1)?.apply { tag = ReadTipConfig.totalProgress1 - isBattery = false + batteryMode = BatteryView.BatteryMode.NO_BATTERY typeface = ChapterProvider.typeface textSize = 12f } tvPageAndTotal = getTipView(ReadTipConfig.pageAndTotal)?.apply { tag = ReadTipConfig.pageAndTotal - isBattery = false + batteryMode = BatteryView.BatteryMode.NO_BATTERY typeface = ChapterProvider.typeface textSize = 12f } tvBookName = getTipView(ReadTipConfig.bookName)?.apply { tag = ReadTipConfig.bookName - isBattery = false + batteryMode = BatteryView.BatteryMode.NO_BATTERY typeface = ChapterProvider.typeface textSize = 12f } tvTimeBattery = getTipView(ReadTipConfig.timeBattery)?.apply { tag = ReadTipConfig.timeBattery - isBattery = true + textSize = 11f + batteryMode = BatteryView.BatteryMode.TIME + } + tvTimeBatteryClassic = getTipView(ReadTipConfig.timeBatteryClassic)?.apply { + tag = ReadTipConfig.timeBatteryClassic typeface = ChapterProvider.typeface textSize = 11f + batteryMode = BatteryView.BatteryMode.CLASSIC } tvBatteryP = getTipView(ReadTipConfig.batteryPercentage)?.apply { tag = ReadTipConfig.batteryPercentage - isBattery = false + batteryMode = BatteryView.BatteryMode.NO_BATTERY typeface = ChapterProvider.typeface textSize = 12f } tvTimeBatteryP = getTipView(ReadTipConfig.timeBatteryPercentage)?.apply { tag = ReadTipConfig.timeBatteryPercentage - isBattery = false + batteryMode = BatteryView.BatteryMode.NO_BATTERY typeface = ChapterProvider.typeface textSize = 12f } @@ -318,6 +327,7 @@ class PageView(context: Context) : FrameLayout(context) { fun upBattery(battery: Int) { this.battery = battery tvBattery?.setBattery(battery) + tvBatteryClassic?.setBattery(battery) tvBatteryInside?.setBattery(battery) tvBatteryIcon?.setBattery(battery) tvBatteryP?.text = "$battery%" @@ -332,7 +342,8 @@ class PageView(context: Context) : FrameLayout(context) { val time = timeFormat.format(Date(System.currentTimeMillis())) tvTimeBattery?.setBattery(battery, time) tvTimeBatteryP?.setBattery(battery, time) - tvTimeBattery?.text = "$time $battery%" + tvTimeBatteryClassic?.setBattery(battery, time) + tvTimeBatteryClassic?.text = "$time $battery%" tvTimeBatteryP?.text = "$time $battery%" } diff --git a/app/src/main/java/io/legado/app/ui/widget/BatteryView.kt b/app/src/main/java/io/legado/app/ui/widget/BatteryView.kt index 9def47610..5e8a8d047 100644 --- a/app/src/main/java/io/legado/app/ui/widget/BatteryView.kt +++ b/app/src/main/java/io/legado/app/ui/widget/BatteryView.kt @@ -19,7 +19,7 @@ class BatteryView @JvmOverloads constructor( private val binding: ViewBatteryBinding = ViewBatteryBinding.inflate(LayoutInflater.from(context), this, true) - enum class BatteryMode { OUTER, INNER, ICON, ARROW } + enum class BatteryMode { OUTER, INNER, ICON, ARROW, TIME, CLASSIC, NO_BATTERY } private val batteryTypeface by lazy { Typeface.createFromAsset(context.assets, "font/number.ttf") @@ -28,22 +28,10 @@ class BatteryView @JvmOverloads constructor( private var battery: Int = 0 init { - setPadding(4.dpToPx(), 3.dpToPx(), 6.dpToPx(), 3.dpToPx()) - binding.batteryText.typeface = batteryTypeface - binding.batteryTextInner.typeface = batteryTypeface + //binding.batteryText.typeface = batteryTypeface + //binding.batteryTextInner.typeface = batteryTypeface } - var isBattery = false - set(value) { - field = value - binding.arrowIcon.visibility = if (value) VISIBLE else GONE - binding.batteryTextInner.visibility = if (value) VISIBLE else GONE - binding.batteryTextInner.typeface = if (value) Typeface.DEFAULT else batteryTypeface - binding.batteryText.typeface = if (value) Typeface.DEFAULT else batteryTypeface - binding.batteryIcon.visibility = if (value) VISIBLE else GONE - binding.batteryFill.visibility = if (value) VISIBLE else GONE - } - var text: CharSequence? get() = binding.batteryText.text set(value) { @@ -77,14 +65,35 @@ class BatteryView @JvmOverloads constructor( fun setBattery(battery: Int, text: String? = null) { this.battery = battery.coerceIn(0, 100) - binding.batteryText.text = text?.let { "$it $battery" } ?: battery.toString() - binding.batteryTextInner.text = text?.let { "$it $battery" } ?: battery.toString() + + when (batteryMode) { + BatteryMode.TIME -> { + val timePart = text ?: "" + val batteryPart = "$battery" + binding.batteryText.text = timePart + binding.batteryTextInner.text = batteryPart + } + + BatteryMode.CLASSIC -> { + binding.batteryClassic.isBattery = true + binding.batteryClassic.setBattery(battery, text) + } + + else -> { + val displayText = text?.let { "$it $battery" } ?: battery.toString() + binding.batteryText.text = displayText + binding.batteryTextInner.text = displayText + } + } + updateFill() } fun setColor(@ColorInt color: Int) { binding.batteryText.setTextColor(color) + binding.batteryTextInner.setTextColor(color) binding.batteryFill.setCardBackgroundColor(color) + binding.batteryClassic.setColor(color) binding.arrowIcon.setColorFilter(color, PorterDuff.Mode.SRC_IN) binding.batteryIcon.setColorFilter(color, PorterDuff.Mode.SRC_IN) binding.batteryIcon.alpha = 0.76f @@ -101,28 +110,58 @@ class BatteryView @JvmOverloads constructor( private fun updateMode() { when (batteryMode) { BatteryMode.OUTER -> { - binding.arrowIcon.visibility = GONE binding.batteryText.visibility = VISIBLE binding.batteryTextInner.visibility = GONE binding.batteryFill.visibility = VISIBLE + binding.batteryIcon.visibility = VISIBLE + binding.arrowIcon.visibility = GONE + binding.batteryClassic.visibility = GONE } BatteryMode.INNER -> { - binding.arrowIcon.visibility = GONE binding.batteryText.visibility = GONE binding.batteryTextInner.visibility = VISIBLE binding.batteryFill.visibility = GONE + binding.batteryIcon.visibility = VISIBLE + binding.arrowIcon.visibility = GONE + binding.batteryClassic.visibility = GONE } BatteryMode.ICON -> { - binding.arrowIcon.visibility = GONE binding.batteryText.visibility = GONE binding.batteryTextInner.visibility = GONE binding.batteryFill.visibility = VISIBLE + binding.batteryIcon.visibility = VISIBLE + binding.arrowIcon.visibility = GONE + binding.batteryClassic.visibility = GONE } BatteryMode.ARROW -> { binding.batteryText.visibility = VISIBLE binding.batteryTextInner.visibility = GONE binding.batteryFill.visibility = GONE + binding.batteryIcon.visibility = GONE binding.arrowIcon.visibility = VISIBLE + binding.batteryClassic.visibility = GONE + } + BatteryMode.TIME -> { + binding.batteryText.visibility = VISIBLE + binding.batteryTextInner.visibility = VISIBLE + binding.batteryFill.visibility = GONE + binding.batteryIcon.visibility = VISIBLE + binding.arrowIcon.visibility = GONE + binding.batteryClassic.visibility = GONE + } + BatteryMode.CLASSIC -> { + binding.batteryText.visibility = GONE + binding.batteryTextInner.visibility = GONE + binding.batteryFill.visibility = GONE + binding.batteryIcon.visibility = GONE + binding.arrowIcon.visibility = GONE + binding.batteryClassic.visibility = VISIBLE + } + BatteryMode.NO_BATTERY -> { + binding.batteryFill.visibility = GONE + binding.batteryIcon.visibility = GONE + binding.arrowIcon.visibility = GONE + binding.batteryClassic.visibility = GONE } } updateFill() diff --git a/app/src/main/java/io/legado/app/ui/widget/BatteryViewOrgin.kt b/app/src/main/java/io/legado/app/ui/widget/BatteryViewOrgin.kt new file mode 100644 index 000000000..86a839733 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/BatteryViewOrgin.kt @@ -0,0 +1,122 @@ +package io.legado.app.ui.widget + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.Typeface +import android.os.Build +import android.text.StaticLayout +import android.util.AttributeSet +import androidx.annotation.ColorInt +import androidx.appcompat.widget.AppCompatTextView +import io.legado.app.help.config.AppConfig +import io.legado.app.utils.canvasrecorder.CanvasRecorderFactory +import io.legado.app.utils.canvasrecorder.recordIfNeededThenDraw +import io.legado.app.utils.dpToPx + +class BatteryViewOrgin @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null +) : AppCompatTextView(context, attrs) { + private val batteryTypeface by lazy { + Typeface.createFromAsset(context.assets, "font/number.ttf") + } + private val batteryPaint = Paint() + private val outFrame = Rect() + private val polar = Rect() + private val canvasRecorder = CanvasRecorderFactory.create() + var isBattery = false + set(value) { + field = value + if (value && !isInEditMode) { + super.setTypeface(batteryTypeface) + postInvalidate() + } + } + private var battery: Int = 0 + + init { + setPadding(4.dpToPx(), 3.dpToPx(), 6.dpToPx(), 3.dpToPx()) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + isFallbackLineSpacing = false + } + batteryPaint.strokeWidth = 1f.dpToPx() + batteryPaint.isAntiAlias = true + batteryPaint.color = paint.color + } + + override fun setTypeface(tf: Typeface?) { + if (!isBattery) { + super.setTypeface(tf) + } + } + + fun setColor(@ColorInt color: Int) { + setTextColor(color) + batteryPaint.color = color + invalidate() + } + + @SuppressLint("SetTextI18n") + fun setBattery(battery: Int, text: String? = null) { + this.battery = battery + if (text.isNullOrEmpty()) { + setText(battery.toString()) + } else { + setText("$text $battery") + } + } + + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + canvasRecorder.invalidate() + } + + override fun onDraw(canvas: Canvas) { + if (AppConfig.optimizeRender) { + canvasRecorder.recordIfNeededThenDraw(canvas, width, height) { + super.onDraw(this) + drawBattery(this) + } + } else { + super.onDraw(canvas) + drawBattery(canvas) + } + } + + private fun drawBattery(canvas: Canvas) { + if (!isBattery) return + layout.getLineBounds(0, outFrame) + val batteryStart = layout + .getPrimaryHorizontal(text.length - battery.toString().length) + .toInt() + 2.dpToPx() + val batteryEnd = batteryStart + + StaticLayout.getDesiredWidth(battery.toString(), paint).toInt() + 4.dpToPx() + outFrame.set( + batteryStart, + 2.dpToPx(), + batteryEnd, + height - 2.dpToPx() + ) + val dj = (outFrame.bottom - outFrame.top) / 3 + polar.set( + batteryEnd, + outFrame.top + dj, + batteryEnd + 2.dpToPx(), + outFrame.bottom - dj + ) + batteryPaint.style = Paint.Style.STROKE + canvas.drawRect(outFrame, batteryPaint) + batteryPaint.style = Paint.Style.FILL + canvas.drawRect(polar, batteryPaint) + } + + @Suppress("UNNECESSARY_SAFE_CALL") + override fun invalidate() { + super.invalidate() + canvasRecorder?.invalidate() + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/view_battery.xml b/app/src/main/res/layout/view_battery.xml index 983cecc44..08dcd99d4 100644 --- a/app/src/main/res/layout/view_battery.xml +++ b/app/src/main/res/layout/view_battery.xml @@ -35,7 +35,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="2.4dp" android:layout_marginBottom="0.8dp" - android:textSize="7sp" + android:textSize="8sp" android:text="@string/text" android:textStyle="bold" app:layout_constraintStart_toStartOf="@id/battery_icon" @@ -68,4 +68,14 @@ app:layout_constraintTop_toTopOf="@id/battery_icon" app:layout_constraintBottom_toBottomOf="@id/battery_icon"/> + + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rHK/arrays.xml b/app/src/main/res/values-zh-rHK/arrays.xml index d26dab26c..9980ec118 100644 --- a/app/src/main/res/values-zh-rHK/arrays.xml +++ b/app/src/main/res/values-zh-rHK/arrays.xml @@ -54,6 +54,7 @@ 標題+箭頭 時間 電量 + 經典電量 電量內顯 僅電量圖標 電量% @@ -62,6 +63,7 @@ 進度(xx/yyy) 頁數同埋進度 時間同埋電量 + 時間同埋電量經典 時間同埋電量% diff --git a/app/src/main/res/values-zh-rTW/arrays.xml b/app/src/main/res/values-zh-rTW/arrays.xml index b35aa7b63..6007cc4f0 100644 --- a/app/src/main/res/values-zh-rTW/arrays.xml +++ b/app/src/main/res/values-zh-rTW/arrays.xml @@ -91,6 +91,7 @@ 標題+箭頭 時間 電量 + 電量经典 電量內顯 僅電量圖標 電量% @@ -99,6 +100,7 @@ 進度(xx/yyy) 頁數及進度 時間及電量 + 時間及電量经典 時間及電量% diff --git a/app/src/main/res/values-zh/arrays.xml b/app/src/main/res/values-zh/arrays.xml index 6a9ce4b47..2ffddb1b3 100644 --- a/app/src/main/res/values-zh/arrays.xml +++ b/app/src/main/res/values-zh/arrays.xml @@ -78,6 +78,7 @@ 带箭头的标题 时间 电量 + 经典电量 电量内显 仅电量图标 电量% @@ -86,6 +87,7 @@ 进度(xx/yyy) 页数及进度 时间及电量 + 经典电量及时间 时间及电量% diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index e8661d7ee..839f29fa4 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -145,6 +145,7 @@ Title With Arrow Time Battery + Battery Classic Battery Inside Battery Only Icon Battery% @@ -153,6 +154,7 @@ Progress(xx/yyy) Pages and progress Time and Battery + Time and Battery Classic Time and Battery%