Expandable manga description

This commit is contained in:
Koitharu
2023-07-20 13:33:48 +03:00
parent 80149b1ce7
commit 82a3b93214
6 changed files with 39 additions and 73 deletions

View File

@@ -11,6 +11,7 @@ import androidx.core.content.res.use
import androidx.core.view.isGone
import androidx.core.widget.TextViewCompat
var TextView.textAndVisible: CharSequence?
get() = text?.takeIf { visibility == View.VISIBLE }
set(value) {
@@ -70,3 +71,13 @@ fun TextView.setThemeTextAppearance(@AttrRes resId: Int, @StyleRes fallback: Int
TextViewCompat.setTextAppearance(this, it.getResourceId(0, fallback))
}
}
val TextView.isTextTruncated: Boolean
get() {
val l = layout ?: return false
if (maxLines in 0 until l.lineCount) {
return true
}
val layoutLines = l.lineCount
return layoutLines > 0 && l.getEllipsisCount(layoutLines - 1) > 0
}

View File

@@ -1,32 +0,0 @@
package org.koitharu.kotatsu.details.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.showDistinct
import org.koitharu.kotatsu.core.util.ext.withArgs
import org.koitharu.kotatsu.databinding.SheetDescriptionBinding
class DescriptionSheet : BaseAdaptiveSheet<SheetDescriptionBinding>() {
override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetDescriptionBinding {
return SheetDescriptionBinding.inflate(inflater, container, false)
}
override fun onViewBindingCreated(binding: SheetDescriptionBinding, savedInstanceState: Bundle?) {
super.onViewBindingCreated(binding, savedInstanceState)
binding.textViewDescription.text = arguments?.getCharSequence(ARG_CONTENT)
}
companion object {
private const val ARG_CONTENT = "content"
private const val TAG = "DescriptionSheet"
fun show(fm: FragmentManager, content: CharSequence) = DescriptionSheet().withArgs(1) {
putCharSequence(ARG_CONTENT, content)
}.showDistinct(fm, TAG)
}
}

View File

@@ -2,9 +2,11 @@ package org.koitharu.kotatsu.details.ui
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.transition.TransitionManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.Toast
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.ContextCompat
@@ -36,7 +38,9 @@ import org.koitharu.kotatsu.core.util.ext.crossfade
import org.koitharu.kotatsu.core.util.ext.drawableTop
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty
import org.koitharu.kotatsu.core.util.ext.isTextTruncated
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.parentView
import org.koitharu.kotatsu.core.util.ext.resolveDp
import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf
import org.koitharu.kotatsu.core.util.ext.textAndVisible
@@ -70,7 +74,7 @@ class DetailsFragment :
BaseFragment<FragmentDetailsBinding>(),
View.OnClickListener,
ChipsView.OnChipClickListener,
OnListItemClickListener<Bookmark> {
OnListItemClickListener<Bookmark>, ViewTreeObserver.OnDrawListener {
@Inject
lateinit var coil: ImageLoader
@@ -94,6 +98,7 @@ class DetailsFragment :
binding.buttonScrobblingMore.setOnClickListener(this)
binding.buttonRelatedMore.setOnClickListener(this)
binding.infoLayout.textViewSource.setOnClickListener(this)
binding.textViewDescription.viewTreeObserver.addOnDrawListener(this)
binding.textViewDescription.movementMethod = LinkMovementMethod.getInstance()
binding.chipsTags.onChipClickListener = this
binding.recyclerViewRelated.addItemDecoration(
@@ -132,6 +137,13 @@ class DetailsFragment :
return true
}
override fun onDraw() {
viewBinding?.run {
buttonDescriptionMore.isVisible = textViewDescription.maxLines == Int.MAX_VALUE ||
textViewDescription.isTextTruncated
}
}
private fun onMangaUpdated(manga: Manga) {
with(requireViewBinding()) {
// Main
@@ -189,12 +201,13 @@ class DetailsFragment :
}
private fun onDescriptionChanged(description: CharSequence?) {
val tv = requireViewBinding().textViewDescription
if (description.isNullOrBlank()) {
requireViewBinding().textViewDescription.setText(R.string.no_description)
tv.setText(R.string.no_description)
} else {
requireViewBinding().textViewDescription.text = description
tv.text = description
}
requireViewBinding().buttonDescriptionMore.isGone = description.isNullOrBlank()
requireViewBinding().buttonDescriptionMore.isVisible = tv.isTextTruncated
}
private fun onLocalSizeChanged(size: Long) {
@@ -300,7 +313,13 @@ class DetailsFragment :
}
R.id.button_description_more -> {
DescriptionSheet.show(parentFragmentManager, viewModel.description.value ?: return)
val tv = requireViewBinding().textViewDescription
TransitionManager.beginDelayedTransition(tv.parentView)
if (tv.maxLines in 1 until Integer.MAX_VALUE) {
tv.maxLines = Integer.MAX_VALUE
} else {
tv.maxLines = resources.getInteger(R.integer.details_description_lines)
}
}
R.id.button_scrobbling_more -> {

View File

@@ -164,7 +164,7 @@
app:layout_constraintBaseline_toBaselineOf="@id/textView_description_title"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
<org.koitharu.kotatsu.core.ui.widgets.SelectableTextView
android:id="@+id/textView_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -173,9 +173,10 @@
android:layout_marginEnd="@dimen/margin_normal"
android:ellipsize="end"
android:lineSpacingMultiplier="1.2"
android:maxLines="5"
android:maxLines="@integer/details_description_lines"
android:paddingBottom="@dimen/margin_normal"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textIsSelectable="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView_description_title"

View File

@@ -1,34 +0,0 @@
<?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:animateLayoutChanges="true"
android:orientation="vertical">
<org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetHeaderBar
android:id="@+id/headerBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/description" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.koitharu.kotatsu.core.ui.widgets.SelectableTextView
android:id="@+id/textView_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginEnd="@dimen/margin_normal"
android:lineSpacingMultiplier="1.2"
android:paddingBottom="@dimen/margin_normal"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textIsSelectable="true"
tools:text="@tools:sample/lorem/random" />
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@@ -6,4 +6,5 @@
<integer name="manga_badge_max_character_count">3</integer>
<integer name="explore_buttons_columns">2</integer>
<integer name="details_description_lines">5</integer>
</resources>