311 lines
13 KiB
Kotlin
311 lines
13 KiB
Kotlin
package com.gh.common.view
|
|
|
|
import android.content.Context
|
|
import android.util.AttributeSet
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.widget.LinearLayout
|
|
import androidx.core.content.ContextCompat
|
|
import com.facebook.drawee.drawable.ScalingUtils
|
|
import com.facebook.drawee.view.SimpleDraweeView
|
|
import com.gh.common.util.*
|
|
import com.gh.gamecenter.ImageViewerActivity
|
|
import com.gh.gamecenter.R
|
|
import com.gh.gamecenter.common.utils.debounceActionWithInterval
|
|
import com.gh.gamecenter.common.utils.dip2px
|
|
import com.gh.gamecenter.common.utils.toResString
|
|
import com.gh.gamecenter.core.utils.DisplayUtils
|
|
import com.gh.gamecenter.common.utils.ImageUtils
|
|
import com.gh.gamecenter.core.utils.TopCutProcess
|
|
import com.gh.gamecenter.databinding.ItemCommunityImageBinding
|
|
import com.gh.gamecenter.login.user.UserManager
|
|
import com.gh.gamecenter.feature.entity.AnswerEntity
|
|
import com.gh.gamecenter.feature.entity.CommunityVideoEntity
|
|
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
|
|
|
class ImageContainerView : LinearLayout {
|
|
private var mAnswerEntity: AnswerEntity? = null
|
|
|
|
//三图默认宽度
|
|
private var mDefaultWidth = 0f
|
|
|
|
//单图固定宽度
|
|
private var mFixdWidth = 0f
|
|
|
|
//最小比例
|
|
private var mMinRatio = 3 / 4f
|
|
|
|
//最大比例
|
|
private var mMaxRatio = 3 / 2f
|
|
|
|
//长图比例
|
|
private var mLongPictureRatio = 9 / 18f
|
|
|
|
private var mEntrance = ""
|
|
private var mPath = ""
|
|
|
|
//图片之间的间距
|
|
private val mItemSpace = 4f.dip2px()
|
|
private var mOffset = 0
|
|
private var index = 0
|
|
|
|
private val imageViewList = arrayListOf<SimpleDraweeView>()
|
|
|
|
constructor(context: Context) : this(context, null)
|
|
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
|
initView(attrs)
|
|
}
|
|
|
|
private fun initView(attrs: AttributeSet?) {
|
|
orientation = HORIZONTAL
|
|
val ta = context.obtainStyledAttributes(attrs, R.styleable.ImageContainerView)
|
|
mOffset = ta.getDimensionPixelSize(R.styleable.ImageContainerView_offset, 0)
|
|
calculateWidth()
|
|
ta.recycle()
|
|
}
|
|
|
|
private fun calculateWidth() {
|
|
mDefaultWidth = (DisplayUtils.getScreenWidth() - mOffset.toFloat() - mItemSpace * 2) / 3
|
|
mFixdWidth = (DisplayUtils.getScreenWidth() - mOffset.toFloat() - mItemSpace * 2) * 2 / 3
|
|
}
|
|
|
|
fun setOffset(offset: Float) {
|
|
mOffset = offset.dip2px()
|
|
calculateWidth()
|
|
}
|
|
|
|
fun bindData(entity: AnswerEntity, entrance: String = "", path: String = "", imageClick: (() -> Unit)? = null) {
|
|
imageViewList.clear()
|
|
if (entity.id != mAnswerEntity?.id) {
|
|
removeAllViews()
|
|
}
|
|
mAnswerEntity = entity
|
|
mEntrance = entrance
|
|
mPath = path
|
|
index = 0
|
|
if ((entity.user.id == UserManager.getInstance().userId && entity.videos.isNotEmpty()) ||
|
|
(entity.user.id != UserManager.getInstance().userId && entity.getPassVideos().isNotEmpty()) ||
|
|
entity.images.isNullOrEmpty()
|
|
) {
|
|
visibility = View.GONE
|
|
return
|
|
}
|
|
visibility = View.VISIBLE
|
|
if (mAnswerEntity?.type == "community_article") {
|
|
//若文章内容含有图片及视频,则信息流卡片,仅展示图片,且标题后带有‘有视频’标签
|
|
//若文章内容仅含有图片,则信息流卡片,仅展示图片,无标签
|
|
//若文章内容仅含有视频,则信息流卡片,仅展示视频,无标签
|
|
when {
|
|
entity.images.isNotEmpty() -> {
|
|
val imagesInfo = entity.imagesInfo
|
|
val images = entity.images.take(3)
|
|
images.forEachIndexed { index, url ->
|
|
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
|
|
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
|
|
bindImage(url, width, height, images.size == 1, imageClick)
|
|
}
|
|
}
|
|
|
|
entity.getPassVideos().isNotEmpty() -> {
|
|
val video = entity.getPassVideos()[0]
|
|
bindVideo(video, video.width, video.height, true)
|
|
}
|
|
|
|
else -> {
|
|
// do noting
|
|
}
|
|
}
|
|
} else {
|
|
//若问答内容含有图片及视频,则信息流卡片,同时展示图片及视频,且参考以往排序逻辑(视频优先放置第一位),无标签
|
|
//若问答内容仅含有图片,则信息流卡片,仅展示图片,无标签
|
|
//若问答内容仅含有视频,则信息流卡片,仅展示视频,无标签
|
|
if (entity.getPassVideos().isNotEmpty()) {
|
|
val video = entity.getPassVideos()[0]
|
|
bindVideo(video, video.width, video.height, mAnswerEntity?.images.isNullOrEmpty())
|
|
entity.images.take(2).forEachIndexed { index, url ->
|
|
val imagesInfo = entity.imagesInfo
|
|
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
|
|
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
|
|
bindImage(url, width, height, false, imageClick)
|
|
}
|
|
} else {
|
|
val images = entity.images.take(3)
|
|
images.forEachIndexed { index, url ->
|
|
val imagesInfo = entity.imagesInfo
|
|
val width = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].width else 0
|
|
val height = if (index <= entity.imagesInfo.size - 1) imagesInfo[index].height else 0
|
|
bindImage(url, width, height, images.size == 1, imageClick)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun bindVideo(video: CommunityVideoEntity, width: Int, height: Int, isChangeRatio: Boolean) {
|
|
val oldView = if (childCount == 0 || index >= childCount) null else getChildAt(index)
|
|
val binding = if (oldView != null) {
|
|
ItemCommunityImageBinding.bind(oldView)
|
|
} else {
|
|
ItemCommunityImageBinding.inflate(LayoutInflater.from(context), null, false)
|
|
}
|
|
if (oldView == null) {
|
|
addView(binding.root)
|
|
}
|
|
binding.durationOrNumTv.visibility = View.VISIBLE
|
|
binding.videoPlay.visibility = View.VISIBLE
|
|
binding.labelIcon.visibility = View.GONE
|
|
binding.durationOrNumTv.text = video.duration
|
|
displayImage(binding, video.poster, width.toFloat(), height.toFloat(), isChangeRatio, true)
|
|
binding.root.setOnClickListener {
|
|
debounceActionWithInterval(it.id, 1000) {
|
|
if (mAnswerEntity == null) return@debounceActionWithInterval
|
|
val videoEntity = mAnswerEntity!!.getPassVideos()[0]
|
|
DirectUtils.directToVideoDetail(
|
|
context,
|
|
videoEntity.id,
|
|
VideoDetailContainerViewModel.Location.VIDEO_HOT.value,
|
|
showComment = false,
|
|
entrance = mEntrance,
|
|
path = mPath
|
|
)
|
|
}
|
|
}
|
|
index++
|
|
}
|
|
|
|
private fun bindImage(
|
|
url: String,
|
|
width: Int,
|
|
height: Int,
|
|
isChangeRatio: Boolean,
|
|
imageClick: (() -> Unit)?
|
|
) {
|
|
val oldView = if (childCount == 0 || index >= childCount) null else getChildAt(index)
|
|
val binding = if (oldView != null) {
|
|
ItemCommunityImageBinding.bind(oldView)
|
|
} else {
|
|
ItemCommunityImageBinding.inflate(LayoutInflater.from(context), null, false)
|
|
}
|
|
binding.root.tag = index
|
|
if (oldView == null) {
|
|
addView(binding.root)
|
|
}
|
|
imageViewList.add(binding.image)
|
|
binding.durationOrNumTv.visibility = View.GONE
|
|
binding.videoPlay.visibility = View.GONE
|
|
displayImage(binding, url, width.toFloat(), height.toFloat(), isChangeRatio)
|
|
binding.root.setOnClickListener {
|
|
if (mAnswerEntity?.status == "pending" || mAnswerEntity?.status == "fail") return@setOnClickListener
|
|
imageClick?.invoke()
|
|
debounceActionWithInterval(it.id, 1000) {
|
|
if (mAnswerEntity == null) return@debounceActionWithInterval
|
|
val position = if (mAnswerEntity?.type == "community_article") {
|
|
binding.root.tag as Int
|
|
} else {
|
|
if (mAnswerEntity!!.getPassVideos()
|
|
.isNullOrEmpty()
|
|
) binding.root.tag as Int else (binding.root.tag as Int) - 1
|
|
}
|
|
if (mAnswerEntity?.communityId.isNullOrEmpty()) {
|
|
mAnswerEntity?.communityId = mAnswerEntity?.bbs?.id
|
|
}
|
|
val intent = ImageViewerActivity.getIntent(
|
|
context, mAnswerEntity!!.images as ArrayList<String>, position, imageViewList,
|
|
if (mAnswerEntity?.type == "community_article") mAnswerEntity else null, mEntrance, true
|
|
)
|
|
context.startActivity(intent)
|
|
}
|
|
}
|
|
index++
|
|
}
|
|
|
|
private fun displayImage(
|
|
binding: ItemCommunityImageBinding,
|
|
url: String,
|
|
width: Float,
|
|
height: Float,
|
|
isChangeRatio: Boolean,
|
|
isVideo: Boolean = false
|
|
) {
|
|
val params = binding.root.layoutParams as LayoutParams
|
|
val hierarchy = binding.image.hierarchy
|
|
binding.labelIcon.visibility = View.GONE
|
|
if (width != 0f && height != 0f) {
|
|
val picRatio = width / height
|
|
if (isChangeRatio) {
|
|
when {
|
|
picRatio <= mMinRatio -> {
|
|
params.height = (mFixdWidth / mMinRatio).toInt()
|
|
if (binding.image.tag != url) {
|
|
ImageUtils.display(binding.image, url, false, TopCutProcess(mMinRatio))
|
|
}
|
|
}
|
|
|
|
picRatio >= mMaxRatio -> {
|
|
params.height = (mFixdWidth / mMaxRatio).toInt()
|
|
ImageUtils.display(binding.image, url, false)
|
|
}
|
|
|
|
else -> {
|
|
params.height = (mFixdWidth / picRatio).toInt()
|
|
ImageUtils.display(binding.image, url, false)
|
|
}
|
|
}
|
|
params.width = mFixdWidth.toInt()
|
|
} else {
|
|
params.width = mDefaultWidth.toInt()
|
|
params.height = mDefaultWidth.toInt()
|
|
if (width > height) {
|
|
val loadImageWidth = width * (mDefaultWidth.toInt() / height)
|
|
binding.image.setTag(ImageUtils.TAG_TARGET_WIDTH, loadImageWidth.toInt())
|
|
}
|
|
ImageUtils.display(binding.image, url, false)
|
|
}
|
|
//长图
|
|
if (!isVideo && picRatio <= mLongPictureRatio) {
|
|
binding.labelIcon.visibility = View.VISIBLE
|
|
binding.labelIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_long_pic_label))
|
|
}
|
|
} else {
|
|
params.width = mDefaultWidth.toInt()
|
|
params.height = mDefaultWidth.toInt()
|
|
ImageUtils.display(binding.image, url, false)
|
|
}
|
|
|
|
if (url.endsWith(".gif")) {
|
|
binding.gifBorder.visibility = View.VISIBLE
|
|
binding.labelIcon.visibility = View.VISIBLE
|
|
binding.labelIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_gif_label))
|
|
}
|
|
|
|
binding.pendingView.run {
|
|
when (mAnswerEntity?.status) {
|
|
"pending" -> {
|
|
visibility = View.VISIBLE
|
|
text = R.string.pending_status.toResString()
|
|
}
|
|
|
|
"fail" -> {
|
|
visibility = View.VISIBLE
|
|
text = R.string.fail_status.toResString()
|
|
}
|
|
|
|
else -> {
|
|
visibility = View.GONE
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
val imageCount = mAnswerEntity?.images?.size ?: 0
|
|
if (!isVideo && index == 2 && imageCount > 3) {
|
|
binding.labelIcon.visibility = View.GONE
|
|
binding.durationOrNumTv.visibility = View.VISIBLE
|
|
binding.durationOrNumTv.text = "+${imageCount - 3}"
|
|
}
|
|
|
|
hierarchy.actualImageScaleType = ScalingUtils.ScaleType.CENTER_CROP
|
|
if (index != 0) params.leftMargin = mItemSpace
|
|
binding.root.layoutParams = params
|
|
}
|
|
} |