Show battery percentage in reader bar
This commit is contained in:
@@ -9,6 +9,8 @@ import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.BatteryManager
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
@@ -16,6 +18,7 @@ import androidx.annotation.AttrRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.withScale
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import org.koitharu.kotatsu.R
|
||||
@@ -29,6 +32,7 @@ import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
|
||||
class ReaderInfoBarView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
@@ -38,7 +42,7 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||
private val textBounds = Rect()
|
||||
private val timeFormat = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
|
||||
private val timeReceiver = TimeReceiver()
|
||||
private val systemStateReceiver = SystemStateReceiver()
|
||||
private var insetLeft: Int = 0
|
||||
private var insetRight: Int = 0
|
||||
private var insetTop: Int = 0
|
||||
@@ -52,8 +56,10 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
context.getThemeColor(materialR.attr.colorSurface, Color.WHITE),
|
||||
200,
|
||||
)
|
||||
private val batteryIcon = ContextCompat.getDrawable(context, R.drawable.ic_battery_outline)
|
||||
|
||||
private var timeText = timeFormat.format(LocalTime.now())
|
||||
private var batteryText = ""
|
||||
private var text: String = ""
|
||||
private var prevTextHeight: Int = 0
|
||||
|
||||
@@ -99,7 +105,8 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
computeTextHeight()
|
||||
val ty = innerHeight / 2f + textBounds.height() / 2f - textBounds.bottom
|
||||
val h = innerHeight.toFloat()
|
||||
val ty = h / 2f + textBounds.height() / 2f - textBounds.bottom
|
||||
paint.textAlign = Paint.Align.LEFT
|
||||
canvas.drawTextOutline(
|
||||
text,
|
||||
@@ -108,11 +115,26 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
)
|
||||
if (isTimeVisible) {
|
||||
paint.textAlign = Paint.Align.RIGHT
|
||||
canvas.drawTextOutline(
|
||||
timeText,
|
||||
(width - paddingRight - insetRight - cutoutInsetRight).toFloat(),
|
||||
paddingTop + insetTop + ty,
|
||||
)
|
||||
var endX = (width - paddingRight - insetRight - cutoutInsetRight).toFloat()
|
||||
canvas.drawTextOutline(timeText, endX, paddingTop + insetTop + ty)
|
||||
if (batteryText.isNotEmpty()) {
|
||||
paint.getTextBounds(timeText, 0, timeText.length, textBounds)
|
||||
endX -= textBounds.width()
|
||||
endX -= h * 0.6f
|
||||
canvas.drawTextOutline(batteryText, endX, paddingTop + insetTop + ty)
|
||||
batteryIcon?.let {
|
||||
paint.getTextBounds(batteryText, 0, batteryText.length, textBounds)
|
||||
endX -= textBounds.width()
|
||||
val iconCenter = paddingTop + insetTop + textBounds.height() / 2
|
||||
it.setBounds(
|
||||
(endX - h).toInt(),
|
||||
(iconCenter - h / 2).toInt(),
|
||||
endX.toInt(),
|
||||
(iconCenter + h / 2).toInt(),
|
||||
)
|
||||
it.drawWithOutline(canvas)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,8 +152,11 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
super.onAttachedToWindow()
|
||||
ContextCompat.registerReceiver(
|
||||
context,
|
||||
timeReceiver,
|
||||
IntentFilter(Intent.ACTION_TIME_TICK),
|
||||
systemStateReceiver,
|
||||
IntentFilter().apply {
|
||||
addAction(Intent.ACTION_TIME_TICK)
|
||||
addAction(Intent.ACTION_BATTERY_CHANGED)
|
||||
},
|
||||
ContextCompat.RECEIVER_EXPORTED,
|
||||
)
|
||||
updateCutoutInsets(ViewCompat.getRootWindowInsets(this))
|
||||
@@ -139,7 +164,7 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
context.unregisterReceiver(timeReceiver)
|
||||
context.unregisterReceiver(systemStateReceiver)
|
||||
}
|
||||
|
||||
fun update(state: ReaderUiState?) {
|
||||
@@ -167,7 +192,7 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
private fun computeTextHeight(): Int {
|
||||
val str = text + timeText
|
||||
val str = text + batteryText + timeText
|
||||
paint.getTextBounds(str, 0, str.length, textBounds)
|
||||
return textBounds.height()
|
||||
}
|
||||
@@ -181,6 +206,20 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
drawText(text, x, y, paint)
|
||||
}
|
||||
|
||||
private fun Drawable.drawWithOutline(canvas: Canvas) {
|
||||
var requiredScale = (bounds.width() + paint.strokeWidth * 2f) / bounds.width().toFloat()
|
||||
setTint(colorOutline)
|
||||
canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) {
|
||||
draw(canvas)
|
||||
}
|
||||
requiredScale = 1f / requiredScale
|
||||
canvas.withScale(requiredScale, requiredScale, bounds.exactCenterX(), bounds.exactCenterY()) {
|
||||
draw(canvas)
|
||||
}
|
||||
setTint(colorText)
|
||||
draw(canvas)
|
||||
}
|
||||
|
||||
private fun updateCutoutInsets(insetsCompat: WindowInsetsCompat?) {
|
||||
val cutouts = (insetsCompat ?: return).displayCutout?.boundingRects.orEmpty()
|
||||
cutoutInsetLeft = 0
|
||||
@@ -195,9 +234,15 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private inner class TimeReceiver : BroadcastReceiver() {
|
||||
private inner class SystemStateReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
|
||||
val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
|
||||
if (level != -1 && scale != -1) {
|
||||
batteryText = context.getString(R.string.percent_string_pattern, (level * 100 / scale).toString())
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
timeText = timeFormat.format(LocalTime.now())
|
||||
if (isTimeVisible) {
|
||||
invalidate()
|
||||
|
||||
10
app/src/main/res/drawable/ic_battery_outline.xml
Normal file
10
app/src/main/res/drawable/ic_battery_outline.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M16,20H8V6H16M16.67,4H15V2H9V4H7.33A1.33,1.33 0 0,0 6,5.33V20.67C6,21.4 6.6,22 7.33,22H16.67A1.33,1.33 0 0,0 18,20.67V5.33C18,4.6 17.4,4 16.67,4Z" />
|
||||
</vector>
|
||||
Reference in New Issue
Block a user