更多的电池模式与带箭头的标题 #185
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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()
|
||||
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
|
||||
binding.batteryText.typeface = batteryTypeface
|
||||
binding.batteryTextInner.typeface = batteryTypeface
|
||||
}
|
||||
|
||||
override fun setTypeface(tf: Typeface?) {
|
||||
if (!isBattery) {
|
||||
super.setTypeface(tf)
|
||||
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) {
|
||||
binding.batteryText.text = value
|
||||
binding.batteryTextInner.text = value
|
||||
}
|
||||
|
||||
var batteryMode: BatteryMode = BatteryMode.OUTER
|
||||
set(value) {
|
||||
field = value
|
||||
updateMode()
|
||||
}
|
||||
|
||||
var typeface: Typeface?
|
||||
get() = binding.batteryText.typeface
|
||||
set(value) {
|
||||
binding.batteryText.typeface = value ?: Typeface.DEFAULT
|
||||
binding.batteryTextInner.typeface = value ?: Typeface.DEFAULT
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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()
|
||||
updateFill()
|
||||
}
|
||||
|
||||
fun setColor(@ColorInt color: Int) {
|
||||
setTextColor(color)
|
||||
batteryPaint.color = color
|
||||
invalidate()
|
||||
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
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun setBattery(battery: Int, text: String? = null) {
|
||||
this.battery = battery
|
||||
if (text.isNullOrEmpty()) {
|
||||
setText(battery.toString())
|
||||
} else {
|
||||
setText("$text $battery")
|
||||
fun setTextIfNotEqual(newText: String?) {
|
||||
if (binding.batteryText.text?.toString() != newText) {
|
||||
binding.batteryText.text = newText
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
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
|
||||
}
|
||||
} else {
|
||||
super.onDraw(canvas)
|
||||
drawBattery(canvas)
|
||||
}
|
||||
updateFill()
|
||||
}
|
||||
|
||||
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()
|
||||
private fun updateFill() {
|
||||
post {
|
||||
val maxWidth = 14.dpToPx()
|
||||
val params = binding.batteryFill.layoutParams
|
||||
params.width = (maxWidth * battery / 100f).toInt()
|
||||
binding.batteryFill.layoutParams = params
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
VERSION_MAJOR=3
|
||||
VERSION_MINOR=26
|
||||
VERSION_PATCH=2
|
||||
VERSION_SUFFIX=-beta.3
|
||||
VERSION_SUFFIX=-beta.4
|
||||
Reference in New Issue
Block a user