Fullscreen cover view activity
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.details.ui
|
||||
|
||||
import android.app.ActivityOptions
|
||||
import android.os.Bundle
|
||||
import android.text.Spanned
|
||||
import android.view.LayoutInflater
|
||||
@@ -27,6 +28,7 @@ import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.model.MangaState
|
||||
import org.koitharu.kotatsu.databinding.FragmentDetailsBinding
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesDialog
|
||||
import org.koitharu.kotatsu.image.ui.ImageActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
import org.koitharu.kotatsu.search.ui.SearchActivity
|
||||
@@ -50,6 +52,7 @@ class DetailsFragment : BaseFragment<FragmentDetailsBinding>(), View.OnClickList
|
||||
binding.buttonFavorite.setOnClickListener(this)
|
||||
binding.buttonRead.setOnClickListener(this)
|
||||
binding.buttonRead.setOnLongClickListener(this)
|
||||
binding.coverCard.setOnClickListener(this)
|
||||
viewModel.manga.observe(viewLifecycleOwner, ::onMangaUpdated)
|
||||
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
|
||||
viewModel.favouriteCategories.observe(viewLifecycleOwner, ::onFavouriteChanged)
|
||||
@@ -189,6 +192,17 @@ class DetailsFragment : BaseFragment<FragmentDetailsBinding>(), View.OnClickList
|
||||
)
|
||||
)
|
||||
}
|
||||
R.id.cover_card -> {
|
||||
val options = ActivityOptions.makeSceneTransitionAnimation(
|
||||
requireActivity(),
|
||||
binding.imageViewCover,
|
||||
binding.imageViewCover.transitionName,
|
||||
)
|
||||
startActivity(
|
||||
ImageActivity.newIntent(v.context, manga.largeCoverUrl ?: manga.coverUrl),
|
||||
options.toBundle()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package org.koitharu.kotatsu.image.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.core.view.updatePadding
|
||||
import coil.ImageLoader
|
||||
import coil.request.CachePolicy
|
||||
import coil.request.ImageRequest
|
||||
import coil.target.PoolableViewTarget
|
||||
import com.davemorrissey.labs.subscaleview.ImageSource
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.databinding.ActivityImageBinding
|
||||
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.utils.ext.indicator
|
||||
|
||||
class ImageActivity : BaseActivity<ActivityImageBinding>() {
|
||||
|
||||
private val coil: ImageLoader by inject()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityImageBinding.inflate(layoutInflater))
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowTitleEnabled(false)
|
||||
}
|
||||
loadImage(intent.data)
|
||||
}
|
||||
|
||||
override fun onWindowInsetsChanged(insets: Insets) {
|
||||
binding.toolbar.updatePadding(
|
||||
left = insets.left,
|
||||
right = insets.right,
|
||||
top = insets.top,
|
||||
)
|
||||
}
|
||||
|
||||
private fun loadImage(url: Uri?) {
|
||||
ImageRequest.Builder(this)
|
||||
.data(url)
|
||||
.memoryCachePolicy(CachePolicy.DISABLED)
|
||||
.lifecycle(this)
|
||||
.target(SsivTarget(binding.ssiv))
|
||||
.indicator(binding.progressBar)
|
||||
.enqueueWith(coil)
|
||||
}
|
||||
|
||||
private class SsivTarget(
|
||||
override val view: SubsamplingScaleImageView,
|
||||
) : PoolableViewTarget<SubsamplingScaleImageView> {
|
||||
|
||||
override fun onStart(placeholder: Drawable?) = setDrawable(placeholder)
|
||||
|
||||
override fun onError(error: Drawable?) = setDrawable(error)
|
||||
|
||||
override fun onSuccess(result: Drawable) = setDrawable(result)
|
||||
|
||||
override fun onClear() = setDrawable(null)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return (this === other) || (other is SsivTarget && view == other.view)
|
||||
}
|
||||
|
||||
override fun hashCode() = view.hashCode()
|
||||
|
||||
override fun toString() = "SsivTarget(view=$view)"
|
||||
|
||||
private fun setDrawable(drawable: Drawable?) {
|
||||
if (drawable != null) {
|
||||
view.setImage(ImageSource.bitmap(drawable.toBitmap()))
|
||||
} else {
|
||||
view.recycle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newIntent(context: Context, url: String): Intent {
|
||||
return Intent(context, ImageActivity::class.java)
|
||||
.setData(Uri.parse(url))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,16 +7,16 @@ import coil.request.ErrorResult
|
||||
import coil.request.ImageRequest
|
||||
import coil.request.ImageResult
|
||||
import coil.request.SuccessResult
|
||||
import com.google.android.material.progressindicator.BaseProgressIndicator
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.utils.progress.ImageRequestIndicatorListener
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun ImageView.newImageRequest(url: String) = ImageRequest.Builder(context)
|
||||
fun ImageView.newImageRequest(url: String) = ImageRequest.Builder(context)
|
||||
.data(url)
|
||||
.crossfade(true)
|
||||
.target(this)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun ImageRequest.Builder.enqueueWith(loader: ImageLoader) = loader.enqueue(build())
|
||||
fun ImageRequest.Builder.enqueueWith(loader: ImageLoader) = loader.enqueue(build())
|
||||
|
||||
fun ImageResult.requireBitmap() = when (this) {
|
||||
is SuccessResult -> drawable.toBitmap()
|
||||
@@ -32,7 +32,10 @@ fun ImageResult.toBitmapOrNull() = when (this) {
|
||||
is ErrorResult -> null
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun ImageRequest.Builder.referer(referer: String): ImageRequest.Builder {
|
||||
fun ImageRequest.Builder.referer(referer: String): ImageRequest.Builder {
|
||||
return setHeader(CommonHeaders.REFERER, referer)
|
||||
}
|
||||
|
||||
fun ImageRequest.Builder.indicator(indicator: BaseProgressIndicator<*>): ImageRequest.Builder {
|
||||
return listener(ImageRequestIndicatorListener(indicator))
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.koitharu.kotatsu.utils.progress
|
||||
|
||||
import coil.request.ImageRequest
|
||||
import coil.request.ImageResult
|
||||
import com.google.android.material.progressindicator.BaseProgressIndicator
|
||||
|
||||
class ImageRequestIndicatorListener(
|
||||
private val indicator: BaseProgressIndicator<*>,
|
||||
) : ImageRequest.Listener {
|
||||
|
||||
override fun onCancel(request: ImageRequest) = indicator.hide()
|
||||
|
||||
override fun onError(request: ImageRequest, throwable: Throwable) = indicator.hide()
|
||||
|
||||
override fun onStart(request: ImageRequest) = indicator.show()
|
||||
|
||||
override fun onSuccess(request: ImageRequest, metadata: ImageResult.Metadata) = indicator.hide()
|
||||
}
|
||||
Reference in New Issue
Block a user