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.manager.UserManager 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 mOffset = 0 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) 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 = "") { mAnswerEntity = entity mEntrance = entrance mPath = path index = 0 removeAllViews() 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) } } 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 } if (mAnswerEntity?.communityId.isNullOrEmpty()) { mAnswerEntity?.communityId = mAnswerEntity?.bbs?.id } val intent = ImageViewerActivity.getIntent(context, mAnswerEntity!!.images as ArrayList, 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.gifBorder.visibility = View.VISIBLE 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?.minus(3)}" } hierarchy.actualImageScaleType = ScalingUtils.ScaleType.CENTER_CROP if (index != 0) params.leftMargin = mItemSpace binding.root.layoutParams = params } }