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

208 lines
7.2 KiB
Kotlin

package com.gh.common.view
import android.content.Context
import android.util.AttributeSet
import android.view.*
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.common.util.DisplayUtils
import com.gh.common.util.ImageUtils
import com.gh.common.util.rxTimer
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.SettingsEntity
import io.reactivex.disposables.Disposable
import kotlin.math.abs
/**
* 视频流广告轮播控件
*/
class AdBannerView : LinearLayout {
private lateinit var mViewPager2: ViewPager2
private var mDatas = ArrayList<SettingsEntity.Advertisement>()
var isAutoPlay = true
private var currentPage = 0
private var autoDurationTime = 6000L
private var mRxTimer: Disposable? = null
private var lastX: Float = 0F
private var lastY: Float = 0F
private var startX: Float = 0F
private var startY: Float = 0F
private val mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
private val bannerWidth = DisplayUtils.dip2px(52f)
var onItemClick: ((position: Int) -> Unit)? = null
private lateinit var mIndicatorLayout: LinearLayout
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
init {
initViews()
}
private fun initViews() {
orientation = VERTICAL
mViewPager2 = ViewPager2(context).apply {
layoutParams = ViewGroup.LayoutParams(bannerWidth, bannerWidth)
orientation = ViewPager2.ORIENTATION_HORIZONTAL
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
currentPage = position
slideIndicator(currentPage % mDatas.size)
}
})
}
val recyclerView = mViewPager2.getChildAt(0) as RecyclerView
recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
addView(mViewPager2)
mIndicatorLayout = LinearLayout(context).apply {
orientation = HORIZONTAL
gravity = Gravity.CENTER
val params = LayoutParams(LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(5F))
params.topMargin = DisplayUtils.dip2px(8f)
layoutParams = params
}
addView(mIndicatorLayout)
}
fun start(datas: ArrayList<SettingsEntity.Advertisement>) {
if (datas.isNullOrEmpty()) throw IllegalArgumentException("广告列表不能为空")
val adapter = mViewPager2.adapter
mDatas = datas
if (adapter == null) {
val bannerAdapter = AdBannerAdapter()
mViewPager2.adapter = bannerAdapter
} else {
adapter.notifyDataSetChanged()
}
currentPage = (mViewPager2.adapter as AdBannerAdapter).getActualFirstPositionInCenter()
mViewPager2.setCurrentItem(currentPage, false)
if (mDatas.size > 1) {
addIndicator()
slideIndicator(currentPage % mDatas.size)
autoPlay()
}
}
private fun autoPlay() {
if (isAutoPlay && mDatas.size > 1) {
if (mRxTimer != null && !mRxTimer!!.isDisposed) {
mRxTimer?.dispose()
mRxTimer = null
}
mRxTimer = rxTimer(autoDurationTime) {
slidePage()
}
}
}
private fun slidePage() {
currentPage++
mViewPager2.setCurrentItem(currentPage, true)
}
fun resumePage() {
autoPlay()
}
fun pausePage() {
if (mRxTimer != null && !mRxTimer!!.isDisposed) {
mRxTimer?.dispose()
mRxTimer = null
}
}
private fun addIndicator() {
mIndicatorLayout.removeAllViews()
mDatas.forEach { _ ->
val view = View(context).apply {
background = ContextCompat.getDrawable(context, R.drawable.selector_video_detail_ad_indicator)
val params = LayoutParams(DisplayUtils.dip2px(4F), DisplayUtils.dip2px(4F))
params.leftMargin = DisplayUtils.dip2px(2F)
params.rightMargin = DisplayUtils.dip2px(2F)
layoutParams = params
}
mIndicatorLayout.addView(view)
}
}
private fun slideIndicator(position: Int) {
for (i in 0 until mIndicatorLayout.childCount) {
val childAt = mIndicatorLayout.getChildAt(i)
childAt.isSelected = i == position
}
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
val action = ev.action
if (action == MotionEvent.ACTION_DOWN) {
lastX = ev.rawX
startX = lastX
lastY = ev.rawY
startY = lastY
} else if (action == MotionEvent.ACTION_MOVE) {
lastX = ev.rawX
lastY = ev.rawY
val distanceX = abs(lastX - startX)
val distanceY = abs(lastY - startY)
val disallowIntercept: Boolean
disallowIntercept = if (mViewPager2.orientation == ViewPager2.ORIENTATION_HORIZONTAL) {
distanceX > mTouchSlop && distanceX > distanceY
} else {
distanceY > mTouchSlop && distanceY > distanceX
}
parent.requestDisallowInterceptTouchEvent(disallowIntercept)
} else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
return abs(lastX - startX) > mTouchSlop || abs(lastY - startY) > mTouchSlop
}
return super.onInterceptTouchEvent(ev)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
if (mRxTimer != null && !mRxTimer!!.isDisposed) {
mRxTimer?.dispose()
mRxTimer = null
}
}
fun getAdDatas(): ArrayList<SettingsEntity.Advertisement> {
return mDatas
}
private inner class AdBannerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return object : RecyclerView.ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_ad_banner, parent, false)) {}
}
override fun getItemCount(): Int = if (mDatas.size == 1) mDatas.size else Int.MAX_VALUE
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val ad = mDatas[position % mDatas.size]
val view = holder.itemView as SimpleDraweeView
ImageUtils.display(view,ad.image)
holder.itemView.setOnClickListener {
onItemClick?.invoke(position % mDatas.size)
}
}
fun getActualFirstPositionInCenter(): Int {
if (mDatas.size == 1) return 0
var index = itemCount / 2
if (index % mDatas.size != 0) {
index -= (index % mDatas.size)
}
return index - 1
}
}
}