From 767c1d1a819bdfcc7474a4143d686719b5d9cbee Mon Sep 17 00:00:00 2001
From: HapeLee <1321903405@qq.com>
Date: Sun, 2 Nov 2025 13:19:27 +0800
Subject: [PATCH] =?UTF-8?q?=E9=A1=B5=E7=9C=89=E9=A1=B5=E8=84=9A=20#193?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../legado/app/help/config/ReadTipConfig.kt | 6 +-
.../legado/app/ui/book/read/page/PageView.kt | 41 +++---
.../io/legado/app/ui/widget/BatteryView.kt | 79 +++++++++---
.../legado/app/ui/widget/BatteryViewOrgin.kt | 122 ++++++++++++++++++
app/src/main/res/layout/view_battery.xml | 12 +-
app/src/main/res/values-zh-rHK/arrays.xml | 2 +
app/src/main/res/values-zh-rTW/arrays.xml | 2 +
app/src/main/res/values-zh/arrays.xml | 2 +
app/src/main/res/values/arrays.xml | 2 +
9 files changed, 230 insertions(+), 38 deletions(-)
create mode 100644 app/src/main/java/io/legado/app/ui/widget/BatteryViewOrgin.kt
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%