diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/detail/CreatorChannelCommunityDetailActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/detail/CreatorChannelCommunityDetailActivity.kt index 206d37f3..71e20f12 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/detail/CreatorChannelCommunityDetailActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/community/detail/CreatorChannelCommunityDetailActivity.kt @@ -3,8 +3,12 @@ package kr.co.vividnext.sodalive.v2.creator.channel.community.detail import android.app.Activity import android.content.Context import android.content.Intent +import android.graphics.Outline +import android.graphics.drawable.Drawable import android.os.Bundle import android.text.method.ScrollingMovementMethod +import android.view.View +import android.view.ViewOutlineProvider import android.view.inputmethod.InputMethodManager import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts @@ -13,6 +17,10 @@ import androidx.core.widget.doAfterTextChanged import androidx.recyclerview.widget.LinearLayoutManager import coil.transform.CircleCropTransformation import com.bumptech.glide.Glide +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.target.Target import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.base.BaseActivity import kr.co.vividnext.sodalive.databinding.ActivityCreatorChannelCommunityDetailBinding @@ -24,6 +32,7 @@ import kr.co.vividnext.sodalive.extensions.moneyFormat import kr.co.vividnext.sodalive.v2.components.modal.V2ModalDialog import kr.co.vividnext.sodalive.v2.creator.channel.community.detail.reply.CreatorChannelCommunityReplyActivity import kr.co.vividnext.sodalive.v2.creator.channel.community.detail.ui.CreatorChannelCommunityCommentAdapter +import kr.co.vividnext.sodalive.v2.widget.feed.calculateFeedCommunityImageHeight import org.koin.androidx.viewmodel.ext.android.viewModel class CreatorChannelCommunityDetailActivity : BaseActivity( @@ -56,6 +65,8 @@ class CreatorChannelCommunityDetailActivity : BaseActivity @@ -156,6 +167,10 @@ class CreatorChannelCommunityDetailActivity : BaseActivity 0 layoutCreatorChannelCommunityDetailImageContainer.isVisible = post.imageUrl != null || post.showPaywall + layoutCreatorChannelCommunityDetailImageContainer.layoutParams = + layoutCreatorChannelCommunityDetailImageContainer.layoutParams.apply { + height = if (post.imageUrl != null) DEFAULT_IMAGE_HEIGHT_DP.dpToPx() else DEFAULT_PAYWALL_HEIGHT_DP.dpToPx() + } layoutCreatorChannelCommunityDetailPaywall.isVisible = post.showPaywall tvCreatorChannelCommunityDetailPaywallPrice.text = post.price.moneyFormat() layoutCreatorChannelCommunityDetailPaywall.setOnClickListener { @@ -165,6 +180,25 @@ class CreatorChannelCommunityDetailActivity : BaseActivity { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: Target, + isFirstResource: Boolean + ): Boolean = false + + override fun onResourceReady( + resource: Drawable, + model: Any, + target: Target?, + dataSource: DataSource, + isFirstResource: Boolean + ): Boolean { + applyDetailImageSize(resource.intrinsicWidth, resource.intrinsicHeight) + return false + } + }) .into(ivCreatorChannelCommunityDetailImage) } else { Glide.with(ivCreatorChannelCommunityDetailImage).clear(ivCreatorChannelCommunityDetailImage) @@ -196,6 +230,29 @@ class CreatorChannelCommunityDetailActivity : BaseActivity 0 } + ?: container.measuredWidth.takeIf { it > 0 } + ?: ivCreatorChannelCommunityDetailImage.width.takeIf { it > 0 } + ?: run { + container.post { applyDetailImageSize(intrinsicWidthPx, intrinsicHeightPx) } + return@with + } + val imageHeight = calculateFeedCommunityImageHeight( + containerWidthPx = containerWidth, + intrinsicWidthPx = intrinsicWidthPx, + intrinsicHeightPx = intrinsicHeightPx + ) ?: return@with + container.layoutParams = container.layoutParams.apply { height = imageHeight } + } + + private fun roundedOutlineProvider() = object : ViewOutlineProvider() { + override fun getOutline(view: View, outline: Outline) { + outline.setRoundRect(0, 0, view.width, view.height, COMMUNITY_IMAGE_RADIUS_DP.dpToPx().toFloat()) + } + } + private fun updateSendButton(enabled: Boolean) = with(binding.btnCreatorChannelCommunityDetailSend) { isEnabled = enabled setBackgroundResource( @@ -269,10 +326,15 @@ class CreatorChannelCommunityDetailActivity : BaseActivity Unit = {}, @@ -54,6 +60,11 @@ class CreatorChannelCommunityListAdapter( private val isPlayingContent: (Long) -> Boolean ) : RecyclerView.ViewHolder(binding.root) { + init { + binding.layoutCreatorChannelCommunityListImageContainer.clipToOutline = true + binding.layoutCreatorChannelCommunityListImageContainer.outlineProvider = roundedOutlineProvider() + } + fun bind(item: CreatorChannelCommunityPostUiModel) = with(binding) { root.setOnClickListener { onPostClick(item) } ivCreatorChannelCommunityListProfile.loadUrl(item.creatorProfileUrl) { @@ -77,11 +88,30 @@ class CreatorChannelCommunityListAdapter( layoutCreatorChannelCommunityListImageContainer.isVisible = visibleImageUrl != null || item.isLocked || item.showPlayButton ivCreatorChannelCommunityListImage.isVisible = visibleImageUrl != null + resetCommunityImageHeight() if (visibleImageUrl != null) { Glide.with(ivCreatorChannelCommunityListImage) .load(visibleImageUrl) .placeholder(R.drawable.ic_place_holder) - .apply(communityImageRequestOptions()) + .listener(object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: Target, + isFirstResource: Boolean + ): Boolean = false + + override fun onResourceReady( + resource: Drawable, + model: Any, + target: Target?, + dataSource: DataSource, + isFirstResource: Boolean + ): Boolean { + applyCommunityImageSize(resource.intrinsicWidth, resource.intrinsicHeight) + return false + } + }) .into(ivCreatorChannelCommunityListImage) } else { Glide.with(ivCreatorChannelCommunityListImage).clear(ivCreatorChannelCommunityListImage) @@ -104,11 +134,45 @@ class CreatorChannelCommunityListAdapter( ivCreatorChannelCommunityListOwnerMore.setOnClickListener { onOwnerMoreClick(item) } } - private fun communityImageRequestOptions(): RequestOptions { - return RequestOptions().transform( - CenterCrop(), - RoundedCorners(14f.dpToPx().toInt()) - ) + private fun resetCommunityImageHeight() { + binding.layoutCreatorChannelCommunityListImageContainer.layoutParams = + binding.layoutCreatorChannelCommunityListImageContainer.layoutParams.apply { + height = DEFAULT_IMAGE_HEIGHT_DP.dpToPx().toInt() + } + } + + private fun applyCommunityImageSize(intrinsicWidthPx: Int, intrinsicHeightPx: Int): Unit = with(binding) { + val container = layoutCreatorChannelCommunityListImageContainer + val containerWidth = container.width.takeIf { it > 0 } + ?: container.measuredWidth.takeIf { it > 0 } + ?: root.width.takeIf { it > 0 }?.let { it - root.paddingLeft - root.paddingRight } + ?: run { + container.post { applyCommunityImageSize(intrinsicWidthPx, intrinsicHeightPx) } + return@with + } + val imageHeight = calculateFeedCommunityImageHeight( + containerWidthPx = containerWidth, + intrinsicWidthPx = intrinsicWidthPx, + intrinsicHeightPx = intrinsicHeightPx + ) ?: return@with + container.layoutParams = container.layoutParams.apply { height = imageHeight } + } + + private fun roundedOutlineProvider() = object : ViewOutlineProvider() { + override fun getOutline(view: View, outline: Outline) { + outline.setRoundRect( + 0, + 0, + view.width, + view.height, + COMMUNITY_IMAGE_RADIUS_DP.dpToPx() + ) + } + } + + private companion object { + const val DEFAULT_IMAGE_HEIGHT_DP = 236f + const val COMMUNITY_IMAGE_RADIUS_DP = 14f } } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt index d8f95b8e..7ad501c3 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt @@ -435,6 +435,14 @@ class CreatorChannelHomeSectionAdapter( val communityImageUrl = community.imageUrl.takeIf { !it.isNullOrBlank() } if (communityImageUrl != null) { communityRow.communityImageView().loadUrl(communityImageUrl) { + listener( + onSuccess = { _, result -> + communityRow.applyCommunityImageSize( + result.drawable.intrinsicWidth, + result.drawable.intrinsicHeight + ) + } + ) if (isCommunityLocked) { transformations(BlurTransformation(itemView.context, 25f, 2.5f)) } diff --git a/app/src/main/res/layout/activity_creator_channel_community_detail.xml b/app/src/main/res/layout/activity_creator_channel_community_detail.xml index 357ab4fc..270fa755 100644 --- a/app/src/main/res/layout/activity_creator_channel_community_detail.xml +++ b/app/src/main/res/layout/activity_creator_channel_community_detail.xml @@ -136,7 +136,7 @@ + android:adjustViewBounds="true" + android:scaleType="fitCenter" />