Files
assistant-android/app/src/main/java/com/gh/common/view/ImageContainerView.kt

221 lines
10 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.gh.common.util.*
import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.ItemCommunityImageBinding
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.CommunityVideoEntity
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import java.util.ArrayList
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 index = 0
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)
val offset = ta.getDimensionPixelSize(R.styleable.ImageContainerView_offset, 0)
mDefaultWidth = (DisplayUtils.getScreenWidth() - offset.toFloat() - mItemSpace * 2) / 3
mFixdWidth = (DisplayUtils.getScreenWidth() - offset.toFloat() - mItemSpace * 2) * 2 / 3
ta.recycle()
}
fun bindData(entity: AnswerEntity, entrance: String = "", path: String = "") {
mAnswerEntity = entity
mEntrance = entrance
mPath = path
index = 0
removeAllViews()
if (entity.getPassVideos().isNullOrEmpty() && 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)
}
}
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)
}
} 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)
}
}
}
}
private fun bindVideo(video: CommunityVideoEntity, width: Int, height: Int, isChangeRatio: Boolean) {
val binding = ItemCommunityImageBinding.inflate(LayoutInflater.from(context), null, false)
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) {
val binding = ItemCommunityImageBinding.inflate(LayoutInflater.from(context), null, false)
binding.root.tag = index
addView(binding.root)
binding.durationOrNumTv.visibility = View.GONE
binding.videoPlay.visibility = View.GONE
displayImage(binding, url, width.toFloat(), height.toFloat(), isChangeRatio)
binding.root.setOnClickListener {
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
}
val intent = ImageViewerActivity.getIntent(context, mAnswerEntity!!.images as ArrayList<String>, position, binding.root,
if (mAnswerEntity?.type == "community_article") mAnswerEntity else null, mEntrance)
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()
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()
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.labelIcon.visibility = View.VISIBLE
binding.labelIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_gif_label))
}
val mediaCount = if (mAnswerEntity?.type == "community_article") {
mAnswerEntity?.images?.size ?: 0
} else {
(mAnswerEntity?.images?.size ?: 0) + (mAnswerEntity?.getPassVideos()?.size ?: 0)
}
if (!isVideo && index == 2 && mediaCount > 3) {
binding.labelIcon.visibility = View.GONE
binding.durationOrNumTv.visibility = View.VISIBLE
binding.durationOrNumTv.text = "+${mAnswerEntity?.images?.size}"
}
hierarchy.actualImageScaleType = ScalingUtils.ScaleType.CENTER_CROP
if (index != 0) params.leftMargin = mItemSpace
binding.root.layoutParams = params
}
}