feat:头饰支持SVGA(个人资料页、房间个人资料弹窗、动态列表、动态详情、我的头饰列表、公聊厅、房间麦位)

This commit is contained in:
max
2024-07-04 15:19:11 +08:00
parent 495bae0d00
commit 2a0d8f06fa
51 changed files with 627 additions and 778 deletions

View File

@@ -221,7 +221,6 @@ dependencies {
api "com.jzxiang.pickerview:TimePickerDialog:1.0.1"
api "com.github.zyyoona7:EasyPopup:1.0.2"
api "com.github.donkingliang:LabelsView:1.6.5"
api "com.github.yyued:SVGAPlayer-Android:2.6.1"
api "com.ms-square:expandableTextView:0.1.4"
annotationProcessor 'androidx.annotation:annotation:1.6.0'

View File

@@ -947,6 +947,8 @@
android:windowSoftInputMode="adjustPan"
android:name=".ui.feedback.FeedbackActivity"
android:screenOrientation="portrait" />
<activity android:name=".ui.debug.DebugActivity"
android:screenOrientation="portrait"/>
</application>
</manifest>

View File

@@ -42,6 +42,7 @@ import com.alibaba.fastjson.JSONObject;
import com.chwl.app.notify.RoomNotifyManager;
import com.chwl.app.ui.webview.baishun.BaiShunGameWebFragment;
import com.chwl.app.ui.webview.baishun.IBaiShunGameListener;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.monsterhunting.bean.MonsterDataBean;
import com.chwl.core.room.game.bean.BaiShunGameConfig;
import com.chwl.core.support.room.AudioRoomContext;
@@ -177,6 +178,15 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
private static final String TAG = "AVRoomActivity";
private static final int SHOW_RED_DIALOG_MAX = 10;
public static boolean isPKModel = false;
private static SVGAView.SVGACache svgaCache;
public static SVGAView.SVGACache getSvgaCache() {
if (svgaCache == null) {
svgaCache = SVGAView.newCache(20);
}
return svgaCache;
}
/**
* 管理限制进房
*/
@@ -899,6 +909,10 @@ public class AVRoomActivity extends BaseMvpActivity<IAvRoomView, AvRoomPresenter
GiftModel.get().cancelCountDownTimer();
EventBus.getDefault().unregister(this);
DemoCache.saveBoolean("FirstCharge", false);
if (svgaCache != null) {
svgaCache.clear();
}
svgaCache = null;
super.onDestroy();
}

View File

@@ -15,8 +15,12 @@ import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.avroom.activity.AVRoomActivity;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.utils.extension.StringExtensionKt;
import com.coorchice.library.SuperTextView;
import com.example.lib_utils.StringUtils2;
import com.netease.nim.uikit.common.util.string.StringUtil;
import com.opensource.svgaplayer.SVGAImageView;
import com.chwl.app.R;
@@ -145,7 +149,7 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
SVGAImageView ivHalo;
@Nullable
ImageView ivHeadWear;
SVGAView ivHeadWear;
@Nullable
ImageView ivCharmLevelTag;
@@ -171,6 +175,7 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
ivUpImage.setOnClickListener(this);
ivLockImage.setOnClickListener(this);
ivAvatar.setOnClickListener(this);
ivHeadWear.bindCache(AVRoomActivity.getSvgaCache());
}
public void clear() {
@@ -276,6 +281,7 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
private void clearHeadWear() {
if (ivHeadWear == null) return;
ivHeadWear.clearAnimation();
ivHeadWear.stopAnimation();
ivHeadWear.setImageDrawable(null);
ivHeadWear.setTag(R.id.mic_item_head_wear, null);
ivHeadWear.setVisibility(View.GONE);
@@ -299,10 +305,13 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
private void updateNobleView(MicMemberInfo chatRoomMember) {
if (ivHeadWear == null) return;
String headWear = chatRoomMember.getHeadWearUrl();
int headWearType = chatRoomMember.getHeadWearType();
if (TextUtils.isEmpty(headWear)) {
headWear = NobleUtil.getHeadResource(HeadWearInfo.EFFECT, chatRoomMember) != null ?
NobleUtil.getHeadResource(HeadWearInfo.EFFECT, chatRoomMember) :
NobleUtil.getHeadResource(HeadWearInfo.PIC, chatRoomMember);
String type = NobleUtil.getHeadResource(HeadWearInfo.TYPE, chatRoomMember);
headWearType = StringUtils2.INSTANCE.toInt(type);
}
String nobleHeadWear = (String) NobleUtil.getResource(NobleResourceType.KEY_HEAD_WEAR, chatRoomMember);
if (!TextUtils.isEmpty(headWear)) {
@@ -310,7 +319,7 @@ public abstract class BaseMicroViewAdapter extends RecyclerView.Adapter<Recycler
//只有头饰发生改变才更新,防止闪烁
if (!headWear.equals(ivHeadWear.getTag(R.id.mic_item_head_wear))) {
ivHeadWear.setTag(R.id.mic_item_head_wear, headWear);
NobleUtil.loadMicHeadWear(headWear, ivHeadWear, R.id.mic_item_head_wear, headWear);
AvatarHelper.loadAvatarFrame(ivHeadWear, headWear, headWearType);
}
} else if (!TextUtils.isEmpty(nobleHeadWear)) {
// 头饰

View File

@@ -2,7 +2,6 @@ package com.chwl.app.avroom.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -13,8 +12,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.R;
import com.chwl.core.bean.RoomQueueInfo;
import com.chwl.core.manager.AvRoomDataManager;
import com.chwl.library.utils.ResUtil;
/**
* @author xiaoyu

View File

@@ -6,7 +6,6 @@ import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
@@ -14,7 +13,7 @@ import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import com.chwl.core.helper.PathHelper;
import com.chwl.library.utils.PathHelper;
import com.chwl.library.download.DownloadException;
import com.chwl.library.download.DownloadManager;
import com.chwl.library.download.DownloadRequest;

View File

@@ -1,72 +0,0 @@
package com.chwl.app.decoration.adapter;
import android.view.View;
import com.chwl.app.R;
import com.chwl.app.bindadapter.BaseAdapter;
import com.chwl.app.bindadapter.BindingViewHolder;
import com.chwl.app.databinding.ItemHeadWearBinding;
import com.chwl.core.decoration.headwear.bean.HeadWearInfo;
import com.chwl.core.noble.NobleUtil;
import com.chwl.library.utils.ListUtils;
/**
* Created by huangmeng1 on 2018/5/10.
*/
public class HeadWearShopAdapter extends BaseAdapter<HeadWearInfo> {
private int selectPosition;
public int getSelectPosition() {
return selectPosition;
}
public void setSelectPosition(int selectPosition) {
notifyItemChanged(this.selectPosition);
this.selectPosition = selectPosition;
notifyItemChanged(this.selectPosition);
}
public HeadWearShopAdapter(int layoutResId, int brid) {
super(layoutResId, brid);
}
@Override
protected void convert(BindingViewHolder helper, HeadWearInfo item) {
super.convert(helper, item);
ItemHeadWearBinding binding = (ItemHeadWearBinding) helper.getBinding();
binding.llRoot.setSelected(selectPosition == helper.getAdapterPosition());
NobleUtil.loadHeadWears(item.getPic(), binding.ivHeadWear);
binding.setSelectPosition(selectPosition == helper.getAdapterPosition());
if (item.getLabelType() == HeadWearInfo.LABEL_TYPE_NORMAL) {
binding.ivTag.setVisibility(View.GONE);
} else if (HeadWearInfo.LABEL_TYPE_NEW == item.getLabelType()) {
binding.ivTag.setVisibility(View.VISIBLE);
binding.ivTag.setImageResource(R.drawable.ic_mark_new);
} else if (HeadWearInfo.LABEL_TYPE_DISCOUNT == item.getLabelType()) {
binding.ivTag.setVisibility(View.VISIBLE);
binding.ivTag.setImageResource(R.drawable.ic_mark_discount);
} else if (HeadWearInfo.LABEL_TYPE_LIMIT == item.getLabelType()) {
binding.ivTag.setVisibility(View.VISIBLE);
binding.ivTag.setImageResource(R.drawable.ic_mark_limit);
} else if (HeadWearInfo.LABEL_TYPE_EXCLUSIVE == item.getLabelType()) {
binding.ivTag.setVisibility(View.VISIBLE);
binding.ivTag.setImageResource(R.drawable.ic_mark_exclusive);
}
binding.tvHeadName.setText(item.getName() + "");
}
public void setCarInfoHasBeenBought(HeadWearInfo carInfo) {
if (carInfo.getHeadwearId() <= 0 || ListUtils.isListEmpty(mData)) return;
int index = mData.indexOf(carInfo);
if (index == -1) return;
mData.get(index).setStatus(HeadWearInfo.STATUS_IN_USED);
notifyItemChanged(index);
}
}

View File

@@ -6,9 +6,11 @@ import com.chwl.app.R;
import com.chwl.app.bindadapter.BaseAdapter;
import com.chwl.app.bindadapter.BindingViewHolder;
import com.chwl.app.databinding.ItemMyHeadWearBinding;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.core.decoration.headwear.bean.HeadWearInfo;
import com.chwl.core.noble.NobleUtil;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.widget.SVGAView;
/**
* Created by huangmeng1 on 2018/5/11.
@@ -20,11 +22,14 @@ public class MyHeadWearAdapter extends BaseAdapter<HeadWearInfo> {
super(layoutResId, brid);
}
private SVGAView.SVGACache svgaCache = SVGAView.newCache(10);
@Override
protected void convert(BindingViewHolder helper, HeadWearInfo item) {
super.convert(helper, item);
ItemMyHeadWearBinding binding = (ItemMyHeadWearBinding) helper.getBinding();
NobleUtil.loadHeadWears(item.getPic(), binding.ivCarCover);
binding.ivCarCover.bindCache(svgaCache);
AvatarHelper.loadAvatarFrame(binding.ivCarCover, item.getFirstUrl(), item.getType());
helper.addOnClickListener(R.id.tv_used);
if (item.getLabelType() == HeadWearInfo.LABEL_TYPE_NORMAL) {

View File

@@ -3,7 +3,7 @@ package com.chwl.app.support
import androidx.lifecycle.viewModelScope
import com.chwl.app.BuildConfig
import com.chwl.app.base.BaseViewModel
import com.chwl.core.helper.PathHelper
import com.chwl.library.utils.PathHelper
import com.chwl.core.home.model.HomeModel
import com.chwl.library.common.util.SPUtils
import com.chwl.library.download.DownloadException

View File

@@ -0,0 +1,50 @@
package com.chwl.app.ui.debug
import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.databinding.DebugActivityBinding
import com.netease.nim.uikit.StatusBarUtil
class DebugActivity : BaseViewBindingActivity<DebugActivityBinding>() {
override fun init() {
initWhiteTitleBar("调试")
initSVGAList()
}
private fun initSVGAList() {
val adapter = DebugAdapter()
binding.recyclerView.adapter = adapter
// binding.recyclerView.setItemViewCacheSize(-1)
val svgaList = listOf(
"https://image.pekolive.com/花和玫瑰.svga",
"https://image.pekolive.com/firecrown.svga",
"https://image.pekolive.com/ningtangchengbaoqietu.svga",
"https://image.pekolive.com/xunmengfengche.svga",
"https://image.pekolive.com/tonghuaqiyuan1334.svga",
"https://image.pekolive.com/mengquyinhe.svga",
"https://image.pekolive.com/duqinghuashu.svga",
"https://image.pekolive.com/juzhijingling.svga",
"https://image.pekolive.com/3121_aixintouwei.svga",
"https://image.pekolive.com/4051_langmanyewan.svga"
)
val list = ArrayList<String>()
list.addAll(svgaList)
list.addAll(svgaList)
adapter.setNewData(list)
binding.btnRefreshAll.setOnClickListener {
adapter.notifyDataSetChanged()
}
binding.btnRefresh.setOnClickListener {
adapter.notifyItemChanged(5, true)
}
}
override fun needSteepStateBar(): Boolean {
return true
}
override fun setStatusBar() {
super.setStatusBar()
StatusBarUtil.transparencyBar(this)
StatusBarUtil.StatusBarLightMode(this)
}
}

View File

@@ -0,0 +1,47 @@
package com.chwl.app.ui.debug
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.chwl.app.R
import com.chwl.library.widget.SVGAView
import com.example.lib_utils.log.ILog
class DebugAdapter : BaseQuickAdapter<String, BaseViewHolder>(R.layout.debug_item_svga), ILog {
private val svgaCache = SVGAView.newCache(10)
override fun convertPayloads(
helper: BaseViewHolder,
item: String?,
payloads: MutableList<Any>
) {
super.convertPayloads(helper, item, payloads)
logD("convertPayloads holder:${helper.absoluteAdapterPosition} #${helper.hashCode()} SVGAView")
val svgaView = helper.getView<SVGAView>(R.id.svga_view)
svgaView.loadUrl(item)
}
override fun convert(helper: BaseViewHolder, item: String?) {
logD("convert holder:${helper.absoluteAdapterPosition} #${helper.hashCode()} SVGAView")
helper.setText(R.id.tv_name, helper.absoluteAdapterPosition.toString())
val item = getItem(helper.bindingAdapterPosition)
val svgaView = helper.getView<SVGAView>(R.id.svga_view)
svgaView.bindCache(svgaCache)
svgaView.setLogTag(helper.absoluteAdapterPosition.toString())
svgaView.loadUrl(item)
}
override fun onViewAttachedToWindow(holder: BaseViewHolder) {
super.onViewAttachedToWindow(holder)
logD("onViewAttachedToWindow holder:${holder.absoluteAdapterPosition} #${holder.hashCode()} SVGAView")
// val item = getItem(holder.bindingAdapterPosition)
// val svgaView = holder.getView<SVGAView>(R.id.svga_view)
// svgaView.bindCache(SVGAView.newCache(10))
// svgaView.setLogTag(holder.absoluteAdapterPosition.toString())
// svgaView.loadUrl(item)
}
override fun onViewDetachedFromWindow(holder: BaseViewHolder) {
super.onViewDetachedFromWindow(holder)
logD("onViewDetachedFromWindow holder:${holder.absoluteAdapterPosition} #${holder.hashCode()} SVGAView")
}
}

View File

@@ -13,6 +13,7 @@ import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.common.widget.dialog.DialogManager.OkCancelDialogListener
import com.chwl.app.databinding.ActivitySettingBinding
import com.chwl.app.notify.RoomNotifyManager
import com.chwl.app.ui.debug.DebugActivity
import com.chwl.app.ui.im.avtivity.BlackListManageActivity
import com.chwl.app.ui.language.LanguageActivity
import com.chwl.app.ui.login.BindPhoneActivity
@@ -221,6 +222,7 @@ class SettingActivity : BaseViewBindingActivity<ActivitySettingBinding>(), View.
}
private fun debug() {
startActivity(Intent(this, DebugActivity::class.java))
// CommonWebViewActivity.start(this,"https://api.molistar.xyz/molistar/activity/2024-invitationFission/index.html")
// PublicChatRoomMessageActivity.start(this)
// MyDecorationActivity.start(this,0)

View File

@@ -25,8 +25,9 @@ import com.chwl.app.ui.user.adapter.UserInfoTopAlbumAdapter;
import com.chwl.app.ui.user.fragment.UserInfoDataFragment;
import com.chwl.app.ui.user.fragment.UserInfoDynamicFragment;
import com.chwl.app.utils.AppBarStateChangeListener;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.decoration.headwear.bean.HeadWearInfo;
import com.chwl.core.noble.NobleUtil;
import com.example.lib_utils.UiUtils;
import com.google.android.material.appbar.AppBarLayout;
import com.netease.nim.uikit.StatusBarUtil;
@@ -254,6 +255,7 @@ public class UserInfoActivity extends BaseBindingActivity<ActivityUserInfoBindin
mBinding.tbUserInfo.setTitle("");
ivOfficialMask = mBinding.inOfficialMask.findViewById(R.id.iv_official_mask);
tvOfficialMask = mBinding.inOfficialMask.findViewById(R.id.tv_official_mask);
mBinding.ivHeadWear.bindCache(SVGAView.newCache(1));
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -269,8 +271,7 @@ public class UserInfoActivity extends BaseBindingActivity<ActivityUserInfoBindin
ImageLoadUtilsV2.loadImage(mBinding.ivUserHead, userInfo.getAvatar());
HeadWearInfo headWearInfo = userInfo.getUserHeadwear();
if (headWearInfo != null && headWearInfo.getFirstUrl() != null) {
NobleUtil.loadHeadWear(headWearInfo.getFirstUrl(), mBinding.ivHeadWear);
mBinding.ivHeadWear.setVisibility(View.VISIBLE);
AvatarHelper.loadAvatarFrame(mBinding.ivHeadWear, headWearInfo.getFirstUrl(), headWearInfo.getType());
mBinding.ivUserHead.setPadding(0, 0, 0, 0);
mBinding.ivUserHead.setStrokeWidth(0);
} else {

View File

@@ -27,6 +27,8 @@ import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.google.android.flexbox.FlexboxLayout;
import com.netease.nim.uikit.common.util.sys.ScreenUtil;
import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder;
@@ -119,7 +121,7 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
private UserInfo userInfo;
private ImageView closeImage;
private FrameLayout avatarLayout;
private ImageView ivAvatarHeadWear;
private SVGAView ivAvatarHeadWear;
private ImageView avatar;
/**
* 头像高斯模糊背景
@@ -246,6 +248,7 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
inNamePlate = findViewById(R.id.in_nameplate);
ivAvatarHeadWear = findViewById(R.id.iv_avatar_head_wear);
ivAvatarHeadWear.bindCache(AVRoomActivity.getSvgaCache());
ivBadge = findViewById(R.id.iv_badge);
ivBadge.setVisibility(View.GONE);
ivOfficialView = findViewById(R.id.iv_user_official);
@@ -678,9 +681,12 @@ public class UserInfoDialog extends AppCompatDialog implements View.OnClickListe
HeadWearInfo userHeadwear = userInfo.getUserHeadwear();
boolean havaHead = false;
// 设置普通人
if (userHeadwear != null && !TextUtils.isEmpty(userHeadwear.getPic())) {
havaHead = true;
NobleUtil.loadHeadWear(userHeadwear.getEffect() != null ? userHeadwear.getEffect() : userHeadwear.getPic(), ivAvatarHeadWear);
if (userHeadwear != null) {
String avatarFrame = userHeadwear.getFirstUrl();
if (!TextUtils.isEmpty(avatarFrame)) {
havaHead = true;
AvatarHelper.loadAvatarFrame(ivAvatarHeadWear, avatarFrame, userHeadwear.getType());
}
}
if (nobleInfo == null || TextUtils.isEmpty(nobleInfo.getCardBg())) {

View File

@@ -0,0 +1,42 @@
package com.chwl.app.utils
import androidx.core.view.isVisible
import com.chwl.app.R
import com.chwl.library.widget.SVGAView
import com.chwl.core.decoration.headwear.bean.HeadWearInfo
import com.chwl.core.noble.NobleUtil
object AvatarHelper {
/**
* 加载头饰
*/
@JvmStatic
fun loadAvatarFrame(view: SVGAView, headWearInfo: HeadWearInfo?) {
loadAvatarFrame(view, headWearInfo?.firstUrl, headWearInfo?.type ?: 0)
}
/**
* 加载头饰
* @param type 头饰类型 0:图片、1:SVGA
*/
@JvmStatic
fun loadAvatarFrame(view: SVGAView, url: String?, type: Int) {
view.setTag(R.id.head_wear, url)
if (url.isNullOrEmpty()) {
view.clearAnimation()
view.stopAnimation()
view.setImageDrawable(null)
return
}
if (type == 1) {
view.clearAnimation()
view.loadUrl(url)
view.isVisible = true
} else {
view.stopAnimation()
NobleUtil.loadHeadWear(url, view, R.id.head_wear, url)
view.isVisible = true
}
}
}

View File

@@ -80,8 +80,9 @@
app:strokeColor="@color/white"
app:strokeWidth="@dimen/dp_1" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:scaleType="centerCrop"
android:layout_width="@dimen/dp_97"
android:layout_height="@dimen/dp_97"
app:layout_constraintBottom_toBottomOf="@id/iv_user_head"

View File

@@ -0,0 +1,45 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.chwl.app.base.TitleBar
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_30"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:overScrollMode="never"
android:scrollbars="none"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/layout_bottom"
app:layout_constraintTop_toBottomOf="@id/title_bar" />
<LinearLayout
android:id="@+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<Button
android:id="@+id/btn_refresh_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="REFRESH-ALL" />
<Button
android:id="@+id/btn_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="REFRESH" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,29 @@
<?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"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_80"
android:layout_marginVertical="@dimen/dp_2">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
android:textSize="@dimen/dp_18"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.chwl.library.widget.SVGAView
android:id="@+id/svga_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/dp_15"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toEndOf="@id/tv_name"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -66,7 +66,7 @@
android:layout_height="55dp"
android:layout_gravity="center" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_avatar_head_wear"
android:layout_width="73dp"
android:layout_height="73dp"

View File

@@ -49,7 +49,7 @@
android:visibility="invisible"
tools:visibility="visible" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -56,7 +56,7 @@
android:visibility="invisible"
tools:visibility="gone" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="headWearInfo"
type="com.chwl.core.decoration.headwear.bean.HeadWearInfo" />
<variable
name="select_position"
type="Boolean" />
</data>
<LinearLayout
android:id="@+id/ll_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/bg_item_select">
<RelativeLayout
android:id="@+id/rl_head_wear"
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="106dp"
android:layout_gravity="center_horizontal">
<ImageView
android:id="@+id/iv_head_wear"
android:layout_width="88dp"
android:layout_height="88dp"
android:layout_marginTop="6dp"
android:layout_marginStart="11dp"
android:layout_marginEnd="11dp"
android:layout_centerInParent="true" />
<ImageView
android:id="@+id/iv_tag"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentTop="true"
tools:src="@drawable/ic_mark_limit"/>
</RelativeLayout>
<TextView
android:id="@+id/tv_head_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:layout_marginBottom="14dp"
android:textColor="@{select_position?@color/appColor:@color/color_666666}"
android:textSize="14sp" />
</LinearLayout>
</layout>

View File

@@ -97,7 +97,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="0dp"
android:layout_height="0dp"

View File

@@ -97,7 +97,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="0dp"
android:layout_height="0dp"

View File

@@ -73,7 +73,7 @@
tools:visibility="visible" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="0dp"
android:layout_height="0dp"
@@ -92,6 +92,10 @@
android:gravity="center"
android:includeFontPadding="false"
android:text="@string/layout_item_micro_game_01"
app:autoSizeMaxTextSize="10dp"
app:autoSizeMinTextSize="5dp"
app:autoSizeStepGranularity="1px"
app:autoSizeTextType="uniform"
android:textColor="@color/white"
android:textSize="10dp"
android:visibility="gone"

View File

@@ -22,7 +22,7 @@
android:layout_height="60dp"
android:layout_gravity="center" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="52.8dp"
android:layout_height="52.8dp"

View File

@@ -23,7 +23,7 @@
android:background="@drawable/bg_secondary_radius_15"
android:gravity="center">
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_car_cover"
android:layout_width="63dp"
android:layout_height="63dp"

View File

@@ -48,7 +48,7 @@
android:visibility="invisible"
tools:visibility="gone" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -52,7 +52,7 @@
android:visibility="invisible"
tools:visibility="gone" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
tools:visibility="gone"
android:layout_width="match_parent"

View File

@@ -13,6 +13,8 @@
<item type="id" name="mic_item_head_wear" />
<item type="id" name="head_wear" />
<item type="id" name="guide_view" />
<item name="animator" type="id" />

View File

@@ -1,307 +0,0 @@
package com.chwl.app.community.dynamic.adapter;
import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.chwl.app.photo.BigPhotoActivity;
import com.chwl.app.photo.PagerOption;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nim.uikit.support.glide.GlideApp;
import com.chwl.app.R;
import com.chwl.app.UIHelper;
import com.chwl.app.community.dynamic.view.DynamicDetailActivity;
import com.chwl.app.community.helper.CalcSize;
import com.chwl.app.community.helper.DynamicUiHelper;
import com.chwl.app.community.helper.ImageUiHelper;
import com.chwl.app.photo.DynamicImageAdapter;
import com.chwl.app.community.utils.ObjectTypeHelper;
import com.chwl.app.community.utils.TopicUpTextWrapper;
import com.chwl.app.community.widget.DynamicNickDetailWidget;
import com.chwl.app.community.widget.ExpandableTextView;
import com.chwl.app.community.widget.TopicLabelWidget;
import com.chwl.app.ui.utils.ImageLoadUtilsV2;
import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil;
import com.chwl.app.utils.NamePlateHelper;
import com.chwl.app.utils.TimeUiUtils;
import com.chwl.core.community.bean.DynamicMedia;
import com.chwl.core.community.bean.WorldDynamicBean;
import com.chwl.core.community.dynamic.DynamicModel;
import com.chwl.core.noble.NobleUtil;
import com.chwl.core.utils.net.DontWarnObserver;
import com.chwl.core.utils.net.RxHelper;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.utils.SingleToastUtil;
import java.util.List;
/**
* create by lvzebiao @2019/11/13
*/
public class WorldDynamicAdapter extends BaseQuickAdapter<WorldDynamicBean, BaseViewHolder> {
private SparseBooleanArray mCollapsedStatus = new SparseBooleanArray();
private SparseIntArray mCollapsedHeightStatus = new SparseIntArray(2);
private Context context;
private long worldId;
private int iconWidth;
private int iconHeight;
/**
* 有文本的图片布局的top-margin
*/
private int imageTmHasText;
/**
* 无文本的图片布局的top-margin
*/
private int imageTmNoText;
/**
* 单图情况下的边界
*/
private int imageBorder;
/**
* 图片的边界值
*/
private int divider;
public WorldDynamicAdapter(Context context, long worldId) {
super(R.layout.item_world_dynamic);
this.context = context;
this.worldId = worldId;
iconWidth = UIUtil.dip2px(context, 32);
iconHeight = UIUtil.dip2px(context, 15);
imageTmHasText = UIUtil.dip2px(context, 15f);
imageTmNoText = UIUtil.dip2px(context, 7.5f);
//0.68
imageBorder = UIUtil.getScreenWidth(context) * ImageUiHelper.BORDER_MIN / ImageUiHelper.BORDER_MAX;
divider = UIUtil.dip2px(context, 10);
}
@Override
protected void convert(BaseViewHolder helper, WorldDynamicBean item) {
//这个值有没有文本UI部分改变图片部分的margin
boolean noTextUi = TextUtils.isEmpty(item.getContent());
helper.setText(R.id.tv_nick, item.getNick());
RecyclerView rvImage = helper.getView(R.id.rv_image);
List<DynamicMedia> dynamicMediaList = item.getDynamicResList();
if (item.getType() == WorldDynamicBean.TYPE_IMAGE
&& dynamicMediaList != null && dynamicMediaList.size() > 0) {
rvImage.setVisibility(View.VISIBLE);
initRecyclerView(rvImage, dynamicMediaList, noTextUi);
} else {
rvImage.setVisibility(View.GONE);
}
//头饰 贵族头饰
ImageView ivHeadWear = helper.getView(R.id.iv_head_wear);
GlideApp.with(ivHeadWear.getContext()).clear(ivHeadWear);
String headwearPic = item.getHeadwearPic();
String micDecorate = item.getMicDecorate();
if (!TextUtils.isEmpty(headwearPic)) {
NobleUtil.loadHeadWear(headwearPic, ivHeadWear);
} else if (!TextUtils.isEmpty(micDecorate)) {
NobleUtil.loadResource(micDecorate, ivHeadWear);
} else {
ivHeadWear.setImageDrawable(null);
}
//头像
ImageLoadUtilsV2.loadImage(helper.getView(R.id.iv_avatar), item.getAvatar());
DynamicNickDetailWidget widget = helper.getView(R.id.widget_nick_detail);
widget.setData(item);
View inOfficialMask = helper.getView(R.id.in_official_mask);
NamePlateHelper.INSTANCE.load(inOfficialMask, inOfficialMask.findViewById(R.id.tv_official_mask), inOfficialMask.findViewById(R.id.iv_official_mask), item.getNameplateWord(), item.getNameplatePic(), item.isCustomWord());
//时间
final String time = TimeUiUtils.getDynamicUi(item.getPublishTime());
helper.setGone(R.id.tv_time, !TextUtils.isEmpty(time));
helper.setText(R.id.tv_time, time);
ExpandableTextView etvContent = helper.getView(R.id.etv_content);
etvContent.setEventType(1);
if (noTextUi && item.getTopicTop() == 0) {
etvContent.setVisibility(View.GONE);
} else {
etvContent.setVisibility(View.VISIBLE);
CharSequence formatText = DynamicUiHelper.formatFirstDynamicContent(
item, etvContent.mTv, iconWidth, iconHeight);
if (item.getTopicTop() == 1) {
//置顶
formatText = TopicUpTextWrapper.INSTANCE.wrapUp(formatText, context);
}
etvContent.setText(formatText, mCollapsedStatus, helper.getAdapterPosition(), mCollapsedHeightStatus);
}
//标签
final List<String> labels = item.getLabelList();
if (labels != null) {
((TopicLabelWidget) helper.getView(R.id.topicView)).setLabels(labels);
}
final String worldName = item.getWorldName();
helper.setText(R.id.tv_mini_world_name, "#" + worldName);
helper.setGone(R.id.tv_mini_world_name, !TextUtils.isEmpty(worldName));
helper.setGone(R.id.space_view, !TextUtils.isEmpty(time) || !TextUtils.isEmpty(worldName));
//评论
setCommentCount(helper, item.getCommentCount());
//点赞
setLikeCount(helper, item.getLikeCount(), item.isLike(), false);
LinearLayout llLike = helper.getView(R.id.ll_like);
llLike.setEnabled(true);
llLike.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
llLike.setEnabled(false);
int status = item.isLike() ? 0 : 1;
DynamicModel.get().like(worldId, item.getDynamicId(), item.getUid(), status, 1)
.compose(RxHelper.bindContext(context))
.subscribe(new DontWarnObserver<String>() {
@Override
public void accept(String s, String error) {
super.accept(s, error);
llLike.setEnabled(true);
if (error != null) {
SingleToastUtil.showToast(error);
} else {
LogUtil.print(ResUtil.getString(R.string.dynamic_adapter_worlddynamicadapter_01));
if (status == 1) {
item.setLikeCount(item.getLikeCount() + 1);
} else {
item.setLikeCount(item.getLikeCount() - 1);
}
item.setLike(status == 1);
setLikeCount(helper, item.getLikeCount(), item.isLike(), true);
}
}
});
}
});
//评论
helper.getView(R.id.ll_comment).setOnClickListener(v -> {
DynamicDetailActivity.start(context, item.getDynamicId(), worldId,
helper.getAdapterPosition(), true, 1);
}
);
View.OnClickListener toDetailListener = v ->
DynamicDetailActivity.start(context, item.getDynamicId(), worldId,
helper.getAdapterPosition(), false, 1);
if (etvContent.mTv != null) {
etvContent.mTv.setOnClickListener(toDetailListener);
}
//跳转去详情
helper.itemView.setOnClickListener(toDetailListener);
helper.addOnClickListener(R.id.iv_more)
.addOnClickListener(R.id.ll_share);
View.OnClickListener userInfoActClick = v -> UIHelper.showUserInfoAct(context, item.getUid());
helper.getView(R.id.iv_avatar).setOnClickListener(userInfoActClick);
helper.getView(R.id.widget_nick_detail).setOnClickListener(userInfoActClick);
}
private void setLikeCount(BaseViewHolder helper, int likeCount, boolean isLike, boolean isAnim) {
TextView tvLike = helper.getView(R.id.tv_like);
String likeCountStr;
if (likeCount < 0) {
likeCountStr = "0";
} else if (likeCount >= 1000) {
likeCountStr = "999+";
} else {
likeCountStr = String.valueOf(likeCount);
}
tvLike.setText(likeCountStr);
ImageView ivLikeAnim = helper.getView(R.id.iv_like_pic);
if (isLike) {
// if (isAnim) {
// AnimationDrawable drawable = (AnimationDrawable) context.getResources()
// .getDrawable(R.drawable.anim_list_dy_like);
// ivLikeAnim.setImageDrawable(drawable);
// drawable.stop();
// drawable.start();
// } else {
ivLikeAnim.setImageResource(R.drawable.icon_dy_list_like);
// }
} else {
ivLikeAnim.setImageResource(R.drawable.icon_dy_list_like_false);
}
}
private void initRecyclerView(RecyclerView rvImage, List<DynamicMedia> imageUrl, boolean noTextUi) {
if (imageUrl == null) {
return;
}
CalcSize calcSize = new CalcSize(imageBorder);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) rvImage.getLayoutParams();
if (imageUrl.size() > 1) {
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
} else {
//单图的情况,按比例显示
DynamicMedia media = null;
if (imageUrl.size() > 0) {
media = imageUrl.get(0);
}
if (media == null) {
return;
}
calcSize = ImageUiHelper.calcImage(media, imageBorder);
params.width = calcSize.width + divider;
params.height = calcSize.height + divider;
}
if (noTextUi) {
params.topMargin = imageTmNoText;
} else {
params.topMargin = imageTmHasText;
}
rvImage.setLayoutParams(params);
rvImage.setNestedScrollingEnabled(false);
rvImage.setLayoutManager(new GridLayoutManager(mContext, imageUrl.size() > 2 ? 3 : imageUrl.size()));
DynamicImageAdapter adapter = new DynamicImageAdapter(R.layout.item_dynamic_image, imageUrl);
adapter.setSingleImageHeight(calcSize.height);
adapter.setOnItemClickListener((adapter1, view, position) -> {
PagerOption option = new PagerOption().setSave(true);
BigPhotoActivity.start((Activity) mContext, ObjectTypeHelper.mediaToCustomList(imageUrl),
position, option);
}
);
rvImage.setAdapter(adapter);
}
private void setCommentCount(BaseViewHolder helper, int commentCount) {
TextView tvComment = helper.getView(R.id.tv_comment);
String commentCountStr;
if (commentCount < 0) {
commentCountStr = "0";
} else if (commentCount >= 1000) {
commentCountStr = "999+";
} else {
commentCountStr = String.valueOf(commentCount);
}
tvComment.setText(commentCountStr);
}
}

View File

@@ -23,6 +23,8 @@ import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.photo.BigPhotoActivity;
import com.chwl.app.photo.PagerOption;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.XConstants;
import com.chwl.core.utils.CoreTextUtils;
import com.coorchice.library.utils.LogUtils;
@@ -97,7 +99,7 @@ public class DynamicDetailActivity extends BaseViewBindingActivity<ActivityDynam
private final static String EXTRA_LIST_POSITION = "extra_list_position";
CircleImageView ivAvatar;
ImageView ivHeadWear;
SVGAView ivHeadWear;
DynamicNickDetailWidget widgetNickDetail;
TextView tvTime;
ImageView ivMore;
@@ -682,11 +684,12 @@ public class DynamicDetailActivity extends BaseViewBindingActivity<ActivityDynam
//头饰 贵族头饰
String headwearEffect = bean.getHeadwearEffect();
String headwearPic = bean.getHeadwearPic();
int headwearType = bean.getHeadwearType();
String micDecorate = bean.getMicDecorate();
if (!TextUtils.isEmpty(headwearEffect)) {
NobleUtil.loadHeadWear(headwearEffect, ivHeadWear);
AvatarHelper.loadAvatarFrame(ivHeadWear, headwearEffect, headwearType);
} else if (!TextUtils.isEmpty(headwearPic)) {
NobleUtil.loadHeadWear(headwearPic, ivHeadWear);
AvatarHelper.loadAvatarFrame(ivHeadWear, headwearPic, headwearType);
} else if (!TextUtils.isEmpty(micDecorate)) {
NobleUtil.loadResource(micDecorate, ivHeadWear);
} else {

View File

@@ -4,15 +4,14 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.viewpager.widget.ViewPager;
import com.chwl.app.base.BaseFragment;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.XConstants;
import com.trello.rxlifecycle3.android.FragmentEvent;
import com.chwl.app.R;
@@ -72,6 +71,8 @@ public class SquareDynamicFragment extends BaseFragment {
private int squareType;
private SVGAView.SVGACache svgaCache;
public static SquareDynamicFragment newInstance(int type) {
SquareDynamicFragment fragment = new SquareDynamicFragment();
Bundle bundle = new Bundle();
@@ -106,7 +107,7 @@ public class SquareDynamicFragment extends BaseFragment {
squareType = bundle.getInt(EXTRA_SQUARE_TYPE, SquareFragment.TAB_TYPE_RECOMMEND);
}
recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
adapter = new SquareDynamicAdapter(getActivity());
adapter = new SquareDynamicAdapter(getActivity(), svgaCache);
recyclerView.setAdapter(adapter);
adapter.setPreLoadNumber(2);
adapter.setHeaderAndEmpty(true);
@@ -174,6 +175,10 @@ public class SquareDynamicFragment extends BaseFragment {
loadData(true);
}
public void setSvgaCache(SVGAView.SVGACache svgaCache) {
this.svgaCache = svgaCache;
}
private void loadData(boolean isRefresh) {
if (isRefresh) {
nextDynamicId = null;

View File

@@ -26,6 +26,7 @@ import com.chwl.app.ui.user.adapter.ContactsIndicatorAdapter;
import com.chwl.app.ui.widget.magicindicator.MagicIndicator;
import com.chwl.app.ui.widget.magicindicator.ViewPagerHelper;
import com.chwl.app.ui.widget.magicindicator.buildins.commonnavigator.CommonNavigator;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.auth.AuthModel;
import com.chwl.core.community.event.UnReadCountEvent;
import com.chwl.core.home.model.HomeModel;
@@ -63,6 +64,8 @@ public class SquareFragment extends BaseFragment implements ContactsIndicatorAda
private FrameLayout flContactList;
private View tvCommunityUnread;
private SVGAView.SVGACache svgaCache = SVGAView.newCache(10);
public static SquareFragment newInstance() {
return new SquareFragment();
}
@@ -96,7 +99,9 @@ public class SquareFragment extends BaseFragment implements ContactsIndicatorAda
} else if (integer == TAB_TYPE_NEW) {
tagList.add(getResources().getString(R.string.dys_tab_new));
}
fragmentList.add(SquareDynamicFragment.newInstance(integer));
SquareDynamicFragment fragment = SquareDynamicFragment.newInstance(integer);
fragment.setSvgaCache(svgaCache);
fragmentList.add(fragment);
}
getUnReadCount();
@@ -187,6 +192,7 @@ public class SquareFragment extends BaseFragment implements ContactsIndicatorAda
public void onDestroyView() {
super.onDestroyView();
EventBus.getDefault().unregister(this);
svgaCache.clear();
}
}

View File

@@ -5,12 +5,15 @@ import android.text.TextUtils;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nim.uikit.support.glide.GlideApp;
import com.chwl.app.R;
@@ -44,6 +47,7 @@ public class SquareDynamicAdapter extends BaseQuickAdapter<WorldDynamicBean, Bas
private SparseIntArray mCollapsedHeightStatus = new SparseIntArray(2);
private Context context;
private SVGAView.SVGACache svgaCache;
private int iconWidth;
@@ -65,9 +69,10 @@ public class SquareDynamicAdapter extends BaseQuickAdapter<WorldDynamicBean, Bas
private int rvWidth;
public SquareDynamicAdapter(Context context) {
public SquareDynamicAdapter(Context context, SVGAView.SVGACache svgaCache) {
super(R.layout.item_square_dynamic);
this.context = context;
this.svgaCache = svgaCache;
iconWidth = UIUtil.dip2px(context, 32);
iconHeight = UIUtil.dip2px(context, 15);
imageTmHasText = UIUtil.dip2px(context, 12f);
@@ -78,6 +83,14 @@ public class SquareDynamicAdapter extends BaseQuickAdapter<WorldDynamicBean, Bas
rvWidth = screenWidth - UIUtil.dip2px(context, 86);
}
@Override
protected BaseViewHolder onCreateDefViewHolder(ViewGroup parent, int viewType) {
BaseViewHolder holder = super.onCreateDefViewHolder(parent, viewType);
SVGAView ivHeadWear = holder.getView(R.id.iv_head_wear);
ivHeadWear.bindCache(svgaCache);
return holder;
}
@Override
protected void convert(BaseViewHolder helper, WorldDynamicBean item) {
//这个值有没有文本UI部分改变图片部分的margin
@@ -90,10 +103,11 @@ public class SquareDynamicAdapter extends BaseQuickAdapter<WorldDynamicBean, Bas
widgetImage.setData(item, noTextUi ? imageTmNoText : imageTmHasText);
//头饰 贵族头饰
ImageView ivHeadWear = helper.getView(R.id.iv_head_wear);
SVGAView ivHeadWear = helper.getView(R.id.iv_head_wear);
GlideApp.with(ivHeadWear.getContext()).clear(ivHeadWear);
String headwearEffect = item.getHeadwearEffect();
String headwearPic = item.getHeadwearPic();
int headwearType = item.getHeadwearType();
String micDecorate = item.getMicDecorate();
if (TextUtils.isEmpty(headwearEffect) && TextUtils.isEmpty(headwearPic) && TextUtils.isEmpty(micDecorate)) {
ivHeadWear.setVisibility(View.GONE);
@@ -102,9 +116,9 @@ public class SquareDynamicAdapter extends BaseQuickAdapter<WorldDynamicBean, Bas
}
if (!TextUtils.isEmpty(headwearEffect)) {
NobleUtil.loadHeadWear(headwearEffect, ivHeadWear);
AvatarHelper.loadAvatarFrame(ivHeadWear, headwearEffect, headwearType);
} else if (!TextUtils.isEmpty(headwearPic)) {
NobleUtil.loadHeadWear(headwearPic, ivHeadWear);
AvatarHelper.loadAvatarFrame(ivHeadWear, headwearPic, headwearType);
} else if (!TextUtils.isEmpty(micDecorate)) {
NobleUtil.loadResource(micDecorate, ivHeadWear);
} else {

View File

@@ -23,7 +23,7 @@
app:layout_constraintTop_toTopOf="@+id/iv_head_wear"
tools:src="@drawable/default_cover" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="@dimen/dp_59"
android:layout_height="@dimen/dp_59"

View File

@@ -30,7 +30,7 @@
android:layout_height="@dimen/dp_45"
android:layout_gravity="center" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/iv_head_wear"
android:layout_width="@dimen/dp_59"
android:layout_height="@dimen/dp_59"

View File

@@ -1,282 +0,0 @@
<?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="wrap_content"
android:paddingBottom="@dimen/dp_8"
android:background="@drawable/bg_corner_shadow_12"
android:orientation="vertical">
<View
android:id="@+id/view_top_line"
android:layout_width="match_parent"
android:layout_height="5dp"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_user_info"
android:layout_marginStart="@dimen/dp_12"
android:layout_width="match_parent"
android:layout_marginTop="@dimen/dp_10"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/view_top_line">
<com.chwl.app.community.widget.TopicLabelWidget
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/topicView"
app:layout_constraintTop_toTopOf="@id/widget_nick_detail"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="@dimen/dp_9"
/>
<FrameLayout
android:id="@+id/fl_avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.chwl.app.common.widget.CircleImageView
android:id="@+id/iv_avatar"
android:layout_width="@dimen/dp_40"
android:layout_height="@dimen/dp_40"
android:layout_gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_head_wear"
android:layout_width="60dp"
android:layout_height="60dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent" />
</FrameLayout>
<com.chwl.app.community.widget.DynamicNickDetailWidget
android:id="@+id/widget_nick_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_15"
app:layout_constraintBottom_toBottomOf="@id/fl_avatar"
app:layout_constraintStart_toEndOf="@id/fl_avatar"
app:layout_constraintTop_toTopOf="@id/fl_avatar" />
<ImageView
android:id="@+id/iv_in_room"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:src="@drawable/ic_dy_square_in_room"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/widget_nick_detail"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="@dimen/dp_9"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:id="@+id/view_avatar_right"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="56dp"
app:layout_constraintBottom_toBottomOf="@id/cl_user_info"
app:layout_constraintStart_toStartOf="@id/cl_user_info"
app:layout_constraintTop_toBottomOf="@id/cl_user_info" />
<com.chwl.app.community.widget.ExpandableTextView
android:id="@+id/etv_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_6"
android:layout_marginEnd="@dimen/dp_30"
android:orientation="vertical"
app:animAlphaStart="1"
app:collapseIndicator="@string/collapse"
app:expandIndicator="@string/expand"
app:expandToggleOnTextClick="false"
app:expandToggleType="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/cl_user_info"
app:layout_constraintTop_toBottomOf="@id/view_avatar_right"
app:maxCollapsedLines="6">
<com.netease.nim.uikit.business.session.widget.NimEmojiTextView
android:id="@+id/expandable_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="4dp"
android:textColor="@color/text_normal_c6c6e9"
android:textSize="15sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/expand_collapse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/expand"
android:textColor="@color/color_34A7FF"
android:textSize="15sp" />
</LinearLayout>
</com.chwl.app.community.widget.ExpandableTextView>
<com.chwl.app.community.widget.GridImageWidget
android:id="@+id/widget_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_12"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="@dimen/dp_10"
app:layout_constraintStart_toStartOf="@id/cl_user_info"
app:layout_constraintTop_toBottomOf="@id/etv_content"
tools:layout_height="100dp" />
<Space
android:id="@+id/space_view"
android:layout_height="24dp"
android:layout_width="1dp"
android:layout_marginTop="@dimen/dp_8"
app:layout_constraintStart_toStartOf="@id/cl_user_info"
app:layout_constraintTop_toBottomOf="@id/widget_image"
/>
<TextView
android:id="@+id/tv_mini_world_name"
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="@id/space_view"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:background="@drawable/bg_round_1affbc51_9_4"
app:layout_constraintTop_toTopOf="@id/space_view"
app:layout_constraintStart_toStartOf="@id/space_view"
android:ellipsize="end"
android:gravity="center"
android:maxWidth="150dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:singleLine="true"
android:textColor="#FFBC51"
android:textSize="@dimen/sp_12"
tools:text="@string/layout_item_world_dynamic_01" />
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:id="@+id/tv_time"
android:gravity="center"
android:textSize="@dimen/sp_12"
android:textColor="@color/color_666666"
app:layout_constraintStart_toEndOf="@id/tv_mini_world_name"
app:layout_constraintTop_toTopOf="@id/space_view"
app:layout_constraintBottom_toBottomOf="@id/space_view"
tools:text = "09:10"
android:layout_marginStart="@dimen/dp_12"
/>
<RelativeLayout
android:id="@+id/rl_option"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_8"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/cl_user_info"
app:layout_constraintTop_toBottomOf="@id/space_view">
<LinearLayout
android:id="@+id/ll_like"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_like_pic"
android:layout_width="@dimen/dp_22"
android:layout_height="@dimen/dp_22"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_square_dynamic_like_normal" />
<TextView
android:id="@+id/tv_like"
android:layout_width="0dp"
android:layout_height="@dimen/dp_24"
android:layout_marginStart="2.5dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:textColor="@color/color_666666"
android:textSize="@dimen/sp_12"
tools:text="0123" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_comment"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/ll_like"
android:orientation="horizontal"
android:paddingEnd="0dp">
<ImageView
android:id="@+id/iv_comment_pic"
android:layout_width="@dimen/dp_22"
android:layout_height="@dimen/dp_22"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_square_dynamic_comment" />
<TextView
android:id="@+id/tv_comment"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_24"
android:layout_marginStart="2.5dp"
android:gravity="center_vertical"
android:textColor="@color/color_666666"
android:textSize="@dimen/sp_12"
tools:text="0" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_share"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/ll_comment"
android:visibility="gone"
android:paddingStart="@dimen/dp_5"
android:paddingEnd="0dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_square_dynamic_share" />
</LinearLayout>
<ImageView
android:id="@+id/iv_more"
android:layout_width="@dimen/dp_22"
android:layout_height="@dimen/dp_22"
android:scaleType="centerInside"
android:src="@drawable/icon_square_dynamic_more"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/dp_12" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,19 +1,20 @@
package com.chwl.app.public_chat.core;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import com.chwl.app.public_chat.core.viewholder.ChatRoomMessageViewHolderBase;
import com.chwl.app.public_chat.core.viewholder.ChatRoomMessageViewHolderFactory;
import com.chwl.library.utils.LogUtil;
import com.chwl.library.widget.SVGAView;
import com.netease.nim.uikit.R;
import com.netease.nim.uikit.business.session.module.Container;
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter;
import com.netease.nim.uikit.common.ui.recyclerview.holder.NIMBaseViewHolder;
import com.netease.nim.uikit.common.ui.recyclerview.holder.PublicChatRoomNimBaseViewHolder;
import com.netease.nim.uikit.impl.NimUIKitImpl;
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.IMMessage;
import java.util.HashMap;
@@ -25,7 +26,7 @@ import java.util.Set;
/**
* Created by huangjun on 2016/12/21.
*/
public class ChatRoomMessageAdapter extends BaseMultiItemFetchLoadAdapter<ChatRoomMessage, NIMBaseViewHolder> {
public class ChatRoomMessageAdapter extends BaseMultiItemFetchLoadAdapter<ChatRoomMessage, PublicChatRoomNimBaseViewHolder> {
private Map<Class<? extends ChatRoomMessageViewHolderBase>, Integer> holder2ViewType;
@@ -34,6 +35,8 @@ public class ChatRoomMessageAdapter extends BaseMultiItemFetchLoadAdapter<ChatRo
private String messageId;
private Container container;
private SVGAView.SVGACache svgaCache = SVGAView.newCache(20);
public ChatRoomMessageAdapter(RecyclerView recyclerView, List<ChatRoomMessage> data, Container container) {
super(recyclerView, data);
@@ -53,6 +56,11 @@ public class ChatRoomMessageAdapter extends BaseMultiItemFetchLoadAdapter<ChatRo
this.container = container;
}
@Override
protected PublicChatRoomNimBaseViewHolder createBaseViewHolder(View view) {
return new PublicChatRoomNimBaseViewHolder(view, svgaCache);
}
@Override
protected int getViewType(ChatRoomMessage message) {
try {

View File

@@ -18,16 +18,20 @@ import androidx.core.util.Consumer;
import com.chwl.app.public_chat.core.ChatRoomMessageAdapter;
import com.chwl.app.ui.utils.ImageLoadUtils;
import com.chwl.app.ui.widget.TextSpannableBuilder;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.core.decoration.headwear.bean.HeadWearInfo;
import com.chwl.core.level.UserLevelResourceType;
import com.chwl.core.noble.NobleUtil;
import com.chwl.core.user.bean.UserInfo;
import com.chwl.library.widget.SVGAView;
import com.example.lib_utils.StringUtils2;
import com.example.lib_utils.UiUtils;
import com.netease.nim.uikit.R;
import com.netease.nim.uikit.api.model.team.AvatarClickListener;
import com.netease.nim.uikit.common.ui.imageview.HeadImageView;
import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter;
import com.netease.nim.uikit.common.ui.recyclerview.holder.NIMBaseViewHolder;
import com.netease.nim.uikit.common.ui.recyclerview.holder.PublicChatRoomNimBaseViewHolder;
import com.netease.nim.uikit.common.ui.recyclerview.holder.RecyclerViewHolder;
import com.netease.nim.uikit.common.util.sys.TimeUtil;
import com.netease.nim.uikit.impl.NimUIKitImpl;
@@ -43,7 +47,7 @@ import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum;
* 具体的消息展示项可继承该基类,然后完成具体消息内容展示即可。
*/
@Keep
public abstract class ChatRoomMessageViewHolderBase extends RecyclerViewHolder<BaseMultiItemFetchLoadAdapter, NIMBaseViewHolder, ChatRoomMessage> {
public abstract class ChatRoomMessageViewHolderBase extends RecyclerViewHolder<BaseMultiItemFetchLoadAdapter, PublicChatRoomNimBaseViewHolder, ChatRoomMessage> {
public ImageView nameIconView;
// basic
@@ -67,8 +71,8 @@ public abstract class ChatRoomMessageViewHolderBase extends RecyclerViewHolder<B
protected View.OnLongClickListener longClickListener;
private HeadImageView avatarLeft;
private HeadImageView avatarRight;
private ImageView headWearLeft;
private ImageView headWearRight;
private SVGAView headWearLeft;
private SVGAView headWearRight;
private View headWearLeftLayout;
private View headWearRightLayout;
private int expLevelHeight = UiUtils.INSTANCE.dip2px(18f);
@@ -178,17 +182,17 @@ public abstract class ChatRoomMessageViewHolderBase extends RecyclerViewHolder<B
/// -- 以下是基类实现代码
@Override
public void convert(NIMBaseViewHolder holder, ChatRoomMessage data, int position, boolean isScrolling) {
public void convert(PublicChatRoomNimBaseViewHolder holder, ChatRoomMessage data, int position, boolean isScrolling) {
view = holder.getConvertView();
context = holder.getContext();
message = data;
inflate();
inflate(holder);
refresh();
bindHolder(holder);
}
protected final void inflate() {
protected final void inflate(PublicChatRoomNimBaseViewHolder holder) {
timeTextView = findViewById(R.id.message_item_time);
avatarLeft = findViewById(R.id.message_item_portrait_left);
avatarRight = findViewById(R.id.message_item_portrait_right);
@@ -209,6 +213,8 @@ public abstract class ChatRoomMessageViewHolderBase extends RecyclerViewHolder<B
View.inflate(view.getContext(), getContentResId(), contentContainer);
}
inflateContentView();
headWearLeft.bindCache(holder.getSvgaCache());
headWearRight.bindCache(holder.getSvgaCache());
}
protected final void refresh() {
@@ -271,8 +277,8 @@ public abstract class ChatRoomMessageViewHolderBase extends RecyclerViewHolder<B
View showLayout = isReceivedMessage() ? headWearLeftLayout : headWearRightLayout;
View hideLayout = isReceivedMessage() ? headWearRightLayout : headWearLeftLayout;
HeadImageView showAvatarView = isReceivedMessage() ? avatarLeft : avatarRight;
ImageView showHeadWearView = isReceivedMessage() ? headWearLeft : headWearRight;
ImageView hideHeadWearView = isReceivedMessage() ? headWearRight : headWearLeft;
SVGAView showHeadWearView = isReceivedMessage() ? headWearLeft : headWearRight;
SVGAView hideHeadWearView = isReceivedMessage() ? headWearRight : headWearLeft;
hideLayout.setVisibility(View.GONE);
clearHeadWear(hideHeadWearView);
if (!isShowHeadImage()) {
@@ -292,11 +298,12 @@ public abstract class ChatRoomMessageViewHolderBase extends RecyclerViewHolder<B
showAvatarView.loadBuddyAvatar(message);
}
String headWear = NobleUtil.getResource(HeadWearInfo.HEAD_WEAR, message);
int headWearType = StringUtils2.INSTANCE.toInt(NobleUtil.getResource(HeadWearInfo.TYPE, message));
if (headWear.length() != 0) {
if (!headWear.equals(showHeadWearView.getTag(com.chwl.app.R.id.mic_item_head_wear))) {
showHeadWearView.setVisibility(View.VISIBLE);
showHeadWearView.setTag(com.chwl.app.R.id.mic_item_head_wear, headWear);
NobleUtil.loadMicHeadWear(headWear, showHeadWearView, com.chwl.app.R.id.mic_item_head_wear, headWear);
AvatarHelper.loadAvatarFrame(showHeadWearView, headWear, headWearType);
}
} else {
clearHeadWear(showHeadWearView);
@@ -304,9 +311,10 @@ public abstract class ChatRoomMessageViewHolderBase extends RecyclerViewHolder<B
}
}
private void clearHeadWear(ImageView view) {
private void clearHeadWear(SVGAView view) {
if (view == null) return;
view.clearAnimation();
view.stopAnimation();
view.setImageDrawable(null);
view.setTag(com.chwl.app.R.id.mic_item_head_wear, null);
view.setVisibility(View.GONE);

View File

@@ -17,6 +17,7 @@ import lombok.Setter;
public class HeadWearInfo extends BaseDecoration implements Serializable {
public static final String PIC = "pic";
public static final String EFFECT = "effect";
public static final String TYPE = "headWearType";
public static final String HEAD_WEAR = "headWearUrl";
public static final int STATUS_IN_USED = 1;
public static final int STATUS_OUT_OF_DATE = 2;
@@ -63,6 +64,7 @@ public class HeadWearInfo extends BaseDecoration implements Serializable {
private String limitDesc;//限定描述
private String redirectLink;//H5连接某些头饰是活动得到这里跳转活动
private int type;
public Map<String, Object> toMap(Map<String, Object> map) {
if (map == null) {
@@ -70,6 +72,7 @@ public class HeadWearInfo extends BaseDecoration implements Serializable {
}
map.put(PIC, pic);
map.put(EFFECT, effect);
map.put(TYPE, type);
if (effect != null && effect.length() > 0) {
map.put(HEAD_WEAR, effect);
} else {

View File

@@ -136,6 +136,9 @@ public class NobleUtil {
.listener(new RequestListener<Bitmap>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
if (url.equals(imageView.getTag())) {
imageView.setImageDrawable(null);
}
return false;
}
@@ -159,6 +162,7 @@ public class NobleUtil {
}).submit();
}
@Deprecated()
public static void loadHeadWear(String url, ImageView imageView) {
GlideApp.with(BasicConfig.INSTANCE.getAppContext())
.asBitmap()
@@ -194,7 +198,7 @@ public class NobleUtil {
* 用于坑位加载头饰
* 引入keyId和keyValue是为了解决异步加载造成坑位头饰加载错误的问题
*/
public static void loadMicHeadWear(String url, ImageView imageView, int keyId, String keyValue) {
public static void loadHeadWear(String url, ImageView imageView, int keyId, String keyValue) {
GlideApp.with(BasicConfig.INSTANCE.getAppContext())
.asBitmap()
.dontAnimate()
@@ -203,6 +207,14 @@ public class NobleUtil {
.listener(new RequestListener<Bitmap>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
if (imageView.getTag(keyId) == null) {
return false;
}
if (!imageView.getTag(keyId).equals(keyValue)) {
//坑位已经变动,不需要设置图片
return false;
}
imageView.setImageDrawable(null);
return false;
}

View File

@@ -623,6 +623,7 @@ public class RoomBaseModel extends BaseModel implements IRoomBaseModel {
if (!TextUtils.isEmpty(headWearUrl)) {
contentJsonObj.put("headWearUrl", headWearUrl);
}
contentJsonObj.put("headWearType", headWearInfo.getType());
}
if (AvRoomDataManager.get().isDatingVip(userInfo.getUid())) {
contentJsonObj.put("vipMic", true);

View File

@@ -22,6 +22,7 @@ public class MicMemberInfo {
private String micNickColor;
private String micCircle;
private String headWearUrl;
private int headWearType;
private boolean preventKick;
/**

View File

@@ -27,6 +27,8 @@ public class BaseUserInfo implements Serializable {
private String headwearEffect;
private int headwearType;
private long uid;
private int nobleId;

View File

@@ -120,6 +120,8 @@ dependencies {
api 'com.qcloud.cos:cos-android:5.9.25'
api 'com.liulishuo.filedownloader:library:1.7.7'
api "com.github.yyued:SVGAPlayer-Android:2.6.1"
}
repositories {
mavenCentral()

View File

@@ -1,4 +1,4 @@
package com.chwl.core.helper
package com.chwl.library.utils
import com.chwl.library.utils.codec.MD5Utils

View File

@@ -0,0 +1,237 @@
package com.chwl.library.widget
import android.content.Context
import android.util.AttributeSet
import android.util.LruCache
import com.chwl.library.download.DownloadException
import com.chwl.library.download.DownloadManager
import com.chwl.library.download.DownloadManager.download
import com.chwl.library.download.DownloadRequest.Companion.build
import com.chwl.library.download.DownloadTask
import com.chwl.library.download.FileDownloadListener
import com.chwl.library.utils.PathHelper
import com.example.lib_utils.AppUtils
import com.example.lib_utils.log.ILog
import com.opensource.svgaplayer.SVGADrawable
import com.opensource.svgaplayer.SVGAImageView
import com.opensource.svgaplayer.SVGAParser
import com.opensource.svgaplayer.SVGAParser.Companion.shareParser
import com.opensource.svgaplayer.SVGAVideoEntity
import java.io.BufferedInputStream
import java.io.FileInputStream
class SVGAView : SVGAImageView, ILog {
companion object {
val shareParser: SVGAParser by lazy {
SVGAParser(AppUtils.getApp())
}
@JvmStatic
fun newCache(maxSize: Int): SVGACache {
if (maxSize > 1) {
return SVGALruCache(maxSize)
} else {
return SVGASingleCache()
}
}
}
var resumePlayAfterAttached = true
private var resourceUrl: String? = null
private var svgaCache: SVGACache? = null
private val downloadTag: String get() = "SVGAVIEW_${hashCode()}"
private var logTag: String? = null
private var isDownloading = false
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
fun loadUrl(url: String?) {
logD("loadUrl() url:$url")
if (url.isNullOrEmpty()) {
this.resourceUrl = null
this.setImageDrawable(null)
onViewStateChanged(0)
if (isDownloading) {
DownloadManager.stopTag(downloadTag)
isDownloading = false
}
return
}
if (url == resourceUrl && drawable is SVGADrawable) {
logD("loadUrl() 已加载 isAnimating:$isAnimating")
if (!isAnimating) {
startAnimation()
}
return
}
this.setImageDrawable(null)
this.resourceUrl = url
val cacheItem = svgaCache?.get(url)
if (cacheItem != null) {
logD("loadUrl() 有缓存")
this@SVGAView.setImageDrawable(SVGADrawable(cacheItem))
this@SVGAView.startAnimation()
return
}
loadSVGAUrl(url)
}
private fun loadSVGAUrl(url: String) {
logD("loadSVGAUrl url:$url")
DownloadManager.stopTag(downloadTag)
val filePath = PathHelper.generateResourcesFilePath(url)
val request = build(url, filePath, downloadTag, null, 60000L)
this.isDownloading = true
download(request, object : FileDownloadListener() {
override fun onDownloadCompleted(task: DownloadTask) {
this@SVGAView.isDownloading = false
val path = task.getRequest().getPath()
logD("loadSVGAUrl onDownloadCompleted url:$url path:$path")
if (resourceUrl == url) {
loadSVGAFile(url, path)
}
}
override fun onDownloadError(exception: DownloadException) {
this@SVGAView.isDownloading = false
logD("loadSVGAUrl onDownloadError url:$url")
if (resourceUrl == url) {
onViewStateChanged(-1)
}
}
})
}
private fun loadSVGAFile(url: String, path: String) {
try {
logD("loadSVGAFile path:$path url:$url")
val inputStream = BufferedInputStream(FileInputStream(path))
shareParser().decodeFromInputStream(
inputStream,
path,
object : SVGAParser.ParseCompletion {
override fun onComplete(videoItem: SVGAVideoEntity) {
logD("SVGAView parseCompletion onComplete url:$url")
if (resourceUrl != url) {
return
}
svgaCache?.put(resourceUrl ?: "", videoItem)
this@SVGAView.setImageDrawable(SVGADrawable(videoItem))
this@SVGAView.startAnimation()
onViewStateChanged(1)
}
override fun onError() {
logD("SVGAView parseCompletion onError url:$url")
if (resourceUrl != url) {
return
}
onViewStateChanged(-1)
}
},
true,
null,
null
)
} catch (e: Exception) {
e.printStackTrace()
logD("loadSVGAFile url:$url e:${e.message}")
onViewStateChanged(-1)
}
}
/**
* @param state -1 异常、0 空、1 成功
*/
private fun onViewStateChanged(state: Int) {
logD("onViewStateChanged state:$state")
}
fun bindCache(cache: SVGACache?) {
logD("bindCache() cache:$cache")
this.svgaCache = cache
}
fun setLogTag(tag: String) {
logD("setLogTag() newTag:$tag oldTag:$logTag")
this.logTag = tag
}
override fun logD(message: String, tag: String, filePrinter: Boolean) {
if (logTag != null) {
super.logD("#$logTag# $message", tag, filePrinter)
} else {
super.logD(message, tag, filePrinter)
}
}
override fun onDetachedFromWindow() {
logD("onDetachedFromWindow()")
super.onDetachedFromWindow()
}
override fun onAttachedToWindow() {
logD("onAttachedToWindow()")
super.onAttachedToWindow()
if (resumePlayAfterAttached) {
if (drawable is SVGADrawable) {
if (!isAnimating) {
logD("onAttachedToWindow() startAnimation")
startAnimation()
}
}
}
}
interface SVGACache {
fun get(key: String): SVGAVideoEntity?
fun put(key: String, entity: SVGAVideoEntity)
fun clear()
}
class SVGALruCache(maxSize: Int) : SVGACache {
val lruCache = LruCache<String, SVGAVideoEntity>(maxSize)
override fun get(key: String): SVGAVideoEntity? {
return lruCache.get(key)
}
override fun put(key: String, entity: SVGAVideoEntity) {
lruCache.put(key, entity)
}
override fun clear() {
lruCache.evictAll()
}
}
class SVGASingleCache : SVGACache {
var cache: Pair<String, SVGAVideoEntity>? = null
override fun get(key: String): SVGAVideoEntity? {
if (cache?.first == key) {
return cache?.second
}
return null
}
override fun put(key: String, entity: SVGAVideoEntity) {
cache = Pair(key, entity)
}
override fun clear() {
cache = null
}
}
}

View File

@@ -8,6 +8,10 @@ import java.util.regex.Pattern
*/
object StringUtils2 {
fun toInt(str: String?): Int {
return str?.toIntOrNull() ?: 0
}
/**
* 拆分字符串(根据匹配规则,按顺序拆分出来)
* @param pattern 匹配节点的规则模式

View File

@@ -40,7 +40,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/message_item_head_wear_left"
android:layout_width="59.4dp"
android:layout_height="59.4dp"
@@ -65,7 +65,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
<com.chwl.library.widget.SVGAView
android:id="@+id/message_item_head_wear_right"
android:layout_width="59.4dp"
android:layout_height="59.4dp"

View File

@@ -0,0 +1,9 @@
package com.netease.nim.uikit.common.ui.recyclerview.holder
import android.view.View
import androidx.annotation.Keep
import com.chwl.library.widget.SVGAView
@Keep
class PublicChatRoomNimBaseViewHolder(view: View, val svgaCache: SVGAView.SVGACache) :
NIMBaseViewHolder(view)