temp save
This commit is contained in:
285
app/src/main/java/com/chwl/app/ui/widget/GiftComboLayout.kt
Normal file
285
app/src/main/java/com/chwl/app/ui/widget/GiftComboLayout.kt
Normal file
@@ -0,0 +1,285 @@
|
||||
package com.chwl.app.ui.widget
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.util.Pools.Pool
|
||||
import androidx.core.util.Pools.SimplePool
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.cursoradapter.widget.SimpleCursorAdapter.ViewBinder
|
||||
import androidx.room.util.query
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.databinding.ItemGiftComboViewBinding
|
||||
import com.chwl.core.gift.bean.GiftComboInfo
|
||||
import com.opensource.svgaplayer.utils.Pools
|
||||
import java.util.LinkedList
|
||||
|
||||
class GiftComboLayout @JvmOverloads constructor(
|
||||
context: Context?,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes), View.OnClickListener {
|
||||
|
||||
private val showingList = LinkedList<GiftComboInfo>()
|
||||
private val waitingList = LinkedList<GiftComboInfo>()
|
||||
private val comboMap = linkedMapOf<GiftComboInfo, ItemGiftComboViewBinding>()
|
||||
private val cacheView = SimplePool<ItemGiftComboViewBinding>(2)
|
||||
private val inflater = LayoutInflater.from(context)
|
||||
|
||||
private val handle = Handler(Looper.getMainLooper()) {
|
||||
if (it.what == 1) {
|
||||
viewOut(it.obj as? GiftComboInfo, false)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
orientation = VERTICAL
|
||||
|
||||
if(isInEditMode){
|
||||
inflater.inflate(R.layout.item_gift_combo_view, this, true)
|
||||
inflater.inflate(R.layout.item_gift_combo_view, this, true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建
|
||||
*/
|
||||
private fun getComboChildView(): ItemGiftComboViewBinding {
|
||||
val acquire = cacheView.acquire()
|
||||
if (acquire == null){
|
||||
val viewbinding = ItemGiftComboViewBinding.inflate(inflater)
|
||||
viewbinding.root.apply {
|
||||
createViewHolder(this)
|
||||
isVisible = true
|
||||
}
|
||||
cacheView.release(viewbinding)
|
||||
return viewbinding
|
||||
}else{
|
||||
return acquire
|
||||
}
|
||||
}
|
||||
|
||||
fun add(giftComboInfo: GiftComboInfo?) {
|
||||
//没有绑定之前不能添加
|
||||
if (!isAttachedToWindow) {
|
||||
return
|
||||
}
|
||||
if (giftComboInfo == null) {
|
||||
return
|
||||
}
|
||||
|
||||
var addToWaiting = true
|
||||
for (comboInfo in showingList) {
|
||||
if(comboInfo == giftComboInfo){
|
||||
comboInfo.giftNumber = giftComboInfo.giftNumber
|
||||
updateNum(comboInfo)
|
||||
addToWaiting = false
|
||||
}
|
||||
}
|
||||
|
||||
for (comboInfo in waitingList) {
|
||||
if(comboInfo == giftComboInfo){
|
||||
comboInfo.giftNumber = giftComboInfo.giftNumber
|
||||
addToWaiting = false
|
||||
}
|
||||
}
|
||||
|
||||
if(addToWaiting){
|
||||
waitingList.add(giftComboInfo)
|
||||
}
|
||||
|
||||
showNext()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 显示下一个
|
||||
*/
|
||||
private fun showNext() {
|
||||
if(waitingList.isEmpty()){
|
||||
return
|
||||
}
|
||||
|
||||
val comboChildView = getComboChildView()
|
||||
addView(comboChildView.root,0)
|
||||
val giftComboInfo = waitingList.remove()
|
||||
showingList.add(giftComboInfo)
|
||||
|
||||
comboMap[giftComboInfo] = comboChildView
|
||||
showUi(giftComboInfo)
|
||||
viewAnimationIn(comboChildView.root)
|
||||
|
||||
handle.sendMessageDelayed(Message.obtain(handle, 1, giftComboInfo), COMBO_STAY_TIME * 1000L)
|
||||
|
||||
if(showingList.size > MAX_SHOWING){
|
||||
handle.removeMessages(1, showingList[0])
|
||||
viewOut(showingList.remove(), true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 飞入动画
|
||||
*/
|
||||
private fun viewAnimationIn(view: View) {
|
||||
view.alpha = 1f
|
||||
view.startAnimation(AnimationUtils.loadAnimation(context, R.anim.right_to_left))
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除动画
|
||||
*/
|
||||
private fun viewOut(giftComboInfo: GiftComboInfo?, isDirectRemove: Boolean) {
|
||||
giftComboInfo ?: return
|
||||
val comboView = comboMap.remove(giftComboInfo) ?: return
|
||||
|
||||
val runnable = {
|
||||
val viewHolder = getViewHolder(comboView)
|
||||
viewHolder?.clear()
|
||||
if(!isDirectRemove){
|
||||
showingList.remove(giftComboInfo)
|
||||
}
|
||||
removeView(comboView)
|
||||
cacheView.release(comboView)
|
||||
showNext()
|
||||
}
|
||||
|
||||
if(isDirectRemove){
|
||||
comboView.isGone = true
|
||||
comboView.post(runnable)
|
||||
}else{
|
||||
val animOut = AnimationUtils.loadAnimation(context, R.anim.alpha_out)
|
||||
animOut.setAnimationListener(object :SimpleAnimatorListener(){
|
||||
override fun onAnimationEnd(animation: Animation) {
|
||||
comboView.post(runnable)
|
||||
}
|
||||
})
|
||||
comboView.startAnimation(animOut)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新数量
|
||||
*/
|
||||
private fun updateNum(giftComboInfo: GiftComboInfo) {
|
||||
val view = comboMap[giftComboInfo] ?: return
|
||||
|
||||
val viewHolder = getViewHolder(view)
|
||||
viewHolder?.refreshNum(giftComboInfo, true)
|
||||
handle.removeMessages(1, giftComboInfo)
|
||||
handle.sendMessageDelayed(Message.obtain(handle, 1, giftComboInfo), COMBO_STAY_TIME * 1000L)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
if(isInEditMode) return
|
||||
|
||||
}
|
||||
|
||||
override fun onRoomCustomMsg(attach: BaseAttach<*>) {
|
||||
if(attach is NormalGiftAttach){
|
||||
val receiveInfo = attach.data ?: return
|
||||
val comboInfo = GiftComboInfo().apply {
|
||||
senderUid = receiveInfo.uid
|
||||
senderName = receiveInfo.nick
|
||||
senderAvatar = receiveInfo.avatar
|
||||
receiverName = receiveInfo.targetNicks?.getOrNull(0)
|
||||
receiverCount = receiveInfo.receiverCount
|
||||
giftCount = receiveInfo.giftComboCount
|
||||
giftUrl = receiveInfo.gift?.giftUrl
|
||||
}
|
||||
add(comboInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun setNextUi(giftComboInfo: GiftComboInfo) {
|
||||
refreshNum(giftComboInfo)
|
||||
tvNick.text = giftComboInfo.senderName
|
||||
tvReceiverNick.text = giftComboInfo.receiverNick
|
||||
tvNumber.text = "x${giftComboInfo.giftCount}"
|
||||
ivGift.load(giftComboInfo.giftUrl)
|
||||
ivAvatar.load(giftComboInfo.senderAvatar)
|
||||
ivAvatar.tag = giftComboInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于刷新数量
|
||||
*/
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun reSetNum(giftComboInfo: GiftComboInfo, isAnim: Boolean = false) {
|
||||
val num = giftComboInfo.giftCount
|
||||
if(num == 0){
|
||||
tvNumber.isVisible = false
|
||||
return
|
||||
}
|
||||
val old = tvNumber.tag as? Int
|
||||
//兼容上一个比下一个数还要大
|
||||
if (old != null && old > num) {
|
||||
return
|
||||
}
|
||||
tvNumber.isVisible = true
|
||||
tvNumber.tag = num
|
||||
tvNumber.text = "x$num"
|
||||
if (isAnim) {
|
||||
tvNumber.animate().cancel()
|
||||
tvNumber.scaleX = 1.3f
|
||||
tvNumber.scaleY = 1.3f
|
||||
tvNumber.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun reSetUi() {
|
||||
tvNumber.animate().cancel()
|
||||
tvNumber.tag = 0
|
||||
ivAvatar.tag = null
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
handle.removeCallbacksAndMessages(null)
|
||||
}
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 最大显示个数
|
||||
*/
|
||||
const val MAX_SHOWING = 2
|
||||
|
||||
/**
|
||||
* 连击停留时间
|
||||
*/
|
||||
const val COMBO_STAY_TIME = 5
|
||||
}
|
||||
|
||||
// override fun onClick(v: View) {
|
||||
// val giftComboInfo = v.tag as? GiftComboInfo ?: return
|
||||
// val sendUid = giftComboInfo.sentUserid
|
||||
// if (sendUid == 0L) {
|
||||
// return
|
||||
// }
|
||||
//// RoomUserInfoDialog.show(sendUid)
|
||||
// }
|
||||
|
||||
}
|
7
app/src/main/res/anim/right_to_left.xml
Normal file
7
app/src/main/res/anim/right_to_left.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="500"
|
||||
android:fromXDelta="100%p"
|
||||
android:toXDelta="0"/>
|
||||
</set>
|
@@ -257,7 +257,7 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
tools:visibility="visible">
|
||||
tools:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
104
app/src/main/res/layout/item_gift_combo_view.xml
Normal file
104
app/src/main/res/layout/item_gift_combo_view.xml
Normal file
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false"
|
||||
tools:background="@color/appColor"
|
||||
android:layout_marginStart="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/layoutBg"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="38dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/sentUserAvatar"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginStart="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/layoutBg"
|
||||
app:layout_constraintStart_toStartOf="@+id/layoutBg"
|
||||
app:layout_constraintTop_toTopOf="@+id/layoutBg"
|
||||
android:src="@drawable/default_avatar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sentUserName"
|
||||
android:layout_width="66dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="#FFE995"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toEndOf="@+id/sentUserAvatar"
|
||||
app:layout_constraintTop_toTopOf="@+id/sentUserAvatar"
|
||||
app:layout_constraintWidth_max="79dp"
|
||||
tools:text="sentUserName" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sendTips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/send"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="10sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/sentUserAvatar"
|
||||
app:layout_constraintStart_toStartOf="@+id/sentUserName" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/receiverUserName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="2dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="#FFE995"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/sendTips"
|
||||
app:layout_constraintStart_toEndOf="@+id/sendTips"
|
||||
app:layout_constraintWidth_max="60dp"
|
||||
tools:text="receiverUserName" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="end"
|
||||
tools:visibility="visible"
|
||||
app:constraint_referenced_ids="sentUserName,receiverUserName" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/giftImg"
|
||||
android:layout_width="38dp"
|
||||
android:layout_height="38dp"
|
||||
android:layout_marginStart="6dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/sentUserAvatar"
|
||||
app:layout_constraintStart_toEndOf="@+id/barrier"
|
||||
app:layout_constraintTop_toTopOf="@id/sentUserAvatar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/giftComboNumber"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:shadowColor="#ffff9900"
|
||||
android:shadowDx="0"
|
||||
android:shadowDy="1"
|
||||
android:shadowRadius="3.0"
|
||||
android:includeFontPadding="false"
|
||||
android:textStyle="bold"
|
||||
android:textSize="36sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/sentUserAvatar"
|
||||
app:layout_constraintStart_toEndOf="@+id/giftImg"
|
||||
app:layout_constraintTop_toTopOf="@id/sentUserAvatar"
|
||||
tools:text="x1111111" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -124,7 +124,7 @@ public class GiftModel extends BaseModel implements IGiftModel {
|
||||
private void addGiftMessage(CustomAttachment attachment) {
|
||||
giftQueue.add(attachment);
|
||||
if (giftQueue.size() == 1) {
|
||||
handler.sendEmptyMessageDelayed(0, 150);
|
||||
handler.sendEmptyMessageDelayed(0, 200);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,12 @@
|
||||
package com.chwl.core.gift.bean;
|
||||
|
||||
public class GiftComboInfo {
|
||||
public long sentUserid;
|
||||
public String sentUserName;
|
||||
public String sentAvatar;
|
||||
public String giftImgUrl;
|
||||
public int giftNumber;
|
||||
public int receiverNumber;
|
||||
public String receiverUserName;
|
||||
|
||||
}
|
Reference in New Issue
Block a user