Update list badges
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package org.koitharu.kotatsu.core.ui.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.os.Parcelable.Creator
|
||||
import android.util.AttributeSet
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import androidx.customview.view.AbsSavedState
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
import com.google.android.material.shape.ShapeAppearanceModel
|
||||
import com.google.android.material.textview.MaterialTextView
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
class BadgeView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : MaterialTextView(context, attrs, R.attr.badgeViewStyle) {
|
||||
|
||||
private var maxCharacterCount = Int.MAX_VALUE
|
||||
|
||||
var number: Int = 0
|
||||
set(value) {
|
||||
field = value
|
||||
updateText()
|
||||
}
|
||||
|
||||
init {
|
||||
context.withStyledAttributes(attrs, R.styleable.BadgeView) {
|
||||
maxCharacterCount = getInt(R.styleable.BadgeView_maxCharacterCount, maxCharacterCount)
|
||||
number = getInt(R.styleable.BadgeView_number, number)
|
||||
val shape = ShapeAppearanceModel.builder(
|
||||
context,
|
||||
getResourceId(R.styleable.BadgeView_shapeAppearance, 0),
|
||||
0,
|
||||
).build()
|
||||
background = MaterialShapeDrawable(shape).also { bg ->
|
||||
bg.fillColor = getColorStateList(R.styleable.BadgeView_backgroundColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(): Parcelable? {
|
||||
val superState = super.onSaveInstanceState() ?: return null
|
||||
return SavedState(superState, number)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(state: Parcelable?) {
|
||||
if (state is SavedState) {
|
||||
super.onRestoreInstanceState(state.superState)
|
||||
number = state.number
|
||||
} else {
|
||||
super.onRestoreInstanceState(state)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateText() {
|
||||
if (number <= 0) {
|
||||
text = null
|
||||
return
|
||||
}
|
||||
val numberString = number.toString()
|
||||
text = if (numberString.length > maxCharacterCount) {
|
||||
buildString(maxCharacterCount) {
|
||||
repeat(maxCharacterCount - 1) { append('9') }
|
||||
append('+')
|
||||
}
|
||||
} else {
|
||||
numberString
|
||||
}
|
||||
}
|
||||
|
||||
private class SavedState : AbsSavedState {
|
||||
|
||||
val number: Int
|
||||
|
||||
constructor(superState: Parcelable, number: Int) : super(superState) {
|
||||
this.number = number
|
||||
}
|
||||
|
||||
constructor(source: Parcel, classLoader: ClassLoader?) : super(source, classLoader) {
|
||||
number = source.readInt()
|
||||
}
|
||||
|
||||
override fun writeToParcel(out: Parcel, flags: Int) {
|
||||
super.writeToParcel(out, flags)
|
||||
out.writeInt(number)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Suppress("unused")
|
||||
@JvmField
|
||||
val CREATOR: Creator<SavedState> = object : Creator<SavedState> {
|
||||
override fun createFromParcel(`in`: Parcel) = SavedState(`in`, SavedState::class.java.classLoader)
|
||||
|
||||
override fun newArray(size: Int): Array<SavedState?> = arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,19 @@ import com.google.android.material.badge.ExperimentalBadgeUtils
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
|
||||
|
||||
@Deprecated("")
|
||||
@CheckResult
|
||||
fun View.bindBadge(badge: BadgeDrawable?, counter: Int): BadgeDrawable? {
|
||||
return bindBadgeImpl(badge, null, counter)
|
||||
}
|
||||
|
||||
@Deprecated("")
|
||||
@CheckResult
|
||||
fun View.bindBadge(badge: BadgeDrawable?, text: String?): BadgeDrawable? {
|
||||
return bindBadgeImpl(badge, text, 0)
|
||||
}
|
||||
|
||||
@Deprecated("")
|
||||
fun View.clearBadge(badge: BadgeDrawable?) {
|
||||
BadgeUtils.detachBadgeDrawable(badge, this)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import androidx.lifecycle.LifecycleOwner
|
||||
import coil3.ImageLoader
|
||||
import coil3.request.allowRgb565
|
||||
import coil3.request.transformations
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
||||
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
|
||||
@@ -30,7 +29,6 @@ fun mangaGridItemAD(
|
||||
) = adapterDelegateViewBinding<MangaGridModel, ListModel, ItemMangaGridBinding>(
|
||||
{ inflater, parent -> ItemMangaGridBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
var badge: BadgeDrawable? = null
|
||||
|
||||
AdapterDelegateClickListenerAdapter(this, clickListener, MangaGridModel::manga).attach(itemView)
|
||||
sizeResolver.attachToView(lifecycleOwner, itemView, binding.textViewTitle, binding.progressView)
|
||||
@@ -47,6 +45,7 @@ fun mangaGridItemAD(
|
||||
mangaExtra(item.manga)
|
||||
enqueueWith(coil)
|
||||
}
|
||||
badge = itemView.bindBadge(badge, item.counter)
|
||||
binding.badge.number = item.counter
|
||||
binding.badge.isVisible = item.counter > 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.koitharu.kotatsu.list.ui.adapter
|
||||
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import coil3.ImageLoader
|
||||
import coil3.request.allowRgb565
|
||||
import coil3.request.transformations
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
||||
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
|
||||
@@ -26,7 +26,6 @@ fun mangaListDetailedItemAD(
|
||||
) = adapterDelegateViewBinding<MangaDetailedListModel, ListModel, ItemMangaListDetailsBinding>(
|
||||
{ inflater, parent -> ItemMangaListDetailsBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
var badge: BadgeDrawable? = null
|
||||
|
||||
AdapterDelegateClickListenerAdapter(this, clickListener, MangaDetailedListModel::manga).attach(itemView)
|
||||
|
||||
@@ -46,6 +45,7 @@ fun mangaListDetailedItemAD(
|
||||
enqueueWith(coil)
|
||||
}
|
||||
binding.textViewTags.text = item.tags.joinToString(separator = ", ") { it.title ?: "" }
|
||||
badge = itemView.bindBadge(badge, item.counter)
|
||||
binding.badge.number = item.counter
|
||||
binding.badge.isVisible = item.counter > 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.list.ui.adapter
|
||||
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import coil3.ImageLoader
|
||||
import coil3.request.allowRgb565
|
||||
@@ -26,7 +27,6 @@ fun mangaListItemAD(
|
||||
) = adapterDelegateViewBinding<MangaCompactListModel, ListModel, ItemMangaListBinding>(
|
||||
{ inflater, parent -> ItemMangaListBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
var badge: BadgeDrawable? = null
|
||||
|
||||
AdapterDelegateClickListenerAdapter(this, clickListener, MangaCompactListModel::manga).attach(itemView)
|
||||
|
||||
@@ -40,6 +40,7 @@ fun mangaListItemAD(
|
||||
mangaExtra(item.manga)
|
||||
enqueueWith(coil)
|
||||
}
|
||||
badge = itemView.bindBadge(badge, item.counter)
|
||||
binding.badge.number = item.counter
|
||||
binding.badge.isVisible = item.counter > 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,17 @@
|
||||
app:srcCompat="@drawable/ic_heart"
|
||||
app:tint="?colorSurfaceBright" />
|
||||
|
||||
<org.koitharu.kotatsu.core.ui.widgets.BadgeView
|
||||
android:id="@+id/badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|end"
|
||||
android:layout_margin="@dimen/margin_small"
|
||||
android:visibility="gone"
|
||||
app:maxCharacterCount="@integer/manga_badge_max_character_count"
|
||||
tools:number="8"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
|
||||
@@ -53,4 +53,16 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView_title"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<org.koitharu.kotatsu.core.ui.widgets.BadgeView
|
||||
android:id="@+id/badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_small"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:maxCharacterCount="@integer/manga_badge_max_character_count"
|
||||
tools:number="8"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
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:background="@drawable/custom_selectable_item_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/custom_selectable_item_background">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -35,22 +35,22 @@
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/imageView_cover"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="12dp">
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
app:lineHeight="18dp"
|
||||
android:maxLines="3"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge"
|
||||
app:lineHeight="18dp"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<TextView
|
||||
@@ -73,17 +73,29 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:ellipsize="end"
|
||||
app:lineHeight="14dp"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/imageView_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView_author"
|
||||
app:lineHeight="14dp"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.koitharu.kotatsu.core.ui.widgets.BadgeView
|
||||
android:id="@+id/badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_small"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:maxCharacterCount="@integer/manga_badge_max_character_count"
|
||||
tools:number="8"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<attr name="tipViewStyle" />
|
||||
<attr name="progressButtonStyle" />
|
||||
<attr name="dotIndicatorStyle" />
|
||||
<attr name="badgeViewStyle" />
|
||||
|
||||
<!--CoverImageView attrs-->
|
||||
<declare-styleable name="CoverImageView">
|
||||
@@ -182,4 +183,11 @@
|
||||
<attr name="showMoreButton" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="BadgeView">
|
||||
<attr name="shapeAppearance" />
|
||||
<attr name="backgroundColor" />
|
||||
<attr name="maxCharacterCount" />
|
||||
<attr name="number" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -163,8 +163,18 @@
|
||||
<item name="scrollerOffset">@dimen/grid_spacing_outer</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Kotatsu.DotIndicator" parent="">
|
||||
<style name="Widget.Kotatsu.DotIndicator" parent="" />
|
||||
|
||||
<style name="Widget.Kotatsu.BadgeView" parent="">
|
||||
<item name="android:textColor">@macro/m3_comp_badge_large_label_text_color</item>
|
||||
<item name="android:minWidth">@dimen/m3_badge_with_text_size</item>
|
||||
<item name="android:minHeight">@dimen/m3_badge_with_text_size</item>
|
||||
<item name="android:textAppearance">@macro/m3_comp_badge_large_label_text_type</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="shapeAppearance">@style/ShapeAppearance.M3.Comp.Badge.Shape</item>
|
||||
<item name="backgroundColor">?attr/colorError</item>
|
||||
<item name="android:elegantTextHeight">false</item>
|
||||
<item name="singleLine">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Kotatsu.ListItemTextView" parent="">
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
<item name="bottomSheetDragHandleStyle">@style/Widget.Kotatsu.BottomSheet.DragHandle</item>
|
||||
<item name="android:dropDownSpinnerStyle">@style/Widget.Kotatsu.Spinner.DropDown</item>
|
||||
<item name="dotIndicatorStyle">@style/Widget.Kotatsu.DotIndicator</item>
|
||||
<item name="badgeViewStyle">@style/Widget.Kotatsu.BadgeView</item>
|
||||
|
||||
<!-- Text appearance -->
|
||||
<item name="actionMenuTextAppearance">@style/TextAppearance.Kotatsu.Menu</item>
|
||||
|
||||
Reference in New Issue
Block a user