UI improvements and author search support
parent
47a22064a5
commit
151777cf61
@ -1,183 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.core.ui.widgets
|
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Outline
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewOutlineProvider
|
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.annotation.StringRes
|
|
||||||
import androidx.appcompat.widget.LinearLayoutCompat
|
|
||||||
import androidx.core.content.withStyledAttributes
|
|
||||||
import androidx.core.graphics.ColorUtils
|
|
||||||
import androidx.core.view.children
|
|
||||||
import androidx.core.widget.TextViewCompat
|
|
||||||
import org.koitharu.kotatsu.R
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.getAnimationDuration
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.getThemeColorStateList
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.resolveDp
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
|
||||||
import com.google.android.material.R as materialR
|
|
||||||
|
|
||||||
@Deprecated("")
|
|
||||||
class ProgressButton @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0,
|
|
||||||
) : LinearLayoutCompat(context, attrs, defStyleAttr), ValueAnimator.AnimatorUpdateListener {
|
|
||||||
|
|
||||||
private val textViewTitle = TextView(context)
|
|
||||||
private val textViewSubtitle = TextView(context)
|
|
||||||
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
||||||
|
|
||||||
private var progress = 0f
|
|
||||||
private var targetProgress = 0f
|
|
||||||
private var colorBase: ColorStateList = ColorStateList.valueOf(Color.TRANSPARENT)
|
|
||||||
private var colorProgress: ColorStateList = ColorStateList.valueOf(Color.TRANSPARENT)
|
|
||||||
private var progressAnimator: ValueAnimator? = null
|
|
||||||
|
|
||||||
private var colorBaseCurrent = colorProgress.defaultColor
|
|
||||||
private var colorProgressCurrent = colorProgress.defaultColor
|
|
||||||
|
|
||||||
var title: CharSequence?
|
|
||||||
get() = textViewTitle.textAndVisible
|
|
||||||
set(value) {
|
|
||||||
textViewTitle.textAndVisible = value
|
|
||||||
}
|
|
||||||
|
|
||||||
var subtitle: CharSequence?
|
|
||||||
get() = textViewSubtitle.textAndVisible
|
|
||||||
set(value) {
|
|
||||||
textViewSubtitle.textAndVisible = value
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
orientation = VERTICAL
|
|
||||||
outlineProvider = OutlineProvider()
|
|
||||||
clipToOutline = true
|
|
||||||
|
|
||||||
context.withStyledAttributes(attrs, R.styleable.ProgressButton, defStyleAttr) {
|
|
||||||
val textAppearanceFallback = androidx.appcompat.R.style.TextAppearance_AppCompat
|
|
||||||
TextViewCompat.setTextAppearance(
|
|
||||||
textViewTitle,
|
|
||||||
getResourceId(R.styleable.ProgressButton_titleTextAppearance, textAppearanceFallback),
|
|
||||||
)
|
|
||||||
TextViewCompat.setTextAppearance(
|
|
||||||
textViewSubtitle,
|
|
||||||
getResourceId(R.styleable.ProgressButton_subtitleTextAppearance, textAppearanceFallback),
|
|
||||||
)
|
|
||||||
textViewTitle.text = getText(R.styleable.ProgressButton_title)
|
|
||||||
textViewSubtitle.text = getText(R.styleable.ProgressButton_subtitle)
|
|
||||||
colorBase = getColorStateList(R.styleable.ProgressButton_baseColor)
|
|
||||||
?: context.getThemeColorStateList(materialR.attr.colorPrimaryContainer) ?: colorBase
|
|
||||||
colorProgress = getColorStateList(R.styleable.ProgressButton_progressColor)
|
|
||||||
?: context.getThemeColorStateList(materialR.attr.colorPrimary) ?: colorProgress
|
|
||||||
getColorStateList(R.styleable.ProgressButton_android_textColor)?.let { colorText ->
|
|
||||||
textViewTitle.setTextColor(colorText)
|
|
||||||
textViewSubtitle.setTextColor(colorText)
|
|
||||||
}
|
|
||||||
progress = getInt(R.styleable.ProgressButton_android_progress, 0).toFloat() /
|
|
||||||
getInt(R.styleable.ProgressButton_android_max, 100).toFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
addView(textViewTitle, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))
|
|
||||||
addView(
|
|
||||||
textViewSubtitle,
|
|
||||||
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT).also { lp ->
|
|
||||||
lp.topMargin = context.resources.resolveDp(2)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
paint.style = Paint.Style.FILL
|
|
||||||
applyGravity()
|
|
||||||
setWillNotDraw(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
|
||||||
super.onDraw(canvas)
|
|
||||||
canvas.drawColor(colorBaseCurrent)
|
|
||||||
if (progress > 0f) {
|
|
||||||
canvas.drawRect(0f, 0f, width * progress, height.toFloat(), paint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawableStateChanged() {
|
|
||||||
super.drawableStateChanged()
|
|
||||||
val state = drawableState
|
|
||||||
colorBaseCurrent = colorBase.getColorForState(state, colorBase.defaultColor)
|
|
||||||
colorProgressCurrent = colorProgress.getColorForState(state, colorProgress.defaultColor)
|
|
||||||
colorProgressCurrent = ColorUtils.setAlphaComponent(colorProgressCurrent, 84 /* 255 * 0.33F */)
|
|
||||||
paint.color = colorProgressCurrent
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setGravity(gravity: Int) {
|
|
||||||
super.setGravity(gravity)
|
|
||||||
if (childCount != 0) {
|
|
||||||
applyGravity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setEnabled(enabled: Boolean) {
|
|
||||||
super.setEnabled(enabled)
|
|
||||||
children.forEach { it.isEnabled = enabled }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAnimationUpdate(animation: ValueAnimator) {
|
|
||||||
if (animation === progressAnimator) {
|
|
||||||
progress = animation.animatedValue as Float
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTitle(@StringRes titleResId: Int) {
|
|
||||||
textViewTitle.setTextAndVisible(titleResId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSubtitle(@StringRes titleResId: Int) {
|
|
||||||
textViewSubtitle.setTextAndVisible(titleResId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setProgress(value: Float, animate: Boolean) {
|
|
||||||
val prevAnimator = progressAnimator
|
|
||||||
if (animate && context.isAnimationsEnabled) {
|
|
||||||
if (value == targetProgress) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
targetProgress = value
|
|
||||||
progressAnimator = ValueAnimator.ofFloat(progress, value).apply {
|
|
||||||
duration = context.getAnimationDuration(android.R.integer.config_mediumAnimTime)
|
|
||||||
interpolator = AccelerateDecelerateInterpolator()
|
|
||||||
addUpdateListener(this@ProgressButton)
|
|
||||||
}
|
|
||||||
progressAnimator?.start()
|
|
||||||
} else {
|
|
||||||
progressAnimator = null
|
|
||||||
progress = value
|
|
||||||
targetProgress = value
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
prevAnimator?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun applyGravity() {
|
|
||||||
val value = (gravity and Gravity.HORIZONTAL_GRAVITY_MASK) or Gravity.CENTER_VERTICAL
|
|
||||||
textViewTitle.gravity = value
|
|
||||||
textViewSubtitle.gravity = value
|
|
||||||
}
|
|
||||||
|
|
||||||
private class OutlineProvider : ViewOutlineProvider() {
|
|
||||||
|
|
||||||
override fun getOutline(view: View, outline: Outline) {
|
|
||||||
outline.setRoundRect(0, 0, view.width, view.height, view.height / 2f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package org.koitharu.kotatsu.list.ui.adapter
|
||||||
|
|
||||||
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
|
import org.koitharu.kotatsu.databinding.ItemButtonFooterBinding
|
||||||
|
import org.koitharu.kotatsu.list.ui.model.ButtonFooter
|
||||||
|
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||||
|
|
||||||
|
fun buttonFooterAD(
|
||||||
|
listener: ListStateHolderListener,
|
||||||
|
) = adapterDelegateViewBinding<ButtonFooter, ListModel, ItemButtonFooterBinding>(
|
||||||
|
{ inflater, parent -> ItemButtonFooterBinding.inflate(inflater, parent, false) },
|
||||||
|
) {
|
||||||
|
|
||||||
|
binding.button.setOnClickListener {
|
||||||
|
listener.onFooterButtonClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
bind {
|
||||||
|
binding.button.setText(item.textResId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package org.koitharu.kotatsu.list.ui.model
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
|
||||||
|
data class ButtonFooter(
|
||||||
|
@StringRes val textResId: Int,
|
||||||
|
) : ListModel {
|
||||||
|
|
||||||
|
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||||
|
return other is ButtonFooter && textResId == other.textResId
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,139 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:background="@color/grey" />
|
||||||
|
|
||||||
|
<org.koitharu.kotatsu.core.ui.widgets.ZoomControl
|
||||||
|
android:id="@+id/zoomControl"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:spacing="2dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_dodgeInsetEdges="bottom"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<org.koitharu.kotatsu.reader.ui.ReaderInfoBarView
|
||||||
|
android:id="@+id/infoBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="top"
|
||||||
|
android:padding="6dp"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appbar_top"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="@dimen/m3_card_elevated_elevation"
|
||||||
|
app:elevation="@dimen/m3_card_elevated_elevation"
|
||||||
|
app:liftOnScroll="false">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="@dimen/m3_card_elevated_elevation"
|
||||||
|
app:elevation="@dimen/m3_card_elevated_elevation"
|
||||||
|
app:popupTheme="@style/ThemeOverlay.Kotatsu"
|
||||||
|
tools:menu="@menu/opt_reader_top">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_slider"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:layout_marginEnd="2dp"
|
||||||
|
android:gravity="center_vertical|end">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/button_prev"
|
||||||
|
style="?actionButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@string/prev_chapter"
|
||||||
|
android:src="@drawable/ic_prev"
|
||||||
|
android:tooltipText="@string/prev_chapter" />
|
||||||
|
|
||||||
|
<com.google.android.material.slider.Slider
|
||||||
|
android:id="@+id/slider"
|
||||||
|
android:layout_width="260dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:stepSize="1.0"
|
||||||
|
android:valueFrom="0"
|
||||||
|
app:labelBehavior="floating"
|
||||||
|
tools:value="6"
|
||||||
|
tools:valueTo="20" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/button_next"
|
||||||
|
style="?actionButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@string/next_chapter"
|
||||||
|
android:src="@drawable/ic_next"
|
||||||
|
android:tooltipText="@string/next_chapter" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<org.koitharu.kotatsu.reader.ui.ReaderToastView
|
||||||
|
android:id="@+id/toastView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|center_horizontal"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:background="@drawable/bg_reader_indicator"
|
||||||
|
android:drawablePadding="6dp"
|
||||||
|
android:elevation="1000dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||||
|
android:theme="@style/ThemeOverlay.Material3.Dark"
|
||||||
|
app:layout_dodgeInsetEdges="bottom"
|
||||||
|
tools:text="@string/loading_" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_loading"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/bg_card"
|
||||||
|
android:backgroundTint="?colorSurfaceContainer"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:outlineProvider="background"
|
||||||
|
android:padding="@dimen/screen_padding">
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView_loading"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:text="@string/loading_"
|
||||||
|
android:textAppearance="?attr/textAppearanceTitleMedium" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="4dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button"
|
||||||
|
style="?materialButtonOutlinedStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="@string/globally" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
Loading…
Reference in New Issue