Просмотр исходного кода

更多的电池模式与带箭头的标题 #185

HapeLee 1 год назад
Родитель
Сommit
45b454c4c1

+ 4 - 1
app/src/main/java/io/legado/app/help/config/ReadTipConfig.kt

@@ -19,9 +19,12 @@ object ReadTipConfig {
     const val timeBattery = 8
     const val timeBatteryPercentage = 9
     const val totalProgress1 = 11
+    const val chapterTitleArrow = 12
+    const val batteryInside = 13
+    const val batteryIcon = 14
 
     val tipValues = arrayOf(
-        none, bookName, chapterTitle, time, battery, batteryPercentage, page,
+        none, bookName, chapterTitle, chapterTitleArrow, time, battery, batteryInside, batteryIcon, batteryPercentage, page,
         totalProgress, totalProgress1, pageAndTotal, timeBattery, timeBatteryPercentage
     )
     val tipNames get() = appCtx.resources.getStringArray(R.array.read_tip).toList()

+ 28 - 1
app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt

@@ -31,7 +31,6 @@ import io.legado.app.utils.applyStatusBarPadding
 import io.legado.app.utils.dpToPx
 import io.legado.app.utils.gone
 import io.legado.app.utils.setOnApplyWindowInsetsListenerCompat
-import io.legado.app.utils.setTextIfNotEqual
 import io.legado.app.utils.statusBarHeight
 import splitties.views.backgroundColor
 import java.util.Date
@@ -55,6 +54,9 @@ class PageView(context: Context) : FrameLayout(context) {
     private var tvBookName: BatteryView? = null
     private var tvTimeBattery: BatteryView? = null
     private var tvTimeBatteryP: BatteryView? = null
+    private var tvTitleArrow: BatteryView? = null
+    private var tvBatteryInside: BatteryView? = null
+    private var tvBatteryIcon: BatteryView? = null
     private var isMainView = false
     var isScroll = false
 
@@ -183,6 +185,13 @@ class PageView(context: Context) : FrameLayout(context) {
             typeface = ChapterProvider.typeface
             textSize = 12f
         }
+        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
@@ -193,6 +202,19 @@ class PageView(context: Context) : FrameLayout(context) {
             tag = ReadTipConfig.battery
             isBattery = true
             textSize = 11f
+            batteryMode = BatteryView.BatteryMode.OUTER
+        }
+        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
@@ -296,6 +318,8 @@ class PageView(context: Context) : FrameLayout(context) {
     fun upBattery(battery: Int) {
         this.battery = battery
         tvBattery?.setBattery(battery)
+        tvBatteryInside?.setBattery(battery)
+        tvBatteryIcon?.setBattery(battery)
         tvBatteryP?.text = "$battery%"
         upTimeBattery()
     }
@@ -307,6 +331,8 @@ class PageView(context: Context) : FrameLayout(context) {
     private fun upTimeBattery() {
         val time = timeFormat.format(Date(System.currentTimeMillis()))
         tvTimeBattery?.setBattery(battery, time)
+        tvTimeBatteryP?.setBattery(battery, time)
+        tvTimeBattery?.text = "$time $battery%"
         tvTimeBatteryP?.text = "$time $battery%"
     }
 
@@ -352,6 +378,7 @@ class PageView(context: Context) : FrameLayout(context) {
     fun setProgress(textPage: TextPage) = textPage.apply {
         tvBookName?.setTextIfNotEqual(ReadBook.book?.name)
         tvTitle?.setTextIfNotEqual(textPage.title)
+        tvTitleArrow?.setTextIfNotEqual(textPage.title)
         val readProgress = readProgress
         tvTotalProgress?.setTextIfNotEqual(readProgress)
         tvTotalProgress1?.setTextIfNotEqual("${chapterIndex.plus(1)}/${chapterSize}")

+ 102 - 84
app/src/main/java/io/legado/app/ui/widget/BatteryView.kt

@@ -1,122 +1,140 @@
 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.PorterDuff
 import android.graphics.Typeface
-import android.os.Build
-import android.text.StaticLayout
 import android.util.AttributeSet
+import android.util.TypedValue
+import android.view.LayoutInflater
 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 androidx.constraintlayout.widget.ConstraintLayout
+import io.legado.app.databinding.ViewBatteryBinding
 import io.legado.app.utils.dpToPx
 
 class BatteryView @JvmOverloads constructor(
     context: Context,
     attrs: AttributeSet? = null
-) : AppCompatTextView(context, attrs) {
+) : ConstraintLayout(context, attrs) {
+
+    private val binding: ViewBatteryBinding =
+        ViewBatteryBinding.inflate(LayoutInflater.from(context), this, true)
+
+    enum class BatteryMode { OUTER, INNER, ICON, ARROW }
+
     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()
+
+    private var battery: Int = 0
+
+    init {
+        setPadding(4.dpToPx(), 3.dpToPx(), 6.dpToPx(), 3.dpToPx())
+        binding.batteryText.typeface = batteryTypeface
+        binding.batteryTextInner.typeface = batteryTypeface
+    }
+
     var isBattery = false
         set(value) {
             field = value
-            if (value && !isInEditMode) {
-                super.setTypeface(batteryTypeface)
-                postInvalidate()
-            }
+            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
         }
-    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
+    var text: CharSequence?
+        get() = binding.batteryText.text
+        set(value) {
+            binding.batteryText.text = value
+            binding.batteryTextInner.text = value
+        }
+
+    var batteryMode: BatteryMode = BatteryMode.OUTER
+        set(value) {
+            field = value
+            updateMode()
         }
-        batteryPaint.strokeWidth = 1f.dpToPx()
-        batteryPaint.isAntiAlias = true
-        batteryPaint.color = paint.color
-    }
 
-    override fun setTypeface(tf: Typeface?) {
-        if (!isBattery) {
-            super.setTypeface(tf)
+    var typeface: Typeface?
+        get() = binding.batteryText.typeface
+        set(value) {
+            binding.batteryText.typeface = value ?: Typeface.DEFAULT
+            binding.batteryTextInner.typeface = value ?: Typeface.DEFAULT
         }
-    }
 
-    fun setColor(@ColorInt color: Int) {
-        setTextColor(color)
-        batteryPaint.color = color
-        invalidate()
+    var textSize: Float
+        get() = binding.batteryText.textSize / binding.batteryText.resources.displayMetrics.density
+        set(value) {
+            binding.batteryText.setTextSize(TypedValue.COMPLEX_UNIT_SP, value)
+        }
+
+    fun setTextColor(@ColorInt color: Int) {
+        binding.batteryText.setTextColor(color)
+        binding.batteryTextInner.setTextColor(color)
     }
 
-    @SuppressLint("SetTextI18n")
     fun setBattery(battery: Int, text: String? = null) {
-        this.battery = battery
-        if (text.isNullOrEmpty()) {
-            setText(battery.toString())
-        } else {
-            setText("$text  $battery")
-        }
+        this.battery = battery.coerceIn(0, 100)
+        binding.batteryText.text = text?.let { "$it  $battery" } ?: battery.toString()
+        binding.batteryTextInner.text = text?.let { "$it  $battery" } ?: battery.toString()
+        updateFill()
     }
 
-    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
-        super.onLayout(changed, left, top, right, bottom)
-        canvasRecorder.invalidate()
+    fun setColor(@ColorInt color: Int) {
+        binding.batteryText.setTextColor(color)
+        binding.batteryFill.setCardBackgroundColor(color)
+        binding.arrowIcon.setColorFilter(color, PorterDuff.Mode.SRC_IN)
+        binding.batteryIcon.setColorFilter(color, PorterDuff.Mode.SRC_IN)
+        binding.batteryIcon.alpha = 0.76f
+        binding.arrowIcon.alpha = 0.76f
     }
 
-    override fun onDraw(canvas: Canvas) {
-        if (AppConfig.optimizeRender) {
-            canvasRecorder.recordIfNeededThenDraw(canvas, width, height) {
-                super.onDraw(this)
-                drawBattery(this)
-            }
-        } else {
-            super.onDraw(canvas)
-            drawBattery(canvas)
+    fun setTextIfNotEqual(newText: String?) {
+        if (binding.batteryText.text?.toString() != newText) {
+            binding.batteryText.text = newText
         }
     }
 
-    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)
+
+    private fun updateMode() {
+        when (batteryMode) {
+            BatteryMode.OUTER -> {
+                binding.arrowIcon.visibility = GONE
+                binding.batteryText.visibility = VISIBLE
+                binding.batteryTextInner.visibility = GONE
+                binding.batteryFill.visibility = VISIBLE
+            }
+            BatteryMode.INNER -> {
+                binding.arrowIcon.visibility = GONE
+                binding.batteryText.visibility = GONE
+                binding.batteryTextInner.visibility = VISIBLE
+                binding.batteryFill.visibility = GONE
+            }
+            BatteryMode.ICON -> {
+                binding.arrowIcon.visibility = GONE
+                binding.batteryText.visibility = GONE
+                binding.batteryTextInner.visibility = GONE
+                binding.batteryFill.visibility = VISIBLE
+            }
+            BatteryMode.ARROW -> {
+                binding.batteryText.visibility = VISIBLE
+                binding.batteryTextInner.visibility = GONE
+                binding.batteryFill.visibility = GONE
+                binding.arrowIcon.visibility = VISIBLE
+            }
+        }
+        updateFill()
     }
 
-    @Suppress("UNNECESSARY_SAFE_CALL")
-    override fun invalidate() {
-        super.invalidate()
-        canvasRecorder?.invalidate()
+    private fun updateFill() {
+        post {
+            val maxWidth = 14.dpToPx()
+            val params = binding.batteryFill.layoutParams
+            params.width = (maxWidth * battery / 100f).toInt()
+            binding.batteryFill.layoutParams = params
+        }
     }
 
 }

+ 12 - 0
app/src/main/res/drawable/ic_battery.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M175.38,680Q135.64,680 107.82,652.18Q80,624.36 80,584.62L80,375.38Q80,335.64 107.82,307.82Q135.64,280 175.38,280L700,280Q739.74,280 767.56,307.82Q795.38,335.64 795.38,375.38L795.38,584.62Q795.38,624.36 767.56,652.18Q739.74,680 700,680L175.38,680ZM175.38,640L700,640Q723.54,640 739.46,624.08Q755.38,608.15 755.38,584.62L755.38,375.38Q755.38,351.85 739.46,335.92Q723.54,320 700,320L175.38,320Q151.85,320 135.92,335.92Q120,351.85 120,375.38L120,584.62Q120,608.15 135.92,624.08Q151.85,640 175.38,640ZM835.38,564.62L835.38,396.15L847.69,396.15Q861.42,396.15 870.71,405.44Q880,414.73 880,428.46L880,532.31Q880,546.04 870.71,555.33Q861.42,564.62 847.69,564.62L835.38,564.62ZM120,640Q120,640 120,624.08Q120,608.15 120,584.62L120,375.38Q120,351.85 120,335.92Q120,320 120,320L120,320Q120,320 120,335.92Q120,351.85 120,375.38L120,584.62Q120,608.15 120,624.08Q120,640 120,640Z"/>
+</vector>
+

+ 71 - 0
app/src/main/res/layout/view_battery.xml

@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <ImageView
+        android:id="@+id/arrow_icon"
+        android:layout_width="24dp"
+        android:layout_height="12dp"
+        android:scaleType="centerCrop"
+        android:visibility="gone"
+        android:src="@drawable/ic_arrow_right"
+        android:rotation="180"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <TextView
+        android:id="@+id/battery_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:includeFontPadding="false"
+        android:textSize="11sp"
+        android:text="@string/text"
+        android:textStyle="bold"
+        app:layout_constraintStart_toEndOf="@id/arrow_icon"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <TextView
+        android:id="@+id/battery_text_inner"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="2.4dp"
+        android:layout_marginBottom="0.8dp"
+        android:textSize="7sp"
+        android:text="@string/text"
+        android:textStyle="bold"
+        app:layout_constraintStart_toStartOf="@id/battery_icon"
+        app:layout_constraintEnd_toEndOf="@id/battery_icon"
+        app:layout_constraintTop_toTopOf="@id/battery_icon"
+        app:layout_constraintBottom_toBottomOf="@id/battery_icon"
+        tools:ignore="SmallSp" />
+
+    <ImageView
+        android:id="@+id/battery_icon"
+        android:layout_width="28dp"
+        android:layout_height="12dp"
+        android:layout_marginStart="4dp"
+        android:scaleType="centerCrop"
+        android:src="@drawable/ic_battery"
+        app:layout_constraintStart_toEndOf="@id/battery_text"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <com.google.android.material.card.MaterialCardView
+        android:id="@+id/battery_fill"
+        android:layout_width="14dp"
+        android:layout_height="8dp"
+        android:visibility="gone"
+        android:layout_marginStart="4.2dp"
+        app:strokeWidth="0dp"
+        app:cardCornerRadius="1dp"
+        app:cardBackgroundColor="?attr/colorControlNormal"
+        app:layout_constraintStart_toStartOf="@id/battery_icon"
+        app:layout_constraintTop_toTopOf="@id/battery_icon"
+        app:layout_constraintBottom_toBottomOf="@id/battery_icon"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 3 - 0
app/src/main/res/values-zh-rHK/arrays.xml

@@ -51,8 +51,11 @@
         <item>無</item>
         <item>書名</item>
         <item>標題</item>
+        <item>標題+箭頭</item>
         <item>時間</item>
         <item>電量</item>
+        <item>電量內顯</item>
+        <item>僅電量圖標</item>
         <item>電量%</item>
         <item>頁數</item>
         <item>進度(%)</item>

+ 3 - 0
app/src/main/res/values-zh-rTW/arrays.xml

@@ -88,8 +88,11 @@
         <item>無</item>
         <item>書名</item>
         <item>標題</item>
+        <item>標題+箭頭</item>
         <item>時間</item>
         <item>電量</item>
+        <item>電量內顯</item>
+        <item>僅電量圖標</item>
         <item>電量%</item>
         <item>頁數</item>
         <item>進度(%)</item>

+ 3 - 0
app/src/main/res/values-zh/arrays.xml

@@ -75,8 +75,11 @@
         <item>无</item>
         <item>书名</item>
         <item>标题</item>
+        <item>带箭头的标题</item>
         <item>时间</item>
         <item>电量</item>
+        <item>电量内显</item>
+        <item>仅电量图标</item>
         <item>电量%</item>
         <item>页数</item>
         <item>进度(%)</item>

+ 3 - 0
app/src/main/res/values/arrays.xml

@@ -142,8 +142,11 @@
 		<item>Blank</item>
 		<item>Book name</item>
 		<item>Title</item>
+		<item>Title With Arrow</item>
 		<item>Time</item>
 		<item>Battery</item>
+		<item>Battery Inside</item>
+		<item>Battery Only Icon</item>
 		<item>Battery%</item>
 		<item>Pages</item>
 		<item>Progress(%)</item>

+ 1 - 1
app/version.properties

@@ -1,4 +1,4 @@
 VERSION_MAJOR=3
 VERSION_MINOR=26
 VERSION_PATCH=2
-VERSION_SUFFIX=-beta.3
+VERSION_SUFFIX=-beta.4