Update reader mode selection ui

This commit is contained in:
Koitharu
2022-07-30 14:00:08 +03:00
parent c313184666
commit 0d8e4dee35
5 changed files with 144 additions and 14 deletions

View File

@@ -8,23 +8,34 @@ import android.widget.LinearLayout
import androidx.annotation.AttrRes
import androidx.annotation.IdRes
import androidx.core.view.children
import com.google.android.material.R as materialR
import com.google.android.material.button.MaterialButton
import com.google.android.material.shape.ShapeAppearanceModel
@Deprecated("")
class CheckableButtonGroup @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0,
) : LinearLayout(context, attrs, defStyleAttr), View.OnClickListener {
@AttrRes defStyleAttr: Int = materialR.attr.materialButtonToggleGroupStyle,
) : LinearLayout(context, attrs, defStyleAttr, materialR.style.Widget_MaterialComponents_MaterialButtonToggleGroup),
View.OnClickListener {
private val originalCornerData = ArrayList<CornerData>()
var onCheckedChangeListener: OnCheckedChangeListener? = null
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
if (child is MaterialButton) {
child.setOnClickListener(this)
setupButton(child)
}
super.addView(child, index, params)
}
override fun onFinishInflate() {
super.onFinishInflate()
updateChildShapes()
}
override fun onClick(v: View) {
setCheckedId(v.id)
}
@@ -36,7 +47,74 @@ class CheckableButtonGroup @JvmOverloads constructor(
onCheckedChangeListener?.onCheckedChanged(this, viewRes)
}
private fun updateChildShapes() {
val childCount = childCount
val firstVisibleChildIndex = 0
val lastVisibleChildIndex = childCount - 1
for (i in 0 until childCount) {
val button: MaterialButton = getChildAt(i) as? MaterialButton ?: continue
if (button.visibility == GONE) {
continue
}
val builder = button.shapeAppearanceModel.toBuilder()
val newCornerData: CornerData? =
getNewCornerData(i, firstVisibleChildIndex, lastVisibleChildIndex)
updateBuilderWithCornerData(builder, newCornerData)
button.shapeAppearanceModel = builder.build()
}
}
private fun setupButton(button: MaterialButton) {
button.setOnClickListener(this)
button.isElegantTextHeight = false
// Saves original corner data
val shapeAppearanceModel: ShapeAppearanceModel = button.shapeAppearanceModel
originalCornerData.add(
CornerData(
shapeAppearanceModel.topLeftCornerSize,
shapeAppearanceModel.bottomLeftCornerSize,
shapeAppearanceModel.topRightCornerSize,
shapeAppearanceModel.bottomRightCornerSize,
),
)
}
private fun getNewCornerData(
index: Int,
firstVisibleChildIndex: Int,
lastVisibleChildIndex: Int,
): CornerData? {
val cornerData: CornerData = originalCornerData.get(index)
// If only one (visible) child exists, use its original corners
if (firstVisibleChildIndex == lastVisibleChildIndex) {
return cornerData
}
val isHorizontal = orientation == HORIZONTAL
if (index == firstVisibleChildIndex) {
return if (isHorizontal) cornerData.start(this) else cornerData.top()
}
return if (index == lastVisibleChildIndex) {
if (isHorizontal) cornerData.end(this) else cornerData.bottom()
} else null
}
private fun updateBuilderWithCornerData(
shapeAppearanceModelBuilder: ShapeAppearanceModel.Builder,
cornerData: CornerData?,
) {
if (cornerData == null) {
shapeAppearanceModelBuilder.setAllCornerSizes(0f)
return
}
shapeAppearanceModelBuilder
.setTopLeftCornerSize(cornerData.topLeft)
.setBottomLeftCornerSize(cornerData.bottomLeft)
.setTopRightCornerSize(cornerData.topRight)
.setBottomRightCornerSize(cornerData.bottomRight)
}
fun interface OnCheckedChangeListener {
fun onCheckedChanged(group: CheckableButtonGroup, checkedId: Int)
}
}
}

View File

@@ -0,0 +1,47 @@
package org.koitharu.kotatsu.base.ui.widgets
import android.view.View
import androidx.core.view.ViewCompat
import com.google.android.material.shape.AbsoluteCornerSize
import com.google.android.material.shape.CornerSize
class CornerData(
var topLeft: CornerSize,
var bottomLeft: CornerSize,
var topRight: CornerSize,
var bottomRight: CornerSize,
) {
fun start(view: View): CornerData {
return if (isLayoutRtl(view)) right() else left()
}
fun end(view: View): CornerData {
return if (isLayoutRtl(view)) left() else right()
}
fun left(): CornerData {
return CornerData(topLeft, bottomLeft, noCorner, noCorner)
}
fun right(): CornerData {
return CornerData(noCorner, noCorner, topRight, bottomRight)
}
fun top(): CornerData {
return CornerData(topLeft, noCorner, topRight, noCorner)
}
fun bottom(): CornerData {
return CornerData(noCorner, bottomLeft, noCorner, bottomRight)
}
private companion object {
val noCorner: CornerSize = AbsoluteCornerSize(0f)
fun isLayoutRtl(view: View): Boolean {
return ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL
}
}
}

View File

@@ -10,11 +10,11 @@ import androidx.core.view.isGone
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.flowWithLifecycle
import com.google.android.material.button.MaterialButtonToggleGroup
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseBottomSheet
import org.koitharu.kotatsu.base.ui.widgets.CheckableButtonGroup
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.databinding.SheetReaderConfigBinding
import org.koitharu.kotatsu.reader.ui.PageSaveContract
@@ -26,9 +26,9 @@ import org.koitharu.kotatsu.utils.ext.withArgs
class ReaderConfigBottomSheet :
BaseBottomSheet<SheetReaderConfigBinding>(),
CheckableButtonGroup.OnCheckedChangeListener,
ActivityResultCallback<Uri?>,
View.OnClickListener {
View.OnClickListener,
MaterialButtonToggleGroup.OnButtonCheckedListener {
private val viewModel by activityViewModels<ReaderViewModel>()
private val savePageRequest = registerForActivityResult(PageSaveContract(), this)
@@ -53,7 +53,7 @@ class ReaderConfigBottomSheet :
binding.buttonReversed.isChecked = mode == ReaderMode.REVERSED
binding.buttonWebtoon.isChecked = mode == ReaderMode.WEBTOON
binding.checkableGroup.onCheckedChangeListener = this
binding.checkableGroup.addOnButtonCheckedListener(this)
binding.buttonSavePage.setOnClickListener(this)
binding.buttonScreenRotate.setOnClickListener(this)
binding.buttonSettings.setOnClickListener(this)
@@ -75,7 +75,10 @@ class ReaderConfigBottomSheet :
}
}
override fun onCheckedChanged(group: CheckableButtonGroup, checkedId: Int) {
override fun onButtonChecked(group: MaterialButtonToggleGroup?, checkedId: Int, isChecked: Boolean) {
if (!isChecked) {
return
}
val newMode = when (checkedId) {
R.id.button_standard -> ReaderMode.STANDARD
R.id.button_webtoon -> ReaderMode.WEBTOON

View File

@@ -55,7 +55,7 @@
android:text="@string/read_mode"
android:textAppearance="?textAppearanceTitleSmall" />
<org.koitharu.kotatsu.base.ui.widgets.CheckableButtonGroup
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/checkableGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -78,7 +78,6 @@
style="@style/Widget.Kotatsu.ToggleButton.Vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_small"
android:layout_weight="1"
android:text="@string/right_to_left"
app:icon="@drawable/ic_reader_rtl" />
@@ -92,7 +91,7 @@
android:text="@string/webtoon"
app:icon="@drawable/ic_script" />
</org.koitharu.kotatsu.base.ui.widgets.CheckableButtonGroup>
</com.google.android.material.button.MaterialButtonToggleGroup>
<TextView
android:layout_width="match_parent"

View File

@@ -109,13 +109,16 @@
<style name="Widget.Kotatsu.ToggleButton.Vertical">
<item name="android:textAlignment">center</item>
<item name="iconPadding">4dp</item>
<item name="iconPadding">2dp</item>
<item name="android:singleLine">false</item>
<item name="android:lines">2</item>
<item name="android:maxLines">2</item>
<item name="iconGravity">top</item>
<item name="android:paddingTop">10dp</item>
<item name="android:paddingTop">12dp</item>
<item name="android:paddingBottom">10dp</item>
<item name="android:paddingStart">6dp</item>
<item name="android:paddingEnd">6dp</item>
<item name="android:elegantTextHeight">false</item>
<item name="shapeAppearance">?shapeAppearanceCornerMedium</item>
</style>