Update material components
parent
98f723200b
commit
4098f06995
@ -0,0 +1,42 @@
|
|||||||
|
package org.koitharu.kotatsu.base.ui.widgets
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
|
import androidx.annotation.IdRes
|
||||||
|
import androidx.core.view.children
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
|
||||||
|
class CheckableButtonGroup @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
@AttrRes defStyleAttr: Int = 0,
|
||||||
|
) : LinearLayout(context, attrs, defStyleAttr), View.OnClickListener {
|
||||||
|
|
||||||
|
var onCheckedChangeListener: OnCheckedChangeListener? = null
|
||||||
|
|
||||||
|
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
|
||||||
|
if (child is MaterialButton) {
|
||||||
|
child.setOnClickListener(this)
|
||||||
|
}
|
||||||
|
super.addView(child, index, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
setCheckedId(v.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCheckedId(@IdRes viewRes: Int) {
|
||||||
|
children.forEach {
|
||||||
|
(it as? MaterialButton)?.isChecked = it.id == viewRes
|
||||||
|
}
|
||||||
|
onCheckedChangeListener?.onCheckedChanged(this, viewRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface OnCheckedChangeListener {
|
||||||
|
fun onCheckedChanged(group: CheckableButtonGroup, checkedId: Int)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,155 @@
|
|||||||
|
package org.koitharu.kotatsu.settings.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.TypedArray
|
||||||
|
import android.os.Parcel
|
||||||
|
import android.os.Parcelable
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.content.withStyledAttributes
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceViewHolder
|
||||||
|
import com.google.android.material.slider.Slider
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.utils.ext.setValueRounded
|
||||||
|
|
||||||
|
class SliderPreference @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = R.attr.sliderPreferenceStyle,
|
||||||
|
defStyleRes: Int = R.style.Preference_Slider,
|
||||||
|
) : Preference(context, attrs, defStyleAttr, defStyleRes) {
|
||||||
|
|
||||||
|
private var valueFrom: Int = 0
|
||||||
|
private var valueTo: Int = 100
|
||||||
|
private var stepSize: Int = 1
|
||||||
|
private var currentValue: Int = 0
|
||||||
|
|
||||||
|
var value: Int
|
||||||
|
get() = currentValue
|
||||||
|
set(value) = setValueInternal(value, notifyChanged = true)
|
||||||
|
|
||||||
|
private val sliderListener = Slider.OnChangeListener { _, value, fromUser ->
|
||||||
|
if (fromUser) {
|
||||||
|
syncValueInternal(value.toInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
context.withStyledAttributes(attrs,
|
||||||
|
R.styleable.SliderPreference,
|
||||||
|
defStyleAttr,
|
||||||
|
defStyleRes) {
|
||||||
|
valueFrom = getFloat(R.styleable.SliderPreference_android_valueFrom,
|
||||||
|
valueFrom.toFloat()).toInt()
|
||||||
|
valueTo =
|
||||||
|
getFloat(R.styleable.SliderPreference_android_valueTo, valueTo.toFloat()).toInt()
|
||||||
|
stepSize =
|
||||||
|
getFloat(R.styleable.SliderPreference_android_stepSize, stepSize.toFloat()).toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||||
|
super.onBindViewHolder(holder)
|
||||||
|
val slider = holder.findViewById(R.id.slider) as? Slider ?: return
|
||||||
|
slider.removeOnChangeListener(sliderListener)
|
||||||
|
slider.addOnChangeListener(sliderListener)
|
||||||
|
slider.valueFrom = valueFrom.toFloat()
|
||||||
|
slider.valueTo = valueTo.toFloat()
|
||||||
|
slider.stepSize = stepSize.toFloat()
|
||||||
|
slider.setValueRounded(currentValue.toFloat())
|
||||||
|
slider.isEnabled = isEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSetInitialValue(defaultValue: Any?) {
|
||||||
|
value = getPersistedInt(defaultValue as? Int ?: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onGetDefaultValue(a: TypedArray, index: Int): Any {
|
||||||
|
return a.getInt(index, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(): Parcelable? {
|
||||||
|
val superState = super.onSaveInstanceState()
|
||||||
|
if (superState == null || isPersistent) {
|
||||||
|
return superState
|
||||||
|
}
|
||||||
|
return SavedState(
|
||||||
|
superState = superState,
|
||||||
|
valueFrom = valueFrom,
|
||||||
|
valueTo = valueTo,
|
||||||
|
currentValue = currentValue,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRestoreInstanceState(state: Parcelable?) {
|
||||||
|
if (state !is SavedState) {
|
||||||
|
super.onRestoreInstanceState(state)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
super.onRestoreInstanceState(state.superState)
|
||||||
|
valueFrom = state.valueFrom
|
||||||
|
valueTo = state.valueTo
|
||||||
|
currentValue = state.currentValue
|
||||||
|
notifyChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setValueInternal(sliderValue: Int, notifyChanged: Boolean) {
|
||||||
|
val newValue = sliderValue.coerceIn(valueFrom, valueTo)
|
||||||
|
if (newValue != currentValue) {
|
||||||
|
currentValue = newValue
|
||||||
|
persistInt(newValue)
|
||||||
|
if (notifyChanged) {
|
||||||
|
notifyChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun syncValueInternal(sliderValue: Int) {
|
||||||
|
if (sliderValue != currentValue) {
|
||||||
|
if (callChangeListener(sliderValue)) {
|
||||||
|
setValueInternal(sliderValue, notifyChanged = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SavedState : View.BaseSavedState {
|
||||||
|
|
||||||
|
val valueFrom: Int
|
||||||
|
val valueTo: Int
|
||||||
|
val currentValue: Int
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
superState: Parcelable,
|
||||||
|
valueFrom: Int,
|
||||||
|
valueTo: Int,
|
||||||
|
currentValue: Int,
|
||||||
|
) : super(superState) {
|
||||||
|
this.valueFrom = valueFrom
|
||||||
|
this.valueTo = valueTo
|
||||||
|
this.currentValue = currentValue
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: Parcel) : super(source) {
|
||||||
|
valueFrom = source.readInt()
|
||||||
|
valueTo = source.readInt()
|
||||||
|
currentValue = source.readInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeToParcel(out: Parcel, flags: Int) {
|
||||||
|
super.writeToParcel(out, flags)
|
||||||
|
out.writeInt(valueFrom)
|
||||||
|
out.writeInt(valueTo)
|
||||||
|
out.writeInt(currentValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmField
|
||||||
|
val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> {
|
||||||
|
override fun createFromParcel(`in`: Parcel) = SavedState(`in`)
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<SavedState?> = arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package org.koitharu.kotatsu.utils.progress
|
||||||
|
|
||||||
|
import com.google.android.material.slider.LabelFormatter
|
||||||
|
|
||||||
|
class IntPercentLabelFormatter : LabelFormatter {
|
||||||
|
override fun getFormattedValue(value: Float) = "%d%%".format(value.toInt())
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
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="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||||
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
tools:ignore="PrivateResource">
|
||||||
|
|
||||||
|
<include layout="@layout/image_frame" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_toStartOf="@android:id/summary"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:labelFor="@id/seekbar"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||||
|
tools:ignore="LabelFor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/summary"
|
||||||
|
style="@style/PreferenceSummaryTextStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textColor="?android:attr/textColorSecondary" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.slider.Slider
|
||||||
|
android:id="@+id/slider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
app:labelBehavior="gone"
|
||||||
|
app:tickVisible="false" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
Loading…
Reference in New Issue