diff --git a/app/build.gradle b/app/build.gradle index 83cfd17b1..35a6ab9cf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -117,6 +117,7 @@ android { 'src/module_treasure_box/java', 'src/module_public_chat/java', 'src/module_game/java', + 'src/module_community/java', ] @@ -133,6 +134,7 @@ android { 'src/module_treasure_box/res', 'src/module_public_chat/res', 'src/module_game/res', + 'src/module_community/res', ] diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 34bb2d8b1..362dfab7c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -934,6 +934,15 @@ android:launchMode="singleTask" android:screenOrientation="portrait" android:windowSoftInputMode="adjustPan" /> + + \ No newline at end of file diff --git a/app/src/main/java/com/chwl/app/MainActivity.java b/app/src/main/java/com/chwl/app/MainActivity.java index 51cb6c87c..9f6890f80 100644 --- a/app/src/main/java/com/chwl/app/MainActivity.java +++ b/app/src/main/java/com/chwl/app/MainActivity.java @@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModelProvider; import com.chwl.app.base.GlobalViewModelOwner; import com.chwl.app.common.widget.dialog.DialogManager; +import com.chwl.app.community.square.SquareFragment; import com.chwl.app.game.core.GameStateAbility; import com.chwl.app.game.data.GameModel2; import com.chwl.app.game.ui.game.GameActivity; @@ -143,7 +144,7 @@ public class MainActivity extends BaseMvpActivity private MainTabLayout mMainTabLayout; private AnchorCardView anchorCardView; private View viewClose; - private int mCurrentTabType = MainTabType.TAB_TYPE_STAR; + private int mCurrentTabType = MainTabType.TAB_TYPE_HOME; /** * 房间最小化动画,换成属性动画,原先的补间动画影响了activity的生命周期 */ @@ -162,9 +163,9 @@ public class MainActivity extends BaseMvpActivity private Runnable touchRunnable; { - fragmentArray.put(MainTabType.TAB_TYPE_STAR, new StarFragment()); - fragmentArray.put(MainTabType.TAB_TYPE_GAME, new GameHomeFragment()); fragmentArray.put(MainTabType.TAB_TYPE_HOME, new HomeFragment()); + fragmentArray.put(MainTabType.TAB_TYPE_GAME, new GameHomeFragment()); + fragmentArray.put(MainTabType.TAB_TYPE_SQUARE, new SquareFragment()); fragmentArray.put(MainTabType.TAB_TYPE_MSG, new ContactsListFragment()); fragmentArray.put(MainTabType.TAB_TYPE_ME, new MeFragment()); } diff --git a/app/src/main/java/com/chwl/app/home/adapter/CommunityNoticeAdapter.java b/app/src/main/java/com/chwl/app/home/adapter/CommunityNoticeAdapter.java index d2349809a..254ce4331 100644 --- a/app/src/main/java/com/chwl/app/home/adapter/CommunityNoticeAdapter.java +++ b/app/src/main/java/com/chwl/app/home/adapter/CommunityNoticeAdapter.java @@ -1,6 +1,8 @@ package com.chwl.app.home.adapter; + import android.text.TextUtils; +import android.widget.TextView; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseViewHolder; @@ -59,7 +61,8 @@ public class CommunityNoticeAdapter extends BaseQuickAdapter { + + private Context context; + @Setter + private int mTwoImageHeight; + @Setter + private int mThreeImageHeight; + + private int imageWidth; + + private int bigImageWidth; + + @Setter + private int singleImageHeight; + + public DynamicImageAdapter(int layoutResId, @Nullable List data) { + super(layoutResId, data); + context = BasicConfig.INSTANCE.getAppContext(); + imageWidth = UIUtil.getScreenWidth(context) * 2 / 5; + bigImageWidth = UIUtil.getScreenWidth(context); + + mTwoImageHeight = (ScreenUtils.getScreenWidth(context) - UIUtil.dip2px(context, 50F)) / 2; + mThreeImageHeight = (ScreenUtils.getScreenWidth(context) - UIUtil.dip2px(context, 60F)) / 3; + } + + @Override + protected void convert(BaseViewHolder helper, DynamicMedia item) { + ImageView ivPhoto = helper.getView(R.id.riv_photo); + helper.setGone(R.id.iv_gif_tag, item.isGif()); + ViewGroup.LayoutParams layoutParams = ivPhoto.getLayoutParams(); + if (helper.itemView instanceof ConstraintLayout && getData().size() > 1) { + ImageLoadUtilsV2.loadImage(ivPhoto, item.getResUrl(), imageWidth); + } else { + switch (getData().size()) { + case 1: + layoutParams.height = singleImageHeight; + ivPhoto.setLayoutParams(layoutParams); + ImageLoadUtilsV2.loadImage(ivPhoto, item.getResUrl(), bigImageWidth); + break; + case 2: + layoutParams.height = mTwoImageHeight; + ivPhoto.setLayoutParams(layoutParams); + ImageLoadUtilsV2.loadImage(ivPhoto, item.getResUrl(), imageWidth); + break; + case 3: + default: + layoutParams.height = mThreeImageHeight; + ivPhoto.setLayoutParams(layoutParams); + ImageLoadUtilsV2.loadImage(ivPhoto, item.getResUrl(), imageWidth); + break; + } + } + } +} diff --git a/app/src/main/java/com/chwl/app/ui/im/ImInitHelper.java b/app/src/main/java/com/chwl/app/ui/im/ImInitHelper.java index edfd74bd3..74369a427 100644 --- a/app/src/main/java/com/chwl/app/ui/im/ImInitHelper.java +++ b/app/src/main/java/com/chwl/app/ui/im/ImInitHelper.java @@ -2,7 +2,11 @@ package com.chwl.app.ui.im; import android.content.Context; +import com.chwl.app.community.holder.DynamicSysHolder; +import com.chwl.app.community.im.WorldDynamicShareViewHolder; import com.chwl.app.module_hall.im.msgholder.FamilyMsgViewHolder; +import com.chwl.core.community.attachment.DynamicSysAttachment; +import com.chwl.core.community.im.WorldDynamicAttachment; import com.chwl.core.module_hall.im.FamilyAttachment; import com.netease.nim.uikit.api.NimUIKit; import com.netease.nim.uikit.api.model.contact.ContactEventListener; @@ -151,6 +155,10 @@ public class ImInitHelper { //瓜分钻石 三级 NimUIKit.registerMsgItemViewHolder(CarveUpGoldThirdLevelAttachment.class, MsgViewHolderText.class); + // 社区动态 + NimUIKit.registerMsgItemViewHolder(DynamicSysAttachment.class, DynamicSysHolder.class); + NimUIKit.registerMsgItemViewHolder(WorldDynamicAttachment.class, WorldDynamicShareViewHolder.class); + NimUIKit.registerMsgItemViewHolder(ChatHintAttachment.class, MsgViewHolderChatHint.class); //技能卡 diff --git a/app/src/main/java/com/chwl/app/ui/user/activity/UserInfoActivity.java b/app/src/main/java/com/chwl/app/ui/user/activity/UserInfoActivity.java index 9f9ae89c6..244008d20 100644 --- a/app/src/main/java/com/chwl/app/ui/user/activity/UserInfoActivity.java +++ b/app/src/main/java/com/chwl/app/ui/user/activity/UserInfoActivity.java @@ -22,6 +22,7 @@ import androidx.viewpager2.widget.ViewPager2; import com.chwl.app.avroom.adapter.CommonVPAdapter; 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.core.decoration.headwear.bean.HeadWearInfo; import com.chwl.core.noble.NobleUtil; @@ -201,12 +202,12 @@ public class UserInfoActivity extends BaseBindingActivity fragmentList = new ArrayList<>(1); + List fragmentList = new ArrayList<>(2); fragmentList.add(new UserInfoDataFragment()); -// fragmentList.add(new UserInfoGiftWallFragment()); - final List tagList = new ArrayList<>(1); + fragmentList.add(new UserInfoDynamicFragment()); + final List tagList = new ArrayList<>(2); tagList.add(getString(R.string.me_data)); -// tagList.add(getString(R.string.me_gift_wall)); + tagList.add(getString(R.string.me_dynamic)); CommonNavigator commonNavigator = new CommonNavigator(context); commonNavigator.setTitleWrapContent(false); UserInfoIndicatorAdapter magicIndicatorAdapter = new UserInfoIndicatorAdapter(context, tagList); diff --git a/app/src/main/java/com/chwl/app/ui/user/activity/UserInfoModifyActivity.kt b/app/src/main/java/com/chwl/app/ui/user/activity/UserInfoModifyActivity.kt index caba93c71..e0150e9ae 100644 --- a/app/src/main/java/com/chwl/app/ui/user/activity/UserInfoModifyActivity.kt +++ b/app/src/main/java/com/chwl/app/ui/user/activity/UserInfoModifyActivity.kt @@ -35,7 +35,6 @@ import com.chwl.app.ui.widget.dialog.CommonTipDialog import com.chwl.app.utils.RegexUtil import com.chwl.core.auth.AuthModel import com.chwl.core.file.FileModel -import com.chwl.core.file.cos.CosException import com.chwl.core.user.UserModel import com.chwl.core.user.bean.UserInfo import com.chwl.core.user.bean.UserPhoto diff --git a/app/src/main/java/com/chwl/app/ui/user/adapter/UserInfoDynamicAdapter.java b/app/src/main/java/com/chwl/app/ui/user/adapter/UserInfoDynamicAdapter.java new file mode 100644 index 000000000..8c73b06b7 --- /dev/null +++ b/app/src/main/java/com/chwl/app/ui/user/adapter/UserInfoDynamicAdapter.java @@ -0,0 +1,249 @@ +package com.chwl.app.ui.user.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.R; +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.widget.ExpandableTextView; +import com.chwl.app.photo.BigPhotoActivity; +import com.chwl.app.photo.PagerOption; +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil; +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.utils.net.DontWarnObserver; +import com.chwl.core.utils.net.RxHelper; +import com.chwl.library.utils.ResUtil; +import com.chwl.library.utils.SingleToastUtil; +import com.netease.nim.uikit.common.util.log.LogUtil; + +import java.util.List; + +/** + * create by lvzebiao @2019/11/13 + */ +public class UserInfoDynamicAdapter extends BaseQuickAdapter { + + private SparseBooleanArray mCollapsedStatus = new SparseBooleanArray(); + private SparseIntArray mCollapsedHeightStatus = new SparseIntArray(2); + + private Context context; + + private long worldId; + + private int iconWidth; + + private int iconHeight; + + /** + * 单图情况下的边界 + */ + private int imageBorder; + /** + * 图片的边界值 + */ + private int divider; + + public UserInfoDynamicAdapter(Context context) { + super(R.layout.item_userinfo_dynamic); + this.context = context; + iconWidth = UIUtil.dip2px(context, 32); + iconHeight = UIUtil.dip2px(context, 15); + //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()); + RecyclerView rvImage = helper.getView(R.id.rv_image); + List 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); + } + + //时间 + helper.setText(R.id.tv_time, TimeUiUtils.getDynamicUi(item.getPublishTime())); + + ExpandableTextView etvContent = helper.getView(R.id.etv_content); + etvContent.setEventType(1); + if (noTextUi) { + etvContent.setVisibility(View.GONE); + } else { + etvContent.setVisibility(View.VISIBLE); + CharSequence formatText = DynamicUiHelper.formatFirstDynamicContent( + item, etvContent.mTv, iconWidth, iconHeight); + etvContent.setText(formatText, mCollapsedStatus, helper.getAdapterPosition(), mCollapsedHeightStatus); + } + + helper.setGone(R.id.layout_root_mini_world, item.getTag() != null); + helper.setText(R.id.tv_mini_world_name, "#" + item.getTag()); + + //评论 + 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) { + if (item.getDynamicId() == 0) { + SingleToastUtil.showToast(ResUtil.getString(R.string.the_default_dynamic_cannot_be_liked)); + return; + } + 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() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + llLike.setEnabled(true); + if (error != null) { + SingleToastUtil.showToast(error); + } else { + LogUtil.print(mContext.getString(R.string.me_call_the_like_interface_to_complete)); + 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 -> { + if (item.getDynamicId() == 0) { + SingleToastUtil.showToast(ResUtil.getString(R.string.the_default_dynamic_cannot_be_commented)); + return; + } + DynamicDetailActivity.start(context, item.getDynamicId(), worldId, + helper.getAdapterPosition(), true, 1); + } + ); + helper.setVisible(R.id.iv_more, item.getDynamicId() != 0); + if (item.getDynamicId() != 0) { + helper.addOnClickListener(R.id.iv_more).addOnClickListener(R.id.ll_share); + } + + View.OnClickListener toDetailListener = v -> { + if (item.getDynamicId() == 0) { + return; + } + DynamicDetailActivity.start(context, item.getDynamicId(), worldId, + helper.getAdapterPosition(), false, 1); + }; + + if (etvContent.mTv != null) { + etvContent.mTv.setOnClickListener(toDetailListener); + } + //跳转去详情 + helper.itemView.setOnClickListener(toDetailListener); + helper.setGone(R.id.line_bottom, getItemCount() - 1 != helper.getLayoutPosition()); + } + + 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) { + ivLikeAnim.setImageResource(R.drawable.icon_dy_list_like); + } else { + ivLikeAnim.setImageResource(R.drawable.icon_dy_list_like_false); + } + + } + + private void initRecyclerView(RecyclerView rvImage, List 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; + } + 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); + } + +} diff --git a/app/src/main/java/com/chwl/app/ui/user/fragment/UserInfoDataFragment.kt b/app/src/main/java/com/chwl/app/ui/user/fragment/UserInfoDataFragment.kt index 24de7bdd2..24783de9a 100644 --- a/app/src/main/java/com/chwl/app/ui/user/fragment/UserInfoDataFragment.kt +++ b/app/src/main/java/com/chwl/app/ui/user/fragment/UserInfoDataFragment.kt @@ -68,7 +68,7 @@ class UserInfoDataFragment : BaseViewBindingFragment() { + + private val viewModel: UserInfoViewModel by activityViewModels() + + private var adapter: UserInfoDynamicAdapter? = null + override fun init() { + initView() + viewModel.userInfoDetailData.observe(this) { + updateList(it.dynamicInfo) + } + } + + private fun initView() { + adapter = UserInfoDynamicAdapter(requireContext()) + adapter?.setEnableLoadMore(false) + adapter?.emptyView = layoutInflater.inflate(R.layout.user_info_tab_empty, null) + binding.recyclerView.adapter = adapter + adapter?.setOnItemChildClickListener { adapter, view: View, pos: Int -> + val bean = + adapter?.getItem(pos) as? WorldDynamicBean ?: return@setOnItemChildClickListener + if (view.id == R.id.iv_more) { + val list: MutableList = ArrayList() + if (!UserModel.get().isMyseft(bean.uid)) { + val item = ButtonItem( + getString(R.string.me_shield_dynamic) + ) { + UserModel.get().addReport(bean.dynamicId, 0) + .subscribe(object : BeanObserver() { + override fun onErrorMsg(error: String) { + dialogManager.dismissDialog() + toast(error) + } + + override fun onSuccess(s: String) { + dialogManager.dismissDialog() + toast(ResUtil.getString(R.string.me_shield_success)) + val size = adapter?.data?.size ?: 0 + if (pos < size) { + if (bean == adapter?.getItem(pos)) { + adapter?.remove(pos) + } + } + } + }) + } + list.add(item) + } + if (!UserModel.get().isMyseft(bean.uid)) { + val blackListItem = ButtonItemFactory.createAddToBlackListItem( + dialogManager, bean.uid.toString() + ) + list.add(blackListItem) + } + if (!UserModel.get().isMyseft(bean.uid)) { + val item = ButtonItem( + getString(R.string.me_report_dynamic) + ) { + UIHelper.showReportPage( + mContext, bean.uid, + XConstants.REPORT_TYPE_DYNAMIC_SQUARE + ) + } + list.add(item) + } + if (UserModel.get().isMyseft(bean.uid) || + isThisWorldOwner(bean) + ) { + val item = ButtonItem( + getString(R.string.me_delete) + ) { deleteDynamic(pos, this.adapter) } + list.add(item) + } + dialogManager.showCommonPopupDialog(list, getString(R.string.cancel)) + } else if (view.id == R.id.ll_share) { +// ShareDynamicHelper(activity).share(bean) + } + } + } + + private fun deleteDynamic(pos: Int, adapter: UserInfoDynamicAdapter?) { + dialogManager.showOkCancelWithTitleDialog(getString(R.string.me_cannot_be_restored), + DialogManager.OkCancelDialogListener { + val bean = adapter?.getItem(pos) ?: return@OkCancelDialogListener + DynamicModel.get().delete(bean.worldId, bean.dynamicId) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .doOnSubscribe { dialogManager.showProgressDialog(mContext) } + .subscribe(object : DontWarnObserver() { + override fun accept(s: String?, error: String?) { + super.accept(s, error) + dialogManager.dismissDialog() + if (error != null) { + toast(error) + } else { + toast(getString(R.string.me_successfully_delete)) + if (pos < adapter.data.size) { + if (bean == adapter.getItem(pos)) { + adapter.remove(pos) + } + } + } + } + }) + }) + } + + /** + * 判断自己是不是该世界的创始人 + */ + private fun isThisWorldOwner(bean: WorldDynamicBean?): Boolean { + return bean != null && bean.worldUid == AuthModel.get().currentUid + } + + private fun updateList(list: List?) { + adapter?.setNewData(list) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/chwl/app/ui/user/viewmodel/UserInfoViewModel.kt b/app/src/main/java/com/chwl/app/ui/user/viewmodel/UserInfoViewModel.kt index 527a8c363..3b2024640 100644 --- a/app/src/main/java/com/chwl/app/ui/user/viewmodel/UserInfoViewModel.kt +++ b/app/src/main/java/com/chwl/app/ui/user/viewmodel/UserInfoViewModel.kt @@ -3,21 +3,16 @@ package com.chwl.app.ui.user.viewmodel import android.annotation.SuppressLint import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel import com.chwl.app.base.BaseViewModel import com.chwl.app.module_hall.HallDataManager import com.chwl.core.auth.AuthModel -import com.chwl.core.module_hall.hall.HallModel -import com.chwl.core.module_hall.hall.bean.ClanAndHallInfo import com.chwl.core.module_hall.hall.bean.UserClanInfo -import com.chwl.core.user.UserInfoUiMgr import com.chwl.core.user.UserModel import com.chwl.core.user.bean.GiftWallInfo import com.chwl.core.user.bean.UserDetailInfo import com.chwl.core.user.bean.UserInfo import com.chwl.core.utils.net.BeanObserver import com.chwl.core.utils.extension.toast -import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.Disposable class UserInfoViewModel : BaseViewModel() { @@ -46,7 +41,7 @@ class UserInfoViewModel : BaseViewModel() { } override fun onSuccess(info: UserInfo) { - _userInfoData.value = info + _userInfoData.postValue(info) } override fun onSubscribe(d: Disposable) { @@ -65,7 +60,7 @@ class UserInfoViewModel : BaseViewModel() { override fun onSuccess(info: UserDetailInfo) { info.let { mRoomUid = it.data.roomUid - _userInfoDetailData.value = it.data + _userInfoDetailData.postValue(it.data) } } diff --git a/app/src/main/java/com/chwl/app/ui/widget/MainRedPointTab.java b/app/src/main/java/com/chwl/app/ui/widget/MainRedPointTab.java index 4d2b83304..7e0fc6a24 100644 --- a/app/src/main/java/com/chwl/app/ui/widget/MainRedPointTab.java +++ b/app/src/main/java/com/chwl/app/ui/widget/MainRedPointTab.java @@ -139,8 +139,8 @@ public class MainRedPointTab extends RelativeLayout { private int getDefaultRes(int tabType, boolean select) { int resId = select ? R.drawable.ic_main_tab_home_pressed : R.drawable.ic_main_tab_home; switch (tabType) { - case MainTabType.TAB_TYPE_STAR: - resId = select ? R.drawable.ic_main_tab_star_pressed : R.drawable.ic_main_tab_star; + case MainTabType.TAB_TYPE_SQUARE: + resId = select ? R.drawable.ic_main_tab_square_pressed : R.drawable.ic_main_tab_square; break; case MainTabType.TAB_TYPE_GAME: resId = select ? R.drawable.ic_main_tab_game_pressed : R.drawable.ic_main_tab_game; diff --git a/app/src/main/java/com/chwl/app/ui/widget/MainTabLayout.java b/app/src/main/java/com/chwl/app/ui/widget/MainTabLayout.java index 253192fb2..01cef0d1a 100644 --- a/app/src/main/java/com/chwl/app/ui/widget/MainTabLayout.java +++ b/app/src/main/java/com/chwl/app/ui/widget/MainTabLayout.java @@ -25,7 +25,7 @@ public class MainTabLayout extends LinearLayout implements View.OnClickListener private final List tabViewList = new ArrayList<>(4); private MainRedPointTab homeTab; - private MainRedPointTab starTab; + private MainRedPointTab squareTab; private MainRedPointTab gameTab; private MainRedPointTab msgTab; private MainRedPointTab meTab; @@ -57,20 +57,20 @@ public class MainTabLayout extends LinearLayout implements View.OnClickListener inflate(context, R.layout.main_tab_layout, this); msgTab = findViewById(R.id.main_msg_tab); - starTab = findViewById(R.id.main_star_tab); + squareTab = findViewById(R.id.main_square_tab); gameTab = findViewById(R.id.main_game_tab); homeTab = findViewById(R.id.main_home_tab); meTab = findViewById(R.id.main_me_tab); homeTab.setOnClickListener(this); meTab.setOnClickListener(this); - starTab.setOnClickListener(this); + squareTab.setOnClickListener(this); gameTab.setOnClickListener(this); msgTab.setOnClickListener(this); - tabViewList.add(starTab); - tabViewList.add(gameTab); tabViewList.add(homeTab); + tabViewList.add(gameTab); + tabViewList.add(squareTab); tabViewList.add(msgTab); tabViewList.add(meTab); } @@ -106,8 +106,8 @@ public class MainTabLayout extends LinearLayout implements View.OnClickListener case R.id.main_home_tab: select(MainTabType.TAB_TYPE_HOME); break; - case R.id.main_star_tab: - select(MainTabType.TAB_TYPE_STAR); + case R.id.main_square_tab: + select(MainTabType.TAB_TYPE_SQUARE); break; case R.id.main_game_tab: select(MainTabType.TAB_TYPE_GAME); @@ -122,10 +122,10 @@ public class MainTabLayout extends LinearLayout implements View.OnClickListener } private void select(int tabType) { - if (tabType == 0) tabType = MainTabType.TAB_TYPE_STAR; + if (tabType == 0) tabType = MainTabType.TAB_TYPE_HOME; if (mLastPosition == tabType) return; msgTab.select(tabType == MainTabType.TAB_TYPE_MSG); - starTab.select(tabType == MainTabType.TAB_TYPE_STAR); + squareTab.select(tabType == MainTabType.TAB_TYPE_SQUARE); gameTab.select(tabType == MainTabType.TAB_TYPE_GAME); homeTab.select(tabType == MainTabType.TAB_TYPE_HOME); meTab.select(tabType == MainTabType.TAB_TYPE_ME); diff --git a/app/src/main/res/drawable-xxhdpi/base_status_empty.png b/app/src/main/res/drawable-xxhdpi/base_status_empty.png new file mode 100644 index 000000000..02ecbd92e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/base_status_empty.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_main_tab_square.png b/app/src/main/res/drawable-xxhdpi/ic_main_tab_square.png new file mode 100644 index 000000000..d0eaa4bbb Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_main_tab_square.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_main_tab_square_pressed.png b/app/src/main/res/drawable-xxhdpi/ic_main_tab_square_pressed.png new file mode 100644 index 000000000..be87661c8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_main_tab_square_pressed.png differ diff --git a/app/src/main/res/layout/activity_big_photo.xml b/app/src/main/res/layout/activity_big_photo.xml index 14ab4a038..c4f004153 100644 --- a/app/src/main/res/layout/activity_big_photo.xml +++ b/app/src/main/res/layout/activity_big_photo.xml @@ -9,6 +9,7 @@ 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" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/main_tab_layout.xml b/app/src/main/res/layout/main_tab_layout.xml index 7810202b5..1f05a39f0 100644 --- a/app/src/main/res/layout/main_tab_layout.xml +++ b/app/src/main/res/layout/main_tab_layout.xml @@ -6,8 +6,15 @@ android:orientation="horizontal" tools:parentTag="LinearLayout"> + + + + + + + + + + + diff --git a/app/src/main/res/layout/user_info_tab_empty.xml b/app/src/main/res/layout/user_info_tab_empty.xml new file mode 100644 index 000000000..ab4a23d4b --- /dev/null +++ b/app/src/main/res/layout/user_info_tab_empty.xml @@ -0,0 +1,33 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 8aff7970d..afb5f021a 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -976,7 +976,7 @@ نقرة على وحدة ميزات مركز الفرد مباشر المعلومات - ديناميكيات + التحديثات جدار الهدايا حجرة الدرع التقرير diff --git a/app/src/module_community/java/com/chwl/app/community/ConstantValue.java b/app/src/module_community/java/com/chwl/app/community/ConstantValue.java new file mode 100644 index 000000000..44c0f318a --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/ConstantValue.java @@ -0,0 +1,10 @@ +package com.chwl.app.community; + +/** + * create by lvzebiao @2019/11/12 + */ +public class ConstantValue { + + public static final int CODE_CHOOSE_PHOTO = 12; + +} diff --git a/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/CommentAdapter.java b/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/CommentAdapter.java new file mode 100644 index 000000000..ba669476d --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/CommentAdapter.java @@ -0,0 +1,165 @@ +package com.chwl.app.community.dynamic.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.chwl.app.R; +import com.chwl.app.UIHelper; +import com.chwl.app.ui.utils.ImageLoadUtilsV2; +import com.chwl.app.utils.RegexUtil; +import com.chwl.app.utils.TimeUiUtils; +import com.chwl.app.vip.util.VipHelper; +import com.chwl.core.community.bean.Comment; +import com.chwl.library.utils.ListUtils; + +import java.util.List; + +/** + * create by lvzebiao @2019/11/26 + */ +public class CommentAdapter extends BaseQuickAdapter { + + + public CommentAdapter() { + super(R.layout.item_dy_comment); + } + + @Override + protected void convert(BaseViewHolder helper, Comment item) { + ImageLoadUtilsV2.loadAvatar(helper.getView(R.id.iv_avatar), item.getAvatar()); + TextView tvNick = helper.getView(R.id.tv_nick); + tvNick.setText(RegexUtil.getPrintableString(item.getNick())); + VipHelper.loadVipIcon(helper.getView(R.id.iv_vip_icon), item.getUserVipInfoVO()); + int endIcon = 0; + if (item.isLandLordFlag()) { + endIcon = R.drawable.icon_dy_dynamic_publisher; + } + tvNick.setCompoundDrawablesWithIntrinsicBounds(0, 0, endIcon, 0); + helper.setText(R.id.tv_content, item.getContent()); + + helper.getView(R.id.iv_avatar).setOnClickListener(v -> + UIHelper.showUserInfoAct(mContext, item.getUid())); + + helper.setText(R.id.tv_time, TimeUiUtils.getDynamicUi(item.getPublishTime())); + + helper.addOnLongClickListener(R.id.tv_content); + helper.addOnClickListener(R.id.tv_content); + + + //===========================回复========================= + RecyclerView rvReply = helper.getView(R.id.rv_reply); + + View lineReplyBottom = helper.getView(R.id.line_reply_bottom); + if (item.isEmptyReply()) { + lineReplyBottom.setVisibility(View.GONE); + } else { + lineReplyBottom.setVisibility(View.VISIBLE); + } + CommentReplyAdapter commentReplyAdapter = new CommentReplyAdapter(item.getReplyInfo().getLeftCount() > 0); + rvReply.setLayoutManager(new LinearLayoutManager(mContext)); + rvReply.setAdapter(commentReplyAdapter); + + commentReplyAdapter.setNewData(item.getReplyList()); + + commentReplyAdapter.setOnItemChildClickListener(new OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + if (onCommentReplyItemChildClickListener != null) { + onCommentReplyItemChildClickListener.onCommentReplyItemChildClick(view, + helper.getAdapterPosition() - 1, position); + } + } + }); + + commentReplyAdapter.setOnItemChildLongClickListener(new OnItemChildLongClickListener() { + @Override + public boolean onItemChildLongClick(BaseQuickAdapter adapter, View view, int position) { + if (onCommentReplyItemChildClickListener != null) { + onCommentReplyItemChildClickListener.onCommentReplyItemChildLongClick(view, + helper.getAdapterPosition() - 1, position); + } + return true; + } + }); + + + View mFooterView = LayoutInflater.from(mContext).inflate(R.layout.item_reply_footer_view, null); + + if (item.getReplyInfo().getLeftCount() > 0) { //剩余回复大于0 + ((TextView) mFooterView).setText(String.format(mContext.getResources().getString(R.string.dy_open_other_number), + String.valueOf(item.getReplyInfo().getLeftCount()))); + commentReplyAdapter.addFooterView(mFooterView); + } else { + commentReplyAdapter.removeAllFooterView(); + } + + mFooterView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + onCommentReplyItemChildClickListener.onLoadMoreClick( + item.getCommentId(), + item.getReplyInfo().getNextTimestamp(), + helper.getLayoutPosition() - 1); + } + }); + + + } + + private OnCommentReplyItemChildClickListener onCommentReplyItemChildClickListener; + + public interface OnCommentReplyItemChildClickListener { + + void onCommentReplyItemChildClick(View view, int groupPosition, int childPosition); + + void onCommentReplyItemChildLongClick(View view, int groupPosition, int childPosition); + + void onLoadMoreClick(long commentId, long nextReplyId, int groupPosition); + + } + + public void setOnCommentReplyItemChildClickListener(OnCommentReplyItemChildClickListener onCommentReplyItemChildClickListener) { + this.onCommentReplyItemChildClickListener = onCommentReplyItemChildClickListener; + } + + public long getItemCommentId(int pos) { + List list = getData(); + if (ListUtils.isListEmpty(list)) { + return 0; + } + if (pos >= 0 && pos < list.size()) { + Comment comment = list.get(pos); + if (comment != null) { + return comment.getCommentId(); + } + } + return 0; + } + + public Comment getDataItem(int pos) { + List list = getData(); + if (ListUtils.isListEmpty(list)) { + return null; + } + if (pos >= 0 && pos < list.size()) { + return list.get(pos); + } + return null; + } + + public void safeDelete(int pos) { + List list = getData(); + if (pos >= 0 && pos < list.size()) { + list.remove(pos); + notifyDataSetChanged(); + } + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/CommentReplyAdapter.java b/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/CommentReplyAdapter.java new file mode 100644 index 000000000..894498387 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/CommentReplyAdapter.java @@ -0,0 +1,74 @@ +package com.chwl.app.community.dynamic.adapter; + +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.chwl.app.R; +import com.chwl.app.UIHelper; +import com.chwl.app.ui.utils.ImageLoadUtilsV2; +import com.chwl.app.utils.RegexUtil; +import com.chwl.app.utils.SpannableBuilder; +import com.chwl.app.utils.TimeUiUtils; +import com.chwl.app.vip.util.VipHelper; +import com.chwl.core.community.bean.comment.Reply; + +/** + * create by lvzebiao @2019/11/27 + */ +public class CommentReplyAdapter extends BaseQuickAdapter { + + private boolean hasExpandFooter; + + public CommentReplyAdapter(boolean hasExpandFooter) { + super(R.layout.item_dy_reply); + this.hasExpandFooter = hasExpandFooter; + } + + @Override + protected void convert(BaseViewHolder helper, Reply item) { + + ImageLoadUtilsV2.loadAvatar(helper.getView(R.id.iv_avatar), item.getAvatar(), true); + TextView tvNick = helper.getView(R.id.tv_nick); + tvNick.setText(RegexUtil.getPrintableString(item.getNick())); + VipHelper.loadVipIcon(helper.getView(R.id.iv_vip_icon), item.getUserVipInfoVO()); + int endIcon = 0; + if (item.isLandLordFlag()) { + endIcon = R.drawable.icon_dy_dynamic_publisher; + } + tvNick.setCompoundDrawablesWithIntrinsicBounds(0, 0, endIcon, 0); + + SpannableBuilder builder = new SpannableBuilder(); + builder.append("@" + item.getToNick(), + new ForegroundColorSpan(mContext.getResources().getColor(R.color.color_7154EE))) + .append(" " + item.getContent(), + new ForegroundColorSpan(mContext.getResources().getColor(R.color.text_normal_c6c6e9))); + + helper.setText(R.id.tv_content, builder.build()); + + helper.getView(R.id.iv_avatar).setOnClickListener(v -> + UIHelper.showUserInfoAct(mContext, item.getUid())); + + helper.setText(R.id.tv_time, TimeUiUtils.getDynamicUi(item.getPublishTime())); + + helper.addOnClickListener(R.id.item_reply_constraintlayout) + .addOnClickListener(R.id.tv_content); + helper.addOnLongClickListener(R.id.tv_content); + + View line = helper.getView(R.id.view_line_reply); + if (hasExpandFooter) { + line.setVisibility(View.VISIBLE); + } else { + //没有回复项的时候,最后一项的线隐藏 + if (helper.getAdapterPosition() == getData().size() - 1) { + line.setVisibility(View.GONE); + } else { + line.setVisibility(View.VISIBLE); + } + } + + + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/WorldDynamicAdapter.java b/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/WorldDynamicAdapter.java new file mode 100644 index 000000000..a7f63bec7 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/dynamic/adapter/WorldDynamicAdapter.java @@ -0,0 +1,307 @@ +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 { + + 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 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 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() { + @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 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); + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/dynamic/view/DynamicDetailActivity.java b/app/src/module_community/java/com/chwl/app/community/dynamic/view/DynamicDetailActivity.java new file mode 100644 index 000000000..ac3d32d7d --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/dynamic/view/DynamicDetailActivity.java @@ -0,0 +1,1162 @@ +package com.chwl.app.community.dynamic.view; + +import android.content.ClipboardManager; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.PopupWindow; +import android.widget.TextView; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.chwl.app.photo.BigPhotoActivity; +import com.chwl.app.photo.PagerOption; +import com.chwl.core.XConstants; +import com.chwl.core.utils.CoreTextUtils; +import com.coorchice.library.utils.LogUtils; +import com.netease.nim.uikit.StatusBarUtil; +import com.netease.nim.uikit.business.session.emoji.IEmoticonSelectedListener; +import com.netease.nim.uikit.business.session.emoji.MoonUtil; +import com.trello.rxlifecycle3.android.ActivityEvent; +import com.chwl.app.R; +import com.chwl.app.UIHelper; +import com.chwl.app.avroom.ButtonItemFactory; +import com.chwl.app.base.BaseViewBindingActivity; +import com.chwl.app.common.widget.CircleImageView; +import com.chwl.app.common.widget.dialog.DialogManager; +import com.chwl.app.community.dynamic.adapter.CommentAdapter; +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.community.helper.ShareDynamicHelper; +import com.chwl.app.photo.DynamicImageAdapter; +import com.chwl.app.community.utils.ObjectTypeHelper; +import com.chwl.app.community.widget.DynamicNickDetailWidget; +import com.chwl.app.community.widget.ExpandableTextView; +import com.chwl.app.databinding.ActivityDynamicDetailBinding; +import com.chwl.app.ui.utils.ImageLoadUtilsV2; +import com.chwl.app.ui.widget.ButtonItem; +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil; +import com.chwl.app.utils.RegexUtil; +import com.chwl.app.utils.SpannableBuilder; +import com.chwl.app.utils.TimeUiUtils; +import com.chwl.core.auth.AuthModel; +import com.chwl.core.community.bean.Comment; +import com.chwl.core.community.bean.CommentResult; +import com.chwl.core.community.bean.DynamicMedia; +import com.chwl.core.community.bean.WorldDynamicBean; +import com.chwl.core.community.bean.comment.PopupParams; +import com.chwl.core.community.bean.comment.Reply; +import com.chwl.core.community.bean.comment.ReplyResult; +import com.chwl.core.community.dynamic.DynamicDetailModel; +import com.chwl.core.community.dynamic.DynamicModel; +import com.chwl.core.community.event.DynamicDetailFinishEvent; +import com.chwl.core.community.event.DynamicRefreshEvent; +import com.chwl.core.noble.NobleUtil; +import com.chwl.core.user.UserModel; +import com.chwl.core.user.bean.UserInfo; +import com.chwl.core.utils.net.BeanObserver; +import com.chwl.core.utils.net.DontWarnObserver; +import com.chwl.core.utils.net.RxHelper; +import com.chwl.library.utils.ListUtils; +import com.chwl.library.utils.LogUtil; +import com.chwl.library.utils.ResUtil; +import com.chwl.library.utils.SingleToastUtil; +import com.chwl.library.utils.keyboard.KeyboardVisibilityEvent; + +import org.greenrobot.eventbus.EventBus; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; + +/** + * create by lvzebiao @2019/11/25 + */ +public class DynamicDetailActivity extends BaseViewBindingActivity + implements IEmoticonSelectedListener, View.OnClickListener { + + private final static String EXTRA_DYNAMIC_ID = "extra_dynamic_id"; + private final static String EXTRA_WORLD_ID = "extra_world_id"; + private final static String EXTRA_NEED_KEYBOARD = "extra_need_keyboard"; + private final static String EXTRA_LIST_POSITION = "extra_list_position"; + + CircleImageView ivAvatar; + ImageView ivHeadWear; + DynamicNickDetailWidget widgetNickDetail; + TextView tvTime; + ImageView ivMore; + RecyclerView rvImage; + ExpandableTextView etvContent; + TextView tvCommentCount; + ConstraintLayout clOption; + ImageView ivLikePic; + TextView tvLikeCount; + ImageView ivCommentPic; + ImageView ivSharePic; + TextView tvCommentCountOption; + TextView tvFlagMiniWorld; + ConstraintLayout layoutRootMiniWorld; + TextView tvMiniWorldName; + private View viewLineDetailHeader; + + private long dynamicId; + + private long worldId; + + private CommentAdapter adapter; + /** + * 对评论进行回复 + */ + public final static int TYPE_TARGET_COMMENT = 1; + /** + * 对回复进行回复 + */ + public final static int TYPE_TARGET_REPLAY = 2; + + private int mReplyType; //0:评论动态, 评论及回复 1:对评论进行回复 2:对回复进行回复 + private int mReplyPosition = -1; + + private Reply cacheReply; + private boolean isErr = false; + + private WorldDynamicBean bean; + + private boolean isLoading; + + private boolean noMoreData; + + private String nextCommentId = null; + + private final static int COMMENT_SIZE = 10; + /** + * 动态被删除,标记为ture + */ + private boolean hasDeleteThisDynamic = false; + + /** + * @param event 统计事件 1-话题客态、2-个人主页、3-APP内分享、4-消息互动通知、5-linkedme 6-动态广场 + */ + public static void start(Context context, long dynamicId, long worldId, int listPosition, + boolean needKeyboard, int event) { + if (dynamicId == 0) { + LogUtils.e(ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_01)); + return; + } + String label = ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_02); + switch (event) { + case 1: + label = ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_03); + break; + case 2: + label = ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_04); + break; + case 3: + label = ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_05); + break; + case 4: + label = ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_06); + break; + case 5: + label = "linkedme"; + break; + case 6: + label = ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_07); + break; + } + + Intent intent = new Intent(context, DynamicDetailActivity.class); + intent.putExtra(EXTRA_DYNAMIC_ID, dynamicId); + intent.putExtra(EXTRA_WORLD_ID, worldId); + intent.putExtra(EXTRA_NEED_KEYBOARD, needKeyboard); + intent.putExtra(EXTRA_LIST_POSITION, listPosition); + context.startActivity(intent); + } + + public static void start(Context context, long dynamicId, long worldId, boolean needKeyboard, int event) { + start(context, dynamicId, worldId, -1, needKeyboard, event); + } + + public static void start(Context context, long dynamicId, long worldId, int event) { + start(context, dynamicId, worldId, false, event); + } + + private View mHeaderView; + + @Override + public void init() { + dynamicId = getIntent().getLongExtra(EXTRA_DYNAMIC_ID, 0L); + worldId = getIntent().getLongExtra(EXTRA_WORLD_ID, 0L); + initWhiteTitleBar(ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_09)); + initRecyclerView(); + initView(); + loadComment(true, true); + //是否需要弹起键盘 + if (getIntent().getBooleanExtra(EXTRA_NEED_KEYBOARD, false)) { + Single.timer(200, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .doOnSuccess(aLong -> showToCommentDynamicLayout()) + .subscribe(); + } + } + + private void initView() { + binding.tvSend.setOnClickListener(this); + binding.ivEmoji.setOnClickListener(this); + + binding.etReply.addTextChangedListener(new TextWatcher() { + + private int start; + private int count; + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + this.start = start; + this.count = count; + } + + @Override + public void afterTextChanged(Editable s) { + MoonUtil.replaceEmoticons(context, s, start, count); + + int editEnd = binding.etReply.getSelectionEnd(); + binding.etReply.removeTextChangedListener(this); + while (s.toString().length() > 500 && editEnd > 0) { + s.delete(editEnd - 1, editEnd); + editEnd--; + } + binding.etReply.setSelection(editEnd); + binding.etReply.addTextChangedListener(this); + + binding.tvSend.setEnabled(!CoreTextUtils.isEmptyText(s.toString())); + } + }); + + KeyboardVisibilityEvent.registerEventListener(this, isOpen -> { + isShowKeyboad = isOpen; + if (isOpen) { + binding.emoticonPickerView.setVisibility(View.GONE); + } else { + binding.emoticonPickerView.postDelayed(() -> { + if (binding.emoticonPickerView.getVisibility() == View.GONE) { + if (currNeedKeyboard) { + currNeedKeyboard = false; + Single.timer(200, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .doOnSuccess(aLong -> { + if (!currNeedKeyboard && !isShowKeyboad) { + clOption.setVisibility(View.VISIBLE); + mReplyPosition = -1; + } + }) + .subscribe(); + return; + } + clOption.setVisibility(View.VISIBLE); + mReplyPosition = -1; + } + currNeedKeyboard = false; + }, 210); + + } + }); + + binding.etReply.setOnFocusChangeListener((v, hasFocus) -> { + if (hasFocus) { + hideEmojiView(); + } + }); + + } + + private void initHeaderView() { + mHeaderView = LayoutInflater.from(this).inflate(R.layout.head_dynamic_detail, null); + ivAvatar = mHeaderView.findViewById(R.id.iv_avatar); + ivHeadWear = mHeaderView.findViewById(R.id.iv_head_wear); + widgetNickDetail = mHeaderView.findViewById(R.id.widget_nick_detail); + tvTime = mHeaderView.findViewById(R.id.tv_time_detail); + ivMore = mHeaderView.findViewById(R.id.iv_more); + etvContent = mHeaderView.findViewById(R.id.etv_content); + rvImage = mHeaderView.findViewById(R.id.rv_image); + tvCommentCount = mHeaderView.findViewById(R.id.tv_comment_count); + clOption = mHeaderView.findViewById(R.id.cl_option); + ivLikePic = mHeaderView.findViewById(R.id.iv_like_pic); + tvLikeCount = mHeaderView.findViewById(R.id.tv_like_count); + ivCommentPic = mHeaderView.findViewById(R.id.iv_comment_pic); + ivSharePic = mHeaderView.findViewById(R.id.iv_share_pic); + tvCommentCountOption = mHeaderView.findViewById(R.id.tv_comment_count_option); + viewLineDetailHeader = mHeaderView.findViewById(R.id.view_line_detail_header); + tvFlagMiniWorld = mHeaderView.findViewById(R.id.tv_flag_mini_world); + layoutRootMiniWorld = mHeaderView.findViewById(R.id.layout_root_mini_world); + tvMiniWorldName = mHeaderView.findViewById(R.id.tv_mini_world_name); + viewLineDetailHeader.setVisibility(View.VISIBLE); + } + + private boolean currNeedKeyboard = false; + + private boolean isShowKeyboad = false; + + private void initRecyclerView() { + initHeaderView(); + binding.rvListComment.setLayoutManager(new LinearLayoutManager(context)); + adapter = new CommentAdapter(); + adapter.setHeaderAndEmpty(true); + adapter.setHeaderView(mHeaderView); + adapter.setOnLoadMoreListener(() -> { + if (isLoading || noMoreData) { + return; + } + LogUtil.print("onLoadMoreRequested..."); + binding.rvListComment.postDelayed(new Runnable() { + @Override + public void run() { + if (ListUtils.isListEmpty(adapter.getData())) { + adapter.loadMoreEnd(); + } else { + if (!isErr) { + //成功获取更多数据 + LogUtil.print(ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_010)); + loadComment(false, false); + } else { + //获取更多数据失败 + isErr = true; + adapter.loadMoreFail(); + } + } + } + }, 1000); + }, binding.rvListComment); + + + adapter.setOnItemClickListener((a, view, position) -> { + + LogUtil.print(ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_011) + position); + + clickOneLevelComment(position); + }); + + adapter.setOnItemChildClickListener((adapter, view, position) -> { + if (view.getId() == R.id.tv_content) { + LogUtil.print(ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_012)); + clickOneLevelComment(position); + } + }); + adapter.setOnItemChildLongClickListener((a, view, position) -> { + + Comment comment = adapter.getDataItem(position); + if (comment == null) { + return false; + } + PopupParams params = new PopupParams(); + params.setType(1); + params.setGroupPostion(position); + params.setCopyContent(comment.getContent()); + params.setDeteleId(comment.getCommentId()); + params.setCommentOwnerUid(comment.getUid()); + showCopyPopup(view, params); + return true; + }); + binding.rvListComment.setAdapter(adapter); + + + //动态详情回复项的点击事件 + adapter.setOnCommentReplyItemChildClickListener(new CommentAdapter.OnCommentReplyItemChildClickListener() { + @Override + public void onCommentReplyItemChildClick(View view, int groupPosition, int childPosition) { + + LogUtil.print("groupPosition:" + groupPosition); + + LogUtil.print("childPosition:" + childPosition); + + Comment comment = adapter.getDataItem(groupPosition); + if (comment == null) { + return; + } + cacheReply = comment.getItemReply(childPosition); + if (cacheReply == null) { + return; + } + if (view.getId() == R.id.item_reply_constraintlayout || view.getId() == R.id.tv_content) { //整个item项,回复事件 + if (!UserModel.get().isMyseft(cacheReply.getUid()) && isBindPhone()) { + mReplyType = TYPE_TARGET_REPLAY; + mReplyPosition = groupPosition; + clOption.setVisibility(View.INVISIBLE); + binding.llReply.setVisibility(View.VISIBLE); + String nick = cacheReply.getNick(); + binding.etReply.setHint(String.format(getString(R.string.dy_reply_someone), + RegexUtil.getPrintableString(nick))); + binding.etReply.requestFocus(); + currNeedKeyboard = true; + showIME(binding.etReply); + } + } + } + + @Override + public void onCommentReplyItemChildLongClick(View view, int groupPosition, int childPosition) { + if (view.getId() == R.id.tv_content) { + Comment comment = adapter.getDataItem(groupPosition); + if (comment == null) { + return; + } + List list = comment.getReplyList(); + Reply reply = null; + if (childPosition >= 0 && childPosition < list.size()) { + reply = list.get(childPosition); + } + if (reply == null) { + return; + } + PopupParams params = new PopupParams(); + params.setType(2); + params.setGroupPostion(groupPosition); + params.setChildPosition(childPosition); + params.setCopyContent(reply.getContent()); + params.setCommentOwnerUid(reply.getUid()); + params.setDeteleId(reply.getReplyId()); + showCopyPopup(view, params); + } + } + + @Override + public void onLoadMoreClick(long commentId, long timestamp, int groupPosition) { + DynamicDetailModel.get().getReplyList(dynamicId, commentId, 5, String.valueOf(timestamp)) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(ReplyResult replyResult, String error) { + super.accept(replyResult, error); + if (error != null) { + toast(error); + return; + } + getMoreReplySuccess(replyResult, groupPosition); + } + }); + } + }); + + //刷新 + binding.refreshLayout.setOnRefreshListener(() -> { + if (isLoading) { + return; + } + loadComment(true, true); + }); + + } + + private void clickOneLevelComment(int position) { + if (!isBindPhone()) { + return; + } + mReplyType = TYPE_TARGET_COMMENT; + mReplyPosition = position; + clOption.setVisibility(View.INVISIBLE); + binding.llReply.setVisibility(View.VISIBLE); + Comment bean = adapter.getData().get(position); + binding.etReply.setHint(String.format(getString(R.string.dy_reply_someone), bean.getNick())); + binding.etReply.requestFocus(); + currNeedKeyboard = true; + showIME(binding.etReply); + } + + private void loadComment(boolean isRefresh, boolean reloadDetail) { + if (reloadDetail) { + loadDetail(); + } + if (isLoading) { + return; + } + isLoading = true; + if (isRefresh) { + isErr = false; + noMoreData = false; + nextCommentId = null; + } + DynamicDetailModel.get().getCommentList(dynamicId, nextCommentId, COMMENT_SIZE) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(CommentResult commentResult, String error) { + super.accept(commentResult, error); + binding.refreshLayout.setRefreshing(false); + isLoading = false; + if (error != null) { + isErr = true; + } else { + isErr = false; + } + List list = null; + if (commentResult != null) { + list = commentResult.getCommentList(); + nextCommentId = String.valueOf(commentResult.getNextTimestamp()); + } + + if (list == null) { + list = new ArrayList<>(); + } + + if (isRefresh) { + adapter.setNewData(list); + adapter.disableLoadMoreIfNotFullPage(binding.rvListComment); + } else { + adapter.addData(list); + } + + if (ListUtils.isListEmpty(list)) { + noMoreData = true; + } + + if (!ListUtils.isListEmpty(adapter.getData()) && ListUtils.isListEmpty(list)) { + adapter.loadMoreEnd(); + } else { + adapter.loadMoreComplete(); + } + + viewLineDetailHeader.setVisibility(View.VISIBLE); + if (adapter.getData().isEmpty()) { + viewLineDetailHeader.setVisibility(View.INVISIBLE); + View emptyView = getLayoutInflater().inflate(R.layout.dy_empty_dynamic_comment, null); + + ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + UIUtil.dip2px(context, 260)); + emptyView.setLayoutParams(layoutParams); + ((ImageView) emptyView.findViewById(R.id.no_data_icon)) + .setImageResource(R.drawable.icon_common_failure); + ((TextView) emptyView.findViewById(R.id.no_data_text)) + .setText(R.string.dy_empty_comment_tips); + adapter.setEmptyView(emptyView); + } + + } + }); + } + + private void showCopyPopup(View v, PopupParams params) { + + View view = LayoutInflater.from(this).inflate(R.layout.popup_dy_comment, null); + PopupWindow popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + TextView tvCopy = view.findViewById(R.id.tv_copy); + tvCopy.setOnClickListener(v1 -> { + ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + cm.setText(params.getCopyContent()); + toast(R.string.copy_success); + popupWindow.dismiss(); + }); + View llContainer = view.findViewById(R.id.ll_container); + TextView tvDelete = view.findViewById(R.id.tv_delete); + TextView tvReport = view.findViewById(R.id.tv_report); + + //如果是帖子发布者uid + long dynamicOwnerUid = 0; + if (bean != null) { + dynamicOwnerUid = bean.getUid(); + } + //这里就不画.9图了,直接采用2张不同背景图来处理 + llContainer.setBackgroundResource(R.drawable.bg_dy_popup_comment); + tvDelete.setVisibility(View.GONE); + tvReport.setVisibility(View.GONE); + if (UserModel.get().isMyseft(dynamicOwnerUid)) { + tvDelete.setVisibility(View.VISIBLE); + if (!UserModel.get().isMyseft(params.getCommentOwnerUid())) { + //如果是自己发的动态,但是不是自己的评论,举报 删除都有 + tvReport.setVisibility(View.VISIBLE); + llContainer.setBackgroundResource(R.drawable.bg_dy_popup_comment_three); + } + } else { + if (UserModel.get().isMyseft(params.getCommentOwnerUid())) { + tvDelete.setVisibility(View.VISIBLE); + } else { + tvReport.setVisibility(View.VISIBLE); + } + } + + tvDelete.setOnClickListener(v1 -> { + popupWindow.dismiss(); + DynamicDetailModel.get().deleteComment(params.getDeteleId()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error != null) { + toast(error); + return; + } + deleteCommentSuccess(params); + } + }); + }); + + tvReport.setOnClickListener(v1 -> { + popupWindow.dismiss(); + UIHelper.showReportPage(context, params.getCommentOwnerUid(), XConstants.REPORT_TYPE_DYNAMICCOMMENT); + }); + + popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + popupWindow.setOutsideTouchable(true); + popupWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + int[] vLoc = new int[2]; + v.getLocationInWindow(vLoc); + int offsetHeight = 0; + int minHeight = UIUtil.dip2px(context, 120f); + if (vLoc[1] < minHeight) { + offsetHeight = minHeight - vLoc[1]; + } + popupWindow.showAsDropDown(v, UIUtil.dip2px(context, 40), -v.getHeight() + - popupWindow.getContentView().getMeasuredHeight() + offsetHeight); + + } + + + private void loadDetail() { + DynamicDetailModel.get().getDetail(dynamicId, worldId) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(WorldDynamicBean bean, String error) { + super.accept(bean, error); + if (error != null) { + toast(error); + finish(); + return; + } + showDynamicDetails(bean); + } + }); + } + + private void showDynamicDetails(WorldDynamicBean info) { + bean = info; + if (bean == null) { + return; + } + ImageLoadUtilsV2.loadAvatar(ivAvatar, bean.getAvatar()); + widgetNickDetail.setData(bean); + + //更多 + ivMore.setOnClickListener(v -> { + header_more(); + }); + + + tvTime.setText(TimeUiUtils.getDynamicUi(bean.getPublishTime())); + etvContent.setVisibility(View.GONE); + etvContent.setEventType(3); + if (!TextUtils.isEmpty(bean.getContent())) { + etvContent.setVisibility(View.VISIBLE); + int iconWidth = UIUtil.dip2px(context, 32); + int iconHeight = UIUtil.dip2px(context, 15); + CharSequence formatText = DynamicUiHelper.formatFirstDynamicContent( + bean, etvContent.mTv, iconWidth, iconHeight); + etvContent.setText(formatText); + } + + initImageRv(); + + setLikeCount(false); + + updateCommentCount(); + + //头饰 贵族头饰 + String headwearEffect = bean.getHeadwearEffect(); + String headwearPic = bean.getHeadwearPic(); + String micDecorate = bean.getMicDecorate(); + if (!TextUtils.isEmpty(headwearEffect)) { + NobleUtil.loadHeadWear(headwearEffect, ivHeadWear); + } else if (!TextUtils.isEmpty(headwearPic)) { + NobleUtil.loadHeadWear(headwearPic, ivHeadWear); + } else if (!TextUtils.isEmpty(micDecorate)) { + NobleUtil.loadResource(micDecorate, ivHeadWear); + } else { + ivHeadWear.setImageDrawable(null); + } + + View.OnClickListener infoListener = v -> { + if (bean == null) { + return; + } + UIHelper.showUserInfoAct(context, bean.getUid()); + }; + ivHeadWear.setOnClickListener(infoListener); + widgetNickDetail.setOnClickListener(infoListener); + + //话题显示 + layoutRootMiniWorld.setVisibility(View.GONE); +// layoutRootMiniWorld.setVisibility(bean.getWorldId() > 0 ? View.VISIBLE : View.GONE); +// if (!TextUtils.isEmpty(bean.getWorldName())) { +// tvMiniWorldName.setText("#" + bean.getWorldName()); +// } +// //去看看 +// tvFlagMiniWorld.setVisibility(bean.isInWorld() ? View.GONE : View.GONE); + + +// tvMiniWorldName.setOnClickListener(v -> { +// TopicMainActivity.start(context, String.valueOf(bean.getWorldId())); +// }); + + //点赞 + ivLikePic.setOnClickListener(v -> { + header_like(); + }); + + //评论 + ivCommentPic.setOnClickListener(v -> { + showToCommentDynamicLayout(); + }); + + //分享动态 + ivSharePic.setOnClickListener(v -> { + new ShareDynamicHelper(DynamicDetailActivity.this) + .share(bean, worldId); + }); + + } + + /** + * header - 更多 + */ + private void header_more() { + List list = new ArrayList<>(); + if (!UserModel.get().isMyseft(bean.getUid())) { + ButtonItem item = new ButtonItem(getString(R.string.me_shield_dynamic), () -> { + UserModel.get().addReport(bean.getDynamicId(), 0) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + getDialogManager().dismissDialog(); + toast(error); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + toast(ResUtil.getString(R.string.me_shield_success)); + EventBus.getDefault().post(new DynamicRefreshEvent()); + finish(); + } + }); + }); + list.add(item); + } + if (!UserModel.get().isMyseft(bean.getUid())) { + ButtonItem blackListItem = ButtonItemFactory.createAddToBlackListItem( + getDialogManager(), String.valueOf(bean.getUid())); + list.add(blackListItem); + } + if (!UserModel.get().isMyseft(bean.getUid())) { + ButtonItem item = new ButtonItem(getString(R.string.me_report_dynamic), () -> { + UIHelper.showReportPage(context, bean.getUid(), + XConstants.REPORT_TYPE_WORLDDYNAMIC); + }); + list.add(item); + } + if (UserModel.get().isMyseft(bean.getUid()) || + isThisWorldOwner(bean)) { + ButtonItem item = new ButtonItem(ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_020), () -> deleteDynamic(bean)); + list.add(item); + } + getDialogManager().showCommonPopupDialog(list, getString(R.string.cancel)); + } + + /** + * header - 点赞 + */ + private void header_like() { + ivLikePic.setEnabled(false); + int status = bean.isLike() ? 0 : 1; + DynamicModel.get().like(worldId, dynamicId, bean.getUid(), status, 3) + .compose(RxHelper.bindContext(context)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + ivLikePic.setEnabled(true); + if (error != null) { + SingleToastUtil.showToast(error); + } else { + if (bean == null) { + return; + } + if (status == 1) { + bean.setLikeCount(bean.getLikeCount() + 1); + } else { + bean.setLikeCount(bean.getLikeCount() - 1); + } + bean.setLike(status == 1); + setLikeCount(true); + } + } + }); + } + + private void deleteDynamic(WorldDynamicBean bean) { + getDialogManager().showOkCancelWithTitleDialog(ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_023), + new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + if (bean == null) { + return; + } + DynamicModel.get().delete(worldId, bean.getDynamicId()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error != null) { + toast(error); + } else { + toast(R.string.delete_success); + hasDeleteThisDynamic = true; + finish(); + } + } + }); + + } + }); + } + + private boolean isThisWorldOwner(WorldDynamicBean bean) { + return bean != null && AuthModel.get().getCurrentUid() == bean.getWorldUid(); + } + + private void initImageRv() { + List imageUrl = bean.getDynamicResList(); + if (ListUtils.isListEmpty(imageUrl)) { + rvImage.setVisibility(View.GONE); + return; + } + rvImage.setVisibility(View.VISIBLE); + rvImage.setNestedScrollingEnabled(false); + rvImage.setLayoutManager(new GridLayoutManager(this, imageUrl.size() > 2 ? 3 : imageUrl.size())); + + int imageBorder = UIUtil.getScreenWidth(context) * + ImageUiHelper.BORDER_MIN / ImageUiHelper.BORDER_MAX; + int divider = UIUtil.dip2px(context, 10); + 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; + } + rvImage.setLayoutParams(params); + + 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(DynamicDetailActivity.this, ObjectTypeHelper.mediaToCustomList(imageUrl), + position, option); + } + ); + rvImage.setAdapter(adapter); + } + + private void setLikeCount(boolean isAnim) { + int likeCount = bean.getLikeCount(); + String likeCountStr; + if (likeCount < 0) { + likeCountStr = "0"; + } else if (likeCount >= 100000) { + likeCountStr = "99999+"; + } else { + likeCountStr = String.valueOf(likeCount); + } + tvLikeCount.setText(likeCountStr); + + if (bean.isLike()) { + ivLikePic.setImageResource(R.drawable.icon_dy_list_like); + } else { + ivLikePic.setImageResource(R.drawable.icon_dy_list_like_false); + } + } + + private void updateCommentCount() { + if (bean == null) { + return; + } + SpannableBuilder builder = new SpannableBuilder(); + if (bean.getCommentCount() < 0) { + bean.setCommentCount(0); + } + String commentCountStr = String.valueOf(bean.getCommentCount()); + if (bean.getCommentCount() >= 100000) { + commentCountStr = "99999+"; + } + String comment = ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_024) + commentCountStr + ")"; + tvCommentCount.setText(comment); + tvCommentCountOption.setText(commentCountStr); + } + + @Override + public void onClick(View view) { + if (bean == null) { + return; + } + switch (view.getId()) { + + case R.id.tv_send: + binding.tvSend.setEnabled(false); + String content = binding.etReply.getText().toString(); + if (mReplyType == TYPE_TARGET_COMMENT || mReplyType == TYPE_TARGET_REPLAY) { + //对一级评论回复 + long paramId = 0; + if (mReplyType == TYPE_TARGET_REPLAY) { + if (cacheReply != null) { + paramId = cacheReply.getReplyId(); + } + } else { + paramId = adapter.getItemCommentId(mReplyPosition); + } + DynamicDetailModel.get().reply(dynamicId, paramId, content) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(Reply reply, String error) { + super.accept(reply, error); + if (error != null) { + toast(error); + return; + } + replySuccess(reply, mReplyPosition); + } + }); + } else { + DynamicDetailModel.get().publishComment(dynamicId, content) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error != null) { + toast(error); + return; + } + onAddCommentSuccess(); + } + }); + } + break; + + case R.id.iv_emoji: + showEmojiView(); + break; + } + } + + private void onAddCommentSuccess() { + toast(ResUtil.getString(R.string.dynamic_view_dynamicdetailactivity_026)); + recoverBottomView(); + loadComment(true, false); + if (bean != null) { + bean.setCommentCount(bean.getCommentCount() + 1); + updateCommentCount(); + } + } + + private void recoverBottomView() { + hideIME(binding.etReply); + mReplyType = 0; + binding.etReply.setHint(R.string.dy_pub_comment); + binding.etReply.setText(""); + clOption.setVisibility(View.VISIBLE); + binding.emoticonPickerView.setVisibility(View.GONE); + } + + private void replySuccess(Reply result, int replyPosition) { + recoverBottomView(); + Comment listBean = adapter.getDataItem(mReplyPosition); + if (listBean == null) { + return; + } + if (result.getParentId() != listBean.getCommentId()) { + //一般是通过 + return; + } + if (listBean.getReplyInfo().getLeftCount() <= 0) { + //如果已经没有下一页回复了,回复成功后,直接添加一项 + listBean.addReply(result); + } + //更新下,剩余的回复数量 + int newLeftCount = result.getReplyCount() - listBean.getReplyList().size(); + if (newLeftCount < 0) { + newLeftCount = 0; + } + listBean.getReplyInfo().setLeftCount(newLeftCount); + adapter.notifyItemChanged(replyPosition + 1); + if (bean != null) { + bean.setCommentCount(bean.getCommentCount() + 1); + updateCommentCount(); + } + } + + public void getMoreReplySuccess(ReplyResult newReplyInfo, int groupPosition) { + Comment listBean = adapter.getDataItem(groupPosition); + if (listBean == null) { + return; + } + ReplyResult oldReplyInfo = listBean.getReplyInfo(); + oldReplyInfo.setLeftCount(newReplyInfo.getLeftCount()); + oldReplyInfo.setNextTimestamp(newReplyInfo.getNextTimestamp()); + List oldReplyList = oldReplyInfo.getReplyList(); + if (!ListUtils.isListEmpty(newReplyInfo.getReplyList())) { + oldReplyList.addAll(newReplyInfo.getReplyList()); + } + adapter.notifyItemChanged(groupPosition + 1); + } + + + @Override + public void onEmojiSelected(String key) { + try { + Editable mEditable = binding.etReply.getText(); + if (key.equals("/DEL")) { + binding.etReply.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + } else { + int start = binding.etReply.getSelectionStart(); + int end = binding.etReply.getSelectionEnd(); + start = (start < 0 ? 0 : start); + end = (start < 0 ? 0 : end); + mEditable.replace(start, end, key); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public void onStickerSelected(String categoryName, String stickerName) { + + } + + private void deleteCommentSuccess(PopupParams params) { + toast(R.string.delete_success); + if (params.getType() == 1) { + //删除评论 + if (bean != null) { + Comment comment = adapter.getDataItem(params.getGroupPostion()); + if (comment == null) { + return; + } + ReplyResult result = comment.getReplyInfo(); + int replyCount = result.getLeftCount(); + if (!ListUtils.isListEmpty(result.getReplyList())) { + replyCount += result.getReplyList().size(); + } + bean.setCommentCount(bean.getCommentCount() - replyCount - 1); + updateCommentCount(); + } + adapter.safeDelete(params.getGroupPostion()); + } else if (params.getType() == 2) { + //删除评论中的回复 + if (bean != null) { + bean.setCommentCount(bean.getCommentCount() - 1); + updateCommentCount(); + } + Comment comment = adapter.getDataItem(params.getGroupPostion()); + if (comment == null) { + return; + } + List list = comment.getReplyList(); + if (params.getChildPosition() >= 0 && params.getChildPosition() < list.size()) { + list.remove(params.getChildPosition()); + adapter.notifyDataSetChanged(); + } + } + } + + private void hideEmojiView() { + binding.emoticonPickerView.setVisibility(View.GONE); + } + + private void showEmojiView() { + binding.etReply.clearFocus(); + hideIME(binding.etReply); + binding.emoticonPickerView.postDelayed(() -> { + binding.emoticonPickerView.setVisibility(View.VISIBLE); + binding.emoticonPickerView.show(this); + }, 200); + } + + /** + * 展示对动态进行评论的输入布局 + */ + private void showToCommentDynamicLayout() { + if (!isBindPhone()) { + return; + } + mReplyType = 0; + mReplyPosition = -1; + clOption.setVisibility(View.INVISIBLE); + binding.llReply.setVisibility(View.VISIBLE); + binding.etReply.requestFocus(); + binding.etReply.setHint(R.string.dy_pub_comment); + showIME(binding.etReply); + } + + @Override + public void finish() { + int listPosition = getIntent().getIntExtra(EXTRA_LIST_POSITION, -1); + if (listPosition >= 0 && bean != null) { + EventBus.getDefault().post(new DynamicDetailFinishEvent(listPosition, bean, hasDeleteThisDynamic)); + } + super.finish(); + } + + private boolean isBindPhone() { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + SingleToastUtil.showToast(ResUtil.getString(R.string.yizhuan_xchat_android_constants_xchatconstants_016)); + return false; + } + return true; + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/helper/CalcSize.java b/app/src/module_community/java/com/chwl/app/community/helper/CalcSize.java new file mode 100644 index 000000000..8a1e74534 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/helper/CalcSize.java @@ -0,0 +1,24 @@ +package com.chwl.app.community.helper; + +import androidx.annotation.Keep; + +/** + * create by lvzebiao @2020/1/3 + */ +@Keep +public class CalcSize { + + public CalcSize(int size) { + width = size; + height = size; + } + + public CalcSize() { + this(0); + } + + public int width; + + public int height; + +} diff --git a/app/src/module_community/java/com/chwl/app/community/helper/DynamicUiHelper.java b/app/src/module_community/java/com/chwl/app/community/helper/DynamicUiHelper.java new file mode 100644 index 000000000..01dcc458b --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/helper/DynamicUiHelper.java @@ -0,0 +1,30 @@ +package com.chwl.app.community.helper; + +import android.text.TextUtils; +import android.widget.TextView; + +import com.chwl.app.avroom.widget.MessageView; +import com.chwl.app.ui.widget.TextSpannableBuilder; +import com.chwl.core.community.bean.WorldDynamicBean; + +/** + * create by lvzebiao @2019/12/4 + */ +public class DynamicUiHelper { + + public static CharSequence formatFirstDynamicContent(WorldDynamicBean item, TextView textView, + int iconWidth, int iconHeight) { + TextSpannableBuilder builder = new TextSpannableBuilder(textView); +// if (item.isFirstDynamic()) { +// builder.append(textView.getResources().getDrawable(R.drawable.icon_dy_first_dynamic), iconWidth, +// iconHeight); +// } + if (!TextUtils.isEmpty(item.getContent())) { + builder.append(item.getContent()); + } else { + builder.append(" "); + } + return builder.build(); + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/helper/ImageUiHelper.java b/app/src/module_community/java/com/chwl/app/community/helper/ImageUiHelper.java new file mode 100644 index 000000000..95f5fd88b --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/helper/ImageUiHelper.java @@ -0,0 +1,73 @@ +package com.chwl.app.community.helper; + +import com.chwl.core.community.bean.DynamicMedia; + +/** + * create by lvzebiao @2020/1/3 + */ +public class ImageUiHelper { + /** + * 图片最大宽度和父布局比例 + * 0.68 + */ + public final static int BORDER_MIN = 68; + /** + * 图片最大宽度和父布局比例 + * 0.68 + */ + public final static int BORDER_MAX = 100; + + /** + * 比例最大2.5,我们用分子分母来表示 + */ + public final static int OFFSET_MIN = 2; + + /** + * 比例最大2.5,我们用分子分母来表示 + */ + public final static int OFFSET_MAX = 5; + + /** + * + * @param width - + * @param height - + * @param border 图片展示的最大边界 + * @return - + */ + public static CalcSize calcImage(int width, int height, int border) { + CalcSize calcSize = new CalcSize(); + int singleImageWidth = border; //单图宽 + int singleImageHeight = border; //单图高 + if (width >= height) { + //横图的情况 + if (height * OFFSET_MAX <= width * OFFSET_MIN) { + singleImageHeight = border * OFFSET_MIN / OFFSET_MAX; + } else { + if (width > 0) { + singleImageHeight = border * height / width; + } + } + } else { + //竖图的情况 + //判断比例是否超过2.5 + if (width * OFFSET_MAX <= height * OFFSET_MIN) { + singleImageWidth = border * OFFSET_MIN / OFFSET_MAX; + } else { + if (height > 0) { + singleImageWidth = border * width / height; + } + } + } + calcSize.width = singleImageWidth; + calcSize.height = singleImageHeight; + return calcSize; + } + + public static CalcSize calcImage(DynamicMedia media, int border) { + if (media == null) { + return new CalcSize(); + } + return calcImage(media.getWidth(), media.getHeight(), border); + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/helper/ShareDynamicHelper.java b/app/src/module_community/java/com/chwl/app/community/helper/ShareDynamicHelper.java new file mode 100644 index 000000000..bf9f5affd --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/helper/ShareDynamicHelper.java @@ -0,0 +1,30 @@ +package com.chwl.app.community.helper; + +import android.app.Activity; +import com.chwl.app.R; +import com.chwl.core.community.bean.WorldDynamicBean; +import com.chwl.library.utils.ResUtil; +import com.chwl.library.utils.SingleToastUtil; + +/** + * create by lvzebiao @2019/11/28 + */ +public class ShareDynamicHelper { + + private Activity activity; + + public ShareDynamicHelper(Activity activity) { + this.activity = activity; + } + + public void share(WorldDynamicBean bean) { + share(bean, bean.getWorldId()); + } + + public void share(WorldDynamicBean bean, long worldId) { + if (bean.isChecking()) { + SingleToastUtil.showToast(ResUtil.getString(R.string.community_helper_sharedynamichelper_01)); + return; + } + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/holder/DynamicSysHolder.java b/app/src/module_community/java/com/chwl/app/community/holder/DynamicSysHolder.java new file mode 100644 index 000000000..be12dd20a --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/holder/DynamicSysHolder.java @@ -0,0 +1,133 @@ +package com.chwl.app.community.holder; + +import android.graphics.Color; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextPaint; +import android.text.style.AbsoluteSizeSpan; +import android.text.style.ForegroundColorSpan; +import android.text.style.MetricAffectingSpan; +import android.widget.TextView; + +import androidx.annotation.Keep; + +import com.alibaba.fastjson.JSON; +import com.chwl.core.msg.sys.bean.ErbanSysMsgComponent; +import com.chwl.core.msg.sys.bean.ErbanSysMsgInfo; +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.chwl.app.R; +import com.chwl.app.ui.im.RouterHandler; +import com.chwl.core.community.attachment.DynamicSysAttachment; +import com.chwl.core.msg.sys.ErbanSysMsgLayout; +import com.chwl.library.utils.SizeUtils; + +import java.util.List; +import java.util.Objects; + +@Keep +public class DynamicSysHolder extends MsgViewHolderBase { + private TextView tvTime; + private TextView tvContent; + private TextView tvTitle; + + public DynamicSysHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.item_dynamic_sys; + } + + @Override + protected void inflateContentView() { + tvTitle = findViewById(R.id.tv_notice_label); + tvTime = findViewById(R.id.tv_time_dynamic_is_pass); + tvContent = findViewById(R.id.tv_content_dynamic_is_pass); + } + + private ErbanSysMsgInfo erbanSysMsgInfo; + @Override + protected void bindContentView() { + DynamicSysAttachment dynamicSysAttachment = (DynamicSysAttachment) message.getAttachment(); + if (dynamicSysAttachment == null) { + return; + } + erbanSysMsgInfo = dynamicSysAttachment.getErbanSysMsgInfo(); + if (erbanSysMsgInfo == null) { + return; + } + + String layout = erbanSysMsgInfo.getLayout(); + ErbanSysMsgLayout erbanSysMsgLayout; + try { + erbanSysMsgLayout = JSON.parseObject(layout, ErbanSysMsgLayout.class); + + } catch (Exception ex) { // json解析出错 + ex.printStackTrace(); + return; + } + // title + setupView(tvTitle, erbanSysMsgLayout.getTitle()); + // timestamp + setupView(tvTime, erbanSysMsgLayout.getTime()); + // content + List erbanSysMsgLayoutContent = erbanSysMsgLayout.getContents(); + if (erbanSysMsgLayoutContent != null) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + for (ErbanSysMsgComponent erbanSysMsgComponent : erbanSysMsgLayoutContent) { + int start = spannableStringBuilder.length(); + String msgBody = erbanSysMsgComponent.getContent(); + if (Objects.equals(msgBody, "/r/n")) { + msgBody = "\r\n"; + spannableStringBuilder.append(msgBody); + continue; + } + spannableStringBuilder.append(msgBody); + if (erbanSysMsgComponent.getFontColor() != null) { + spannableStringBuilder.setSpan(new ForegroundColorSpan(Color.parseColor(erbanSysMsgComponent.getFontColor())), + start, spannableStringBuilder.length(), + Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + if (erbanSysMsgComponent.getFontSize() > 0) { + spannableStringBuilder.setSpan(new AbsoluteSizeSpan(SizeUtils.sp2px(tvContent.getContext(), erbanSysMsgComponent.getFontSize() + 0.5F)), + start, spannableStringBuilder.length(), + Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + spannableStringBuilder.setSpan( + new MetricAffectingSpan() { + @Override + public void updateMeasureState(TextPaint p) { + + } + + @Override + public void updateDrawState(TextPaint tp) { + tp.setFakeBoldText(erbanSysMsgComponent.isFontBold()); + } + }, + start, spannableStringBuilder.length(), + Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + tvContent.setText(spannableStringBuilder); + } + + } + + public void setupView(TextView view, ErbanSysMsgComponent erbanSysMsgComponent) { + if (erbanSysMsgComponent != null) { + setupComponent(view, erbanSysMsgComponent.getContent(), erbanSysMsgComponent.getFontColor(), erbanSysMsgComponent.getFontSize(), + erbanSysMsgComponent.getRouterType(), erbanSysMsgComponent.getRouterValue()); + } + } + + public void setupComponent(TextView view, String text, String textColor, float fontSize, int routerType, int routerValue) { + view.setText(text); + view.setTextColor(Color.parseColor(textColor)); + view.setTextSize(fontSize); + if (routerType > 0) { + view.setOnClickListener(v -> RouterHandler.handle(context, routerType, String.valueOf(routerValue))); + } + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/im/WorldDynamicShareViewHolder.java b/app/src/module_community/java/com/chwl/app/community/im/WorldDynamicShareViewHolder.java new file mode 100644 index 000000000..0040a4c4d --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/im/WorldDynamicShareViewHolder.java @@ -0,0 +1,103 @@ +package com.chwl.app.community.im; + +import android.text.TextUtils; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.Keep; + +import com.netease.nim.uikit.business.session.viewholder.MsgViewHolderBase; +import com.netease.nim.uikit.common.ui.recyclerview.adapter.BaseMultiItemFetchLoadAdapter; +import com.chwl.app.R; +import com.chwl.app.community.dynamic.view.DynamicDetailActivity; +import com.chwl.app.ui.utils.ImageLoadUtilsV2; +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil; +import com.chwl.core.community.im.DynamicImMsg; +import com.chwl.core.community.im.WorldDynamicAttachment; +import com.chwl.library.utils.ResUtil; + +/** + * create by lvzebiao @2019/11/25 + */ +@Keep +public class WorldDynamicShareViewHolder extends MsgViewHolderBase { + + private ImageView rivCover; + + private TextView tvTitle; + + private TextView tvContent; + + private TextView tvShareText; + + private ViewGroup container; + + public WorldDynamicShareViewHolder(BaseMultiItemFetchLoadAdapter adapter) { + super(adapter); + } + + @Override + protected int getContentResId() { + return R.layout.view_holder_world_dynamic_share; + } + + @Override + protected void inflateContentView() { + rivCover = findViewById(R.id.riv_cover); + tvTitle = findViewById(R.id.tv_title); + tvContent = findViewById(R.id.tv_content); + tvShareText = findViewById(R.id.tv_share_text); + container = findViewById(R.id.cl_container_dynamic); + int layoutWidth = UIUtil.getScreenWidth(context) - UIUtil.dip2px(context, 150); + ViewGroup.LayoutParams params = container.getLayoutParams(); + params.width = layoutWidth; + container.setLayoutParams(params); + if (isReceivedMessage()) { + tvTitle.setTextColor(context.getResources().getColor(R.color.color_333333)); + tvShareText.setTextColor(context.getResources().getColor(R.color.color_333333)); + tvContent.setTextColor(context.getResources().getColor(R.color.color_9E9E9E)); + } else { + tvTitle.setTextColor(context.getResources().getColor(R.color.white)); + tvShareText.setTextColor(context.getResources().getColor(R.color.white)); + tvContent.setTextColor(context.getResources().getColor(R.color.white_transparent_80)); + } + } + + @Override + protected void bindContentView() { + try { + if (!(message.getAttachment() instanceof WorldDynamicAttachment)) { + return; + } + WorldDynamicAttachment worldDynamicAttachment = (WorldDynamicAttachment) message.getAttachment(); + if (worldDynamicAttachment == null) { + return; + } + DynamicImMsg dynamicImMsg = worldDynamicAttachment.getDynamicImMsg(); + ImageLoadUtilsV2.loadAvatar(rivCover, dynamicImMsg.getImageUrl()); + + String nick = dynamicImMsg.getNick(); + if (TextUtils.isEmpty(nick)) { + nick = ""; + } else if (nick.length() >= 4) { + try { + nick = nick.substring(0, 2) + "..."; + } catch (Exception ex) { + ex.printStackTrace(); + } + } + tvTitle.setText(nick); + String content = dynamicImMsg.getContent(); + if (TextUtils.isEmpty(dynamicImMsg.getContent())) { + content = ResUtil.getString(R.string.community_im_worlddynamicshareviewholder_01); + } + tvContent.setText(content); + container.setOnClickListener(v -> + DynamicDetailActivity.start(context, dynamicImMsg.getDynamicId(), dynamicImMsg.getWorldId(), 3)); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/publish/ImageAdapter.java b/app/src/module_community/java/com/chwl/app/community/publish/ImageAdapter.java new file mode 100644 index 000000000..7867f8169 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/publish/ImageAdapter.java @@ -0,0 +1,46 @@ +package com.chwl.app.community.publish; + +import android.widget.ImageView; + +import androidx.annotation.Nullable; + +import com.bumptech.glide.load.resource.bitmap.CenterCrop; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.netease.nim.uikit.support.glide.GlideApp; +import com.chwl.app.R; +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil; +import com.chwl.core.community.bean.PublishItem; + +import java.util.List; + +public class ImageAdapter extends BaseQuickAdapter { + + + public ImageAdapter(int layoutResId, @Nullable List data) { + super(layoutResId, data); + } + + @Override + protected void convert(BaseViewHolder helper, PublishItem item) { + helper.addOnClickListener(R.id.iv_delete); + helper.setVisible(R.id.iv_delete, !item.isAddItem()); + ImageView ivPhoto = helper.getView(R.id.iv_photo); + if (item.getButtonType() == PublishItem.BUTTON_TYPE_ADD_ITEM) { + ivPhoto.setImageResource(R.drawable.icon_dy_add_image); + } else { + GlideApp.with(ivPhoto.getContext()) + .asBitmap() + .load(item.getPath()) + .transform(new CenterCrop(), + new RoundedCorners(UIUtil.dip2px(ivPhoto.getContext(), 8))) + .placeholder(R.drawable.default_cover) + .error(R.drawable.default_cover) + .into(ivPhoto); + } + + helper.setGone(R.id.iv_gif_tag, item.getFileTag() == 1); + + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/publish/presenter/PublishPresenter.java b/app/src/module_community/java/com/chwl/app/community/publish/presenter/PublishPresenter.java new file mode 100644 index 000000000..8f3d88669 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/publish/presenter/PublishPresenter.java @@ -0,0 +1,222 @@ +package com.chwl.app.community.publish.presenter; + +import android.text.TextUtils; + +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpPresenter; +import com.chwl.app.community.publish.view.IPublishView; +import com.chwl.core.Constants; +import com.chwl.core.auth.AuthModel; +import com.chwl.core.community.ImageUploadConfig; +import com.chwl.core.community.PublishModel; +import com.chwl.core.community.bean.DynamicMedia; +import com.chwl.core.community.bean.MiniWorldChooseInfo; +import com.chwl.core.community.bean.PublishBody; +import com.chwl.core.file.FileModel; +import com.chwl.core.utils.DirectoryHelper; +import com.chwl.core.utils.net.DontWarnObserver; +import com.chwl.core.utils.net.RxHelper; +import com.chwl.library.base.PresenterEvent; +import com.chwl.library.utils.ListUtils; +import com.chwl.library.utils.ResUtil; +import com.chwl.library.utils.file.JXFileUtils; +import com.chwl.library.utils.image.JXImageUtils; +import com.example.matisse.internal.entity.CustomItem; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.SingleObserver; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.SingleSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Function; + +/** + * create by lvzebiao @2019/11/12 + */ +public class PublishPresenter extends BaseMvpPresenter { + + private PublishBody publishBody; + private Disposable mImageUploadSubscribe; + + private boolean isOriginalImage; + + private MiniWorldChooseInfo miniWorldChooseInfo = new MiniWorldChooseInfo(); + + public void publishDy(List list, long worldId, String content, boolean isOriginalImage) { + publishBody = new PublishBody(); + List uploadList = new ArrayList<>(list); + int type = ListUtils.isListEmpty(uploadList) ? 0 : 2; + publishBody.setType(type); + publishBody.setUid(AuthModel.get().getCurrentUid()); + publishBody.setContent(content); + if (worldId > 0) { + publishBody.setWorldId(worldId); + } + this.isOriginalImage = isOriginalImage; + uploadImage(uploadList) + .flatMap((Function>) s -> + PublishModel.get().publish(publishBody)) + .subscribe(new DontWarnObserver() { + @Override + public void acceptThrowable(String s, Throwable throwable) { + super.acceptThrowable(s, throwable); + if (throwable != null) { + throwable.printStackTrace(); + dealUploadFileError(throwable); + } else { + if (getMvpView() != null) { + getMvpView().onPublishSuccess(); + } + } + } + }); + } + + private Single uploadImage(List imagePaths) { + upload(imagePaths); + return Single.create(emitter -> + mImageUploadSubscribe = Observable.interval(500, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .filter(aLong -> imagePaths != null && imagePaths.size() == 0) + .subscribe(aLong -> { + emitter.onSuccess(""); + if (mImageUploadSubscribe != null) { + mImageUploadSubscribe.dispose(); + } + })); + } + + private void upload(List imagePaths) { + if (imagePaths == null || imagePaths.size() == 0) { + return; + } + DynamicMedia item = imagePaths.get(0); + String file = item.getLocalFilePath(); + Single.create((SingleOnSubscribe) e -> { + long fileLength = JXFileUtils.getFileLength(file); + LogUtil.print(ResUtil.getString(R.string.publish_presenter_publishpresenter_01) + fileLength); + String compressFile = null; + if (!isOriginalImage && fileLength > ImageUploadConfig.MAX_FILE_SIZE) { + JXImageUtils.CompressResult result = JXImageUtils.compressImagePxAndQuality( + file, DirectoryHelper.get().getDynamicDir(), + "dynamic_" + System.currentTimeMillis() + ".jpg", + ImageUploadConfig.EXPECT_MIN_WIDTH, + ImageUploadConfig.EXPECT_COMPRESS_SIZE); + if (result != null) { + compressFile = result.getPath(); + if (result.getWidth() > 0 && item.getWidth() != result.getWidth()) { + item.setWidth(result.getWidth()); + } + if (result.getHeight() > 0 && item.getHeight() != result.getHeight()) { + item.setHeight(result.getHeight()); + } + if (result.getFormat() != null) { + item.setFormat(result.getFormat()); + } + } + LogUtil.print(ResUtil.getString(R.string.publish_presenter_publishpresenter_02) + compressFile); + } + if (!TextUtils.isEmpty(compressFile)) { + e.onSuccess(compressFile); + } else if (!TextUtils.isEmpty(file)) { + e.onSuccess(file); + } else { + e.onError(new Throwable(ResUtil.getString(R.string.publish_presenter_publishpresenter_03))); + } + }) + .compose(RxHelper.handleSchedulers()) + .flatMap((Function>) + path -> FileModel.get().uploadFile(path)) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void acceptThrowable(String url, Throwable throwable) { + super.acceptThrowable(url, throwable); + if (throwable != null) { + throwable.printStackTrace(); + if (mImageUploadSubscribe != null) { + mImageUploadSubscribe.dispose(); + } + dealUploadFileError(throwable); + } else { + item.setResUrl(url); + LogUtil.print(ResUtil.getString(R.string.publish_presenter_publishpresenter_04), item); + publishBody.addDynamicMedia(item); + imagePaths.remove(0); + upload(imagePaths); + } + } + }); + + } + + public void recommendWorlds() { + PublishModel.get().squareWorld(Constants.TYPE_RECOMMEND, 1, 5) + .compose(bindToLifecycle()).subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List miniWorldChooseInfos) { + if (miniWorldChooseInfos != null) { + if (mMvpView != null) { + mMvpView.recommendWorldsSuccess(miniWorldChooseInfos); + } + } else { + if (mMvpView != null) { + mMvpView.recommendWorldsFails(ResUtil.getString(R.string.publish_presenter_publishpresenter_05)); + } + } + + } + + @Override + public void onError(Throwable e) { + if (mMvpView != null) { + mMvpView.recommendWorldsFails(e.getMessage()); + } + + } + }); + } + + private void dealUploadFileError(Throwable e) { + if (getMvpView() != null) { + getMvpView().onPublishFailed(e); + } + } + + public void setWorldId(long worldId) { + if (miniWorldChooseInfo != null) { + miniWorldChooseInfo.setWorldId(worldId); + } + } + + public void setIsInWorld(boolean isInWorld) { + if (miniWorldChooseInfo != null) { + miniWorldChooseInfo.setInWorld(isInWorld); + } + } + + public void setMiniWorldChooseInfo(MiniWorldChooseInfo miniWorldChooseInfo) { + this.miniWorldChooseInfo = miniWorldChooseInfo; + } + + public long getWorldId() { + return miniWorldChooseInfo != null ? miniWorldChooseInfo.getWorldId() : 0; + } + + public boolean isInWorld() { + return miniWorldChooseInfo != null && miniWorldChooseInfo.isInWorld(); + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/publish/presenter/WorldChoosePresenter.java b/app/src/module_community/java/com/chwl/app/community/publish/presenter/WorldChoosePresenter.java new file mode 100644 index 000000000..b1c170205 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/publish/presenter/WorldChoosePresenter.java @@ -0,0 +1,62 @@ +package com.chwl.app.community.publish.presenter; + +import androidx.annotation.Keep; + +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpPresenter; +import com.chwl.app.community.publish.view.IWorldsChooseView; +import com.chwl.core.Constants; +import com.chwl.core.community.PublishModel; +import com.chwl.core.community.bean.MiniWorldChooseInfo; +import com.chwl.library.utils.ResUtil; + +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.disposables.Disposable; +@Keep +public class WorldChoosePresenter extends BaseMvpPresenter { + + private int page = 0; + + public void loadData(boolean isRefresh, byte type) { + if (isRefresh) { + page = 1; + } else { + page++; + } + + PublishModel.get().squareWorld(type, page, Constants.PAGE_SIZE) + .compose(bindToLifecycle()).subscribe(new SingleObserver>() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onSuccess(List miniWorldChooseInfos) { + if (miniWorldChooseInfos != null) { + if (mMvpView != null) { + mMvpView.squareWorldsSuccess(miniWorldChooseInfos); + } + } else { + if (mMvpView != null) { + mMvpView.squareWorldsFails(ResUtil.getString(R.string.publish_presenter_worldchoosepresenter_01)); + } + } + } + + @Override + public void onError(Throwable e) { + if (mMvpView != null) { + mMvpView.squareWorldsFails(e.getMessage()); + } + + } + }); + } + + public int getPage() { + return page; + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/publish/view/IPublishView.java b/app/src/module_community/java/com/chwl/app/community/publish/view/IPublishView.java new file mode 100644 index 000000000..05fe44421 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/publish/view/IPublishView.java @@ -0,0 +1,20 @@ +package com.chwl.app.community.publish.view; + +import com.chwl.core.community.bean.MiniWorldChooseInfo; +import com.chwl.library.base.IMvpBaseView; + +import java.util.List; + +/** + * create by lvzebiao @2019/11/12 + */ +public interface IPublishView extends IMvpBaseView { + + void onPublishSuccess(); + + void onPublishFailed(Throwable throwable); + + void recommendWorldsSuccess(List list); + void recommendWorldsFails(String error); + +} diff --git a/app/src/module_community/java/com/chwl/app/community/publish/view/IWorldsChooseView.java b/app/src/module_community/java/com/chwl/app/community/publish/view/IWorldsChooseView.java new file mode 100644 index 000000000..98ff2b322 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/publish/view/IWorldsChooseView.java @@ -0,0 +1,11 @@ +package com.chwl.app.community.publish.view; + +import com.chwl.core.community.bean.MiniWorldChooseInfo; +import com.chwl.library.base.IMvpBaseView; + +import java.util.List; + +public interface IWorldsChooseView extends IMvpBaseView { + void squareWorldsSuccess(List list); + void squareWorldsFails(String error); +} diff --git a/app/src/module_community/java/com/chwl/app/community/publish/view/PublishActivity.java b/app/src/module_community/java/com/chwl/app/community/publish/view/PublishActivity.java new file mode 100644 index 000000000..d1d2c2b53 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/publish/view/PublishActivity.java @@ -0,0 +1,656 @@ + +package com.chwl.app.community.publish.view; + +import android.Manifest; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.chwl.app.photo.BigPhotoActivity; +import com.chwl.app.photo.PagerOption; +import com.chwl.core.utils.CoreTextUtils; +import com.example.matisse.Matisse; +import com.google.android.flexbox.FlexboxLayout; +import com.hjq.toast.ToastUtils; +import com.netease.nim.uikit.StatusBarUtil; +import com.netease.nim.uikit.common.util.log.LogUtil; +import com.trello.rxlifecycle3.android.ActivityEvent; +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpActivity; +import com.chwl.app.common.widget.dialog.DialogManager; +import com.chwl.app.community.ConstantValue; +import com.chwl.app.community.publish.ImageAdapter; +import com.chwl.app.community.publish.presenter.PublishPresenter; +import com.chwl.app.community.utils.ObjectTypeHelper; +import com.chwl.app.ui.widget.dialog.CommonTipDialog; +import com.chwl.app.ui.widget.recyclerview.decoration.GridSpacingItemDecoration; +import com.chwl.core.Constants; +import com.chwl.core.auth.AuthModel; +import com.chwl.core.community.bean.MiniWorldChooseInfo; +import com.chwl.core.community.bean.PublishItem; +import com.chwl.core.miniworld.model.MiniWorldModel; +import com.chwl.core.user.UserModel; +import com.chwl.core.user.bean.UserInfo; +import com.chwl.core.utils.SharedPreferenceUtils; +import com.chwl.core.utils.net.DontWarnObserver; +import com.chwl.library.base.factory.CreatePresenter; +import com.chwl.library.common.photo.PhotoProvider; +import com.chwl.library.common.util.PhotoCompressUtil; +import com.chwl.library.common.util.PhotosCompressCallback; +import com.chwl.library.easypermisssion.EasyPermissions; +import com.chwl.library.easyphoto.models.album.entity.Photo; +import com.chwl.library.easyphoto.utils.settings.SettingsUtils; +import com.chwl.library.utils.ResUtil; +import com.chwl.library.utils.SingleToastUtil; +import com.example.matisse.internal.entity.CustomItem; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Single; +import io.reactivex.android.schedulers.AndroidSchedulers; +import kotlin.Unit; +import kotlin.jvm.functions.Function1; +import kotlinx.coroutines.Job; + +/** + * create by lvzebiao @2019/11/11 + */ +@CreatePresenter(PublishPresenter.class) +public class PublishActivity extends BaseMvpActivity + implements IPublishView, WorldsChooseFrg.ChooseWorldCallback, EasyPermissions.PermissionCallbacks, + View.OnClickListener { + + private final static String KEY_SP_ORIGINAL_IMAGE = "key_sp_original_image"; + private final static int PERMISSION_CODE_STORAGE = 12; + private final static int REQUEST_CODE_STORAGE = 42; + private final static int REQUEST_CODE_OPEN_PHOTO_PROVIDER = 111; // 从相册中选择 + private final static int maxSelect = 9; + + private RecyclerView rvImages; + private TextView tvPublish; + private EditText etContent; + private TextView tvMiniWorldName; + private TextView tvInputLimit; + + private TextView tvChoose; + private LinearLayout llGroupChoose; + private TextView tvLabelReChoose; + private LinearLayout llMiniWorld; + private FlexboxLayout flGroup; + private RelativeLayout rlChooseGroup; + private ImageView ivClose; + + private ImageAdapter imageAdapter; + + private List imageShowList = new ArrayList<>(); + + private List uploadList = new ArrayList<>(); + + private boolean isOriginalImage; + + // 话题客态页进入(话题进入不让修改话题标签) + private boolean fromWorld; + + private Job mJob = null; + + public static void start(DialogManager manager, long worldId) { + if (beforeStart(manager)) { + return; + } + Context context = manager.getContext(); + Intent intent = new Intent(context, PublishActivity.class); + intent.putExtra("worldId", worldId); + context.startActivity(intent); + } + + /** + * 非话题页面进入 + */ + public static void start(DialogManager manager) { + if (beforeStart(manager)) { + return; + } + Context context = manager.getContext(); + Intent intent = new Intent(context, PublishActivity.class); + context.startActivity(intent); + } + + private static boolean beforeStart(DialogManager manager) { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + if (userInfo == null) { + SingleToastUtil.showToast(ResUtil.getString(R.string.yizhuan_xchat_android_constants_xchatconstants_016)); + return true; + + } else { + return false; + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_publish); + + findView(); + initListener(); + + long worldId = getIntent().getLongExtra("worldId", 0L); + if (worldId > 0) { + fromWorld = true; + getMvpPresenter().setWorldId(worldId); + getMvpPresenter().setIsInWorld(true); + } + + isOriginalImage = (boolean) SharedPreferenceUtils.get(KEY_SP_ORIGINAL_IMAGE, false); + initWhiteTitleBar(getString(R.string.pic_text_publish)); + initGridImages(); + updateImagesData(); + initEditContent(); + initOtherView(); + +// if (!fromWorld) { +// getMvpPresenter().recommendWorlds(); +// } else { // 话题进入,关闭多余的控件 +// llGroupChoose.setVisibility(View.GONE); +// tvChoose.setVisibility(View.GONE); +// ivClose.setVisibility(View.GONE); +// +// flGroup.setVisibility(View.GONE); +// } + rlChooseGroup.setVisibility(View.GONE); + flGroup.setVisibility(View.GONE); + } + + private void findView() { + rvImages = findViewById(R.id.rv_images); + tvPublish = findViewById(R.id.tv_publish); + etContent = findViewById(R.id.et_content); + tvMiniWorldName = findViewById(R.id.tv_mini_world_name); + tvInputLimit = findViewById(R.id.tv_input_limit); + tvChoose = findViewById(R.id.tv_choose); + llGroupChoose = findViewById(R.id.ll_group_choose); + tvLabelReChoose = findViewById(R.id.tv_label_re_choose); + llMiniWorld = findViewById(R.id.ll_miniworld); + flGroup = findViewById(R.id.fl_group); + rlChooseGroup = findViewById(R.id.rl_choose_group); + ivClose = findViewById(R.id.iv_close); + } + + private void initListener() { + tvPublish.setOnClickListener(this); + ivClose.setOnClickListener(this); + llGroupChoose.setOnClickListener(this); + rlChooseGroup.setOnClickListener(this); + } + + private void initGridImages() { + GridLayoutManager gridLayoutManager = new GridLayoutManager(context, 3); + rvImages.setLayoutManager(gridLayoutManager); + rvImages.addItemDecoration(new GridSpacingItemDecoration(context, 3, 10)); + imageAdapter = new ImageAdapter(R.layout.item_publish_image, imageShowList); + imageAdapter.setOnItemClickListener((adapter, view, position) -> { + PublishItem item = imageShowList.get(position); + if (item.isAddItem()) { + checkStoragePermission(); + } else { + BigPhotoActivity.startCanDelete(PublishActivity.this, (ArrayList) uploadList, + position, new PagerOption().setDelete(true)); + } + }); + imageAdapter.setOnItemChildClickListener((adapter, view, position) -> { + if (position < uploadList.size()) { + getDialogManager().showOkCancelDialog(ResUtil.getString(R.string.publish_view_publishactivity_02), () -> { + uploadList.remove(position); + updateImagesData(); + imageAdapter.notifyDataSetChanged(); + toast(ResUtil.getString(R.string.publish_view_publishactivity_03)); + }); + } + }); + rvImages.setAdapter(imageAdapter); + updateImagesData(); + } + + private void updateImagesData() { + List tmp = new ArrayList<>(); + for (int i = 0; i < uploadList.size(); i++) { + CustomItem item = uploadList.get(i); + if (item.getFileType() == 0 || item.getFileType() == 1) { + PublishItem publishItem = new PublishItem(i, PublishItem.BUTTON_TYPE_SHOW_PIC, + item.getPath(), item.isGif() ? 1 : 0); + tmp.add(publishItem); + } + } + imageShowList.clear(); + imageShowList.addAll(tmp); + if (uploadList.size() < 9) { + imageShowList.add(new PublishItem(-1, PublishItem.BUTTON_TYPE_ADD_ITEM, null, 0)); + } + imageAdapter.notifyDataSetChanged(); + updatePublishStatus(); + } + + private void initEditContent() { + etContent.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + tvInputLimit.setText(s.length() + "/500"); + updatePublishStatus(); + String inputText = s.toString().trim(); + tvPublish.setTextColor(!TextUtils.isEmpty(inputText) ? getResources().getColor(R.color.color_7154EE) : getResources().getColor(R.color.color_999999)); + tvPublish.setEnabled(!TextUtils.isEmpty(inputText)); + } + }); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.tv_publish: + publish(); + break; + + case R.id.iv_close: + showChooseView(); + break; + } + } + + + private void publish() { + tvPublish.setEnabled(false); + getDialogManager().showProgressDialog(context); + getMvpPresenter().publishDy( + ObjectTypeHelper.customToMediaList(uploadList), + getMvpPresenter().getWorldId(), etContent.getText().toString(), isOriginalImage); + } + + private void updatePublishStatus() { + tvPublish.setEnabled(!(uploadList.size() == 0 && + CoreTextUtils.isEmptyText(etContent.getText().toString()))); + } + + private void initOtherView() { + //话题名称 + long worldId = getMvpPresenter().getWorldId(); + if (worldId > 0) { + MiniWorldModel.getInstance().getWorldDetailInfo(String.valueOf(worldId), + String.valueOf(AuthModel.get().getCurrentUid())) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .doOnSuccess(info -> { + if (info != null && !TextUtils.isEmpty(info.getName())) { + showReChooseView(info.getName()); + } + }) + .subscribe(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_CODE_STORAGE) { + checkStoragePermission(); + } else if (resultCode == RESULT_OK) { + switch (requestCode) { + case REQUEST_CODE_OPEN_PHOTO_PROVIDER: + if (data == null) { + return; + } + PhotoProvider.getResultPathListAsync(data, new Function1, Unit>() { + @Override + public Unit invoke(List list) { + if (list.isEmpty()) { + return null; + } else { + if (mJob != null) { + mJob.cancel(null); + } + ArrayList pathList = new ArrayList<>(); + for (Photo photo : list) { + pathList.add(photo.path); + } + mJob = PhotoCompressUtil.compress(PublishActivity.this, pathList, + PhotoCompressUtil.getCompressCachePath("publish") + , new PhotosCompressCallback() { + @Override + public void onSuccess(@NonNull ArrayList compressedImgList) { + List pathResult = new ArrayList<>(); + for (int i = 0; i < compressedImgList.size(); i++) { + if (i < list.size()) { + Photo photo = list.get(i); + String format = "image/jpeg"; + if (photo.type != null) { + format = photo.type; + } + pathResult.add(new CustomItem(compressedImgList.get(i), CustomItem.IMAGE_NORMAL, format, photo.width, photo.height)); + } + } + if (pathResult.size() == 0) { + return; + } + LogUtil.print(pathResult); + + uploadList.addAll(pathResult); + updateImagesData(); + + isOriginalImage = false; + LogUtil.print("isOriginalImage:" + isOriginalImage); + SharedPreferenceUtils.put(KEY_SP_ORIGINAL_IMAGE, isOriginalImage); + } + + @Override + public void onFail(@NonNull Throwable e) { + toast(getString(R.string.picker_image_error)); + } + }, 200, false, Constants.UPLOAD_IMAGE_MAX_SIZE, Constants.UPLOAD_IMAGE_MAX_FILE_LENGTH); + } + return null; + } + }); + break; + + case ConstantValue.CODE_CHOOSE_PHOTO: + String mimeType = Matisse.obtainMineResult(data); + List pathResult = Matisse.obtainPathResult(data); + if ("video".equals(mimeType)) { + toast(ResUtil.getString(R.string.publish_view_publishactivity_04)); + return; + } + if (pathResult == null) { + return; + } + LogUtil.print(pathResult); + + uploadList.addAll(pathResult); + updateImagesData(); + + isOriginalImage = Matisse.obtainOriginalImageResult(data); + LogUtil.print("isOriginalImage:" + isOriginalImage); + SharedPreferenceUtils.put(KEY_SP_ORIGINAL_IMAGE, isOriginalImage); + + break; + + case BigPhotoActivity.CODE_DELETE_PHOTO: + List newList = data.getParcelableArrayListExtra( + BigPhotoActivity.KEY_IMG_URL); + uploadList.clear(); + uploadList.addAll(newList); + updateImagesData(); + break; + + } + } + } + + @Override + public void onPublishSuccess() { + hideIME(etContent); + getDialogManager().dismissDialog(); + tvPublish.setEnabled(true); + getDialogManager().showCustomViewDialog(R.layout.dialog_dy_publish_success); + getDialogManager().getDialog().setCanceledOnTouchOutside(true); + getDialogManager().getDialog().setOnDismissListener(dialog -> finish()); + getDialogManager().getDialog().setOnKeyListener((dialog, keyCode, event) -> { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 + && event.getAction() == KeyEvent.ACTION_DOWN) { + hideDialogAndFinish(); + return true; + } + return false; + }); + Single.timer(3, TimeUnit.SECONDS, AndroidSchedulers.mainThread()) + .compose(bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(Long aLong, String error) { + super.accept(aLong, error); + if (error == null) { + hideDialogAndFinish(); + } + } + }); + + } + + private void hideDialogAndFinish() { + getDialogManager().dismissDialog(); + finish(); + } + + @Override + public void onPublishFailed(Throwable throwable) { + tvPublish.setEnabled(true); + getDialogManager().dismissDialog(); + toast(throwable.getMessage()); + } + + @Override + public void recommendWorldsSuccess(List list) { + addMiniWorldList(list); + } + + @Override + public void recommendWorldsFails(String error) { + flGroup.setVisibility(View.GONE); + + toast(error); + } + + private void handleFinish() { + if (!tvPublish.isEnabled()) { + finish(); + return; + } + getDialogManager().showOkCancelWithTitleDialog(ResUtil.getString(R.string.publish_view_publishactivity_06), ResUtil.getString(R.string.publish_view_publishactivity_07), + ResUtil.getString(R.string.publish_view_publishactivity_08), ResUtil.getString(R.string.publish_view_publishactivity_09), new DialogManager.OkCancelDialogListener() { + + @Override + public void onCancel() { + finish(); + } + + @Override + public void onOk() { + + } + + }); + } + + @Override + protected void onLeftClickListener() { + handleFinish(); + } + + @Override + public void onBackPressed() { + handleFinish(); + } + + private void showChooseView() { + rlChooseGroup.setEnabled(true); + llGroupChoose.setEnabled(false); + + tvChoose.setVisibility(View.VISIBLE); + tvLabelReChoose.setVisibility(View.GONE); + + llMiniWorld.setVisibility(View.GONE); + tvMiniWorldName.setText(""); + + getMvpPresenter().setMiniWorldChooseInfo(new MiniWorldChooseInfo()); + } + + private void showReChooseView(String worldName) { + rlChooseGroup.setEnabled(false); + llGroupChoose.setEnabled(true); + + tvChoose.setVisibility(View.GONE); + tvLabelReChoose.setVisibility(View.VISIBLE); + tvMiniWorldName.setText("#" + worldName); + + llMiniWorld.setVisibility(View.VISIBLE); + } + + private List miniWorldChooseInfoList; + + private void addMiniWorldList(List list) { + miniWorldChooseInfoList = list; + flGroup.removeAllViews(); + + if (miniWorldChooseInfoList != null && miniWorldChooseInfoList.size() > 0) { + for (MiniWorldChooseInfo item : miniWorldChooseInfoList) { + TextView textView = (TextView) LayoutInflater.from(this).inflate(R.layout.item_label_mini_world, flGroup, false); + textView.setText(item.getWorldName()); + textView.setTag(item.getWorldId()); + textView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TextView tv = (TextView) v; + + if (miniWorldChooseInfoList != null && tv != null) { + for (MiniWorldChooseInfo sub : miniWorldChooseInfoList) { + Long tag = (Long) tv.getTag(); + long worldid = sub.getWorldId(); + if (worldid == tag) { + getMvpPresenter().setMiniWorldChooseInfo(sub); + showReChooseView(sub.getWorldName()); + break; + } + + } + } + + } + }); + + flGroup.addView(textView); + } + + } else { + flGroup.setVisibility(View.GONE); + } + } + + @Override + public void callback(MiniWorldChooseInfo miniWorldChooseInfo) { + getMvpPresenter().setMiniWorldChooseInfo(miniWorldChooseInfo); + if (miniWorldChooseInfo == null) { + showChooseView(); + } else { + showReChooseView(miniWorldChooseInfo.getWorldName()); + } + + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); + } + + @Override + public void onPermissionsGranted(int requestCode, @NonNull List perms) { + if (requestCode == PERMISSION_CODE_STORAGE) { + checkStoragePermission(); + } + } + + @Override + public void onPermissionsDenied(int requestCode, @NonNull List perms) { + if (requestCode == PERMISSION_CODE_STORAGE) { + String requestTip = getString(R.string.permission_storage_denied); + CommonTipDialog mPrivacyDialog = new CommonTipDialog(context); + mPrivacyDialog.setTipMsg(requestTip); + mPrivacyDialog.setOkText(getString(R.string.room_perform_go_update)); + mPrivacyDialog.setOnActionListener(new CommonTipDialog.OnActionListener() { + @Override + public void onOk() { + //同意跳到应用详情页面 + SettingsUtils.startMyApplicationDetailsForResult(PublishActivity.this, + getPackageName()); + } + + @Override + public void onCancel() { + CommonTipDialog.OnActionListener.super.onCancel(); + //取消跳到应用详情页面 + ToastUtils.show(getString(R.string.permission_storage_refused)); + } + }); + mPrivacyDialog.show(); + } + } + + private void checkStoragePermission() { + if (!EasyPermissions.hasPermissions( + this, + Build.VERSION.SDK_INT >= 33 ? Manifest.permission.READ_MEDIA_IMAGES : Manifest.permission.READ_EXTERNAL_STORAGE + ) + ) { + EasyPermissions.requestPermissions( + this, + getString(R.string.permission_storage_rationale), + PERMISSION_CODE_STORAGE, + Build.VERSION.SDK_INT >= 33 ? Manifest.permission.READ_MEDIA_IMAGES : Manifest.permission.READ_EXTERNAL_STORAGE + ); + } else { + PhotoProvider.photoProvider( + this, + maxSelect - uploadList.size(), + true, + REQUEST_CODE_OPEN_PHOTO_PROVIDER, + true, + true + ); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mJob != null) { + mJob.cancel(null); + } + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/publish/view/WorldChooseAdapter.java b/app/src/module_community/java/com/chwl/app/community/publish/view/WorldChooseAdapter.java new file mode 100644 index 000000000..d0bbe74ec --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/publish/view/WorldChooseAdapter.java @@ -0,0 +1,31 @@ +package com.chwl.app.community.publish.view; + +import android.widget.ImageView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.chwl.app.R; +import com.chwl.app.ui.utils.ImageLoadUtilsV2; +import com.chwl.core.community.bean.MiniWorldChooseInfo; + +public class WorldChooseAdapter extends BaseQuickAdapter { + + public WorldChooseAdapter() { + super(R.layout.item_worlds_choose, null); + } + + @Override + protected void convert(BaseViewHolder helper, MiniWorldChooseInfo item) { + if (item == null) { + return; + } + + helper.setText(R.id.tv_world_name, item.getWorldName() + "") + .setText(R.id.tv_world_desc, item.getDescription() + ""); + + ImageView imageView = helper.getView(R.id.rriv_world); + ImageLoadUtilsV2.loadImage(imageView, item.getIcon()); + helper.addOnClickListener(R.id.cl_container); + + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/publish/view/WorldsChooseFrg.java b/app/src/module_community/java/com/chwl/app/community/publish/view/WorldsChooseFrg.java new file mode 100644 index 000000000..eb366d2c8 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/publish/view/WorldsChooseFrg.java @@ -0,0 +1,147 @@ +package com.chwl.app.community.publish.view; + +import android.os.Bundle; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpFragment; +import com.chwl.app.community.publish.presenter.WorldChoosePresenter; +import com.chwl.app.ui.widget.recyclerview.decoration.HorizontalDecoration; +import com.chwl.core.Constants; +import com.chwl.core.community.bean.MiniWorldChooseInfo; +import com.chwl.library.base.factory.CreatePresenter; +import com.chwl.library.utils.SizeUtils; + +import java.util.List; + +@CreatePresenter(WorldChoosePresenter.class) +public class WorldsChooseFrg extends BaseMvpFragment implements IWorldsChooseView { + private SwipeRefreshLayout swipeRefreshLayout; + private RecyclerView recyclerView; + private WorldChooseAdapter mAdapter; + + private byte mType; + + public static WorldsChooseFrg newInstance(byte type) { + WorldsChooseFrg fragment = new WorldsChooseFrg(); + Bundle args = new Bundle(); + args.putByte("type", type); + fragment.setArguments(args); + return fragment; + } + + @Override + public int getRootLayoutId() { + return R.layout.frg_worlds_choose; + } + + @Override + public void onFindViews() { + swipeRefreshLayout = mView.findViewById(R.id.swipe_refresh); + recyclerView = mView.findViewById(R.id.recycler_view); + } + + @Override + public void onSetListener() { + swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + mAdapter.setEnableLoadMore(true); + loadData(true); + } + }); + } + + @Override + public void initiate() { + Bundle bundle = getArguments(); + if (bundle != null) { + mType = bundle.getByte("type", Constants.TYPE_ALL); + } else { + mType = Constants.TYPE_ALL; + } + + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + mAdapter = new WorldChooseAdapter(); + mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + List list = adapter.getData(); + + if (list.size() > 0 && position < list.size()) { + MiniWorldChooseInfo miniWorldChooseInfo = list.get(position); + if (mChooseWorldCallback != null) { + mChooseWorldCallback.callback(miniWorldChooseInfo); + } + } + } + }); + recyclerView.setAdapter(mAdapter); + recyclerView.addItemDecoration(new HorizontalDecoration(SizeUtils.dp2px(mContext, 25), false, true)); + + loadData(true); + } + + private void loadData(boolean isRefresh) { + getMvpPresenter().loadData(isRefresh, mType); + } + + private ChooseWorldCallback mChooseWorldCallback; + + public WorldsChooseFrg setmChooseWorldCallback(ChooseWorldCallback chooseWorldCallback) { + this.mChooseWorldCallback = chooseWorldCallback; + return this; + } + + @Override + public void squareWorldsSuccess(List list) { + hideStatus(); + + if (mAdapter != null) { + int page = getMvpPresenter().getPage(); + if (page <= 1) { + swipeRefreshLayout.setRefreshing(false); + + if (list == null || list.size() == 0) { + showNoData(); + } else { + mAdapter.setNewData(list); + } + + } else { + mAdapter.addData(list); + + if (list.size() == 0) { + mAdapter.loadMoreComplete(); + mAdapter.loadMoreEnd(); + mAdapter.setEnableLoadMore(false); + } + } + } + } + + @Override + public void onReloadData() { + super.onReloadData(); + loadData(true); + } + + @Override + public void squareWorldsFails(String error) { + hideStatus(); + + int page = getMvpPresenter().getPage(); + if (page <= 1) { + showNoData(); + } + } + + public interface ChooseWorldCallback { + void callback(MiniWorldChooseInfo miniWorldChooseInfo); + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/square/SquareDynamicFragment.java b/app/src/module_community/java/com/chwl/app/community/square/SquareDynamicFragment.java new file mode 100644 index 000000000..12a2b0a2d --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/square/SquareDynamicFragment.java @@ -0,0 +1,313 @@ +package com.chwl.app.community.square; + +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.core.XConstants; +import com.trello.rxlifecycle3.android.FragmentEvent; +import com.chwl.app.R; +import com.chwl.app.UIHelper; +import com.chwl.app.avroom.ButtonItemFactory; +import com.chwl.app.avroom.activity.AVRoomActivity; +import com.chwl.app.common.EmptyViewHelper; +import com.chwl.app.common.widget.dialog.DialogManager; +import com.chwl.app.community.helper.ShareDynamicHelper; +import com.chwl.app.community.square.adapter.SquareDynamicAdapter; +import com.chwl.app.ui.widget.ButtonItem; +import com.chwl.core.auth.AuthModel; +import com.chwl.core.community.CommunityConstant; +import com.chwl.core.community.bean.WorldDynamicBean; +import com.chwl.core.community.bean.WorldDynamicListResult; +import com.chwl.core.community.dynamic.DynamicModel; +import com.chwl.core.community.event.DynamicPublishEvent; +import com.chwl.core.community.event.DynamicRefreshEvent; +import com.chwl.core.community.square.SquareModel; +import com.chwl.core.user.UserModel; +import com.chwl.core.user.event.LoadLoginUserInfoEvent; +import com.chwl.core.utils.net.BeanObserver; +import com.chwl.core.utils.net.DontWarnObserver; +import com.chwl.library.utils.ResUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import io.reactivex.Single; + +/** + * create by lvzebiao @2020/1/7 + */ +public class SquareDynamicFragment extends BaseFragment { + + public static final String EXTRA_SQUARE_TYPE = "square_type"; + + private RecyclerView recyclerView; + private SwipeRefreshLayout refreshLayout; + /** + * 话题类型ID + * 全部 0 + * 推荐 1 + */ + private static final String TOPIC_CATEGORY_ID = "1"; + + private String nextDynamicId; + + private int page = 1; + + private SquareDynamicAdapter adapter; + + private int squareType; + + public static SquareDynamicFragment newInstance(int type) { + SquareDynamicFragment fragment = new SquareDynamicFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(EXTRA_SQUARE_TYPE, type); + fragment.setArguments(bundle); + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mView = inflater.inflate(R.layout.fragment_square_dynamic, container, false); + EventBus.getDefault().register(this); + return mView; + } + + @Override + public void onFindViews() { + recyclerView = mView.findViewById(R.id.recycler_view); + refreshLayout = mView.findViewById(R.id.refresh_layout); + } + + @Override + public void onSetListener() { + + } + + @Override + public void initiate() { + Bundle bundle = getArguments(); + if (bundle != null) { + squareType = bundle.getInt(EXTRA_SQUARE_TYPE, SquareFragment.TAB_TYPE_RECOMMEND); + } + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + adapter = new SquareDynamicAdapter(getActivity()); + recyclerView.setAdapter(adapter); + adapter.setPreLoadNumber(2); + adapter.setHeaderAndEmpty(true); + adapter.setOnLoadMoreListener(() -> loadData(false), recyclerView); + adapter.setOnItemChildClickListener((baseQuickAdapter, view, pos) -> { + WorldDynamicBean bean = adapter.getItem(pos); + if (bean == null) { + return; + } + if (view.getId() == R.id.iv_more) { + List list = new ArrayList<>(); + if (!UserModel.get().isMyseft(bean.getUid())) { + ButtonItem item = new ButtonItem(getString(R.string.me_shield_dynamic), () -> { + UserModel.get().addReport(bean.getDynamicId(), 0) + .subscribe(new BeanObserver() { + @Override + public void onErrorMsg(String error) { + getDialogManager().dismissDialog(); + toast(error); + } + + @Override + public void onSuccess(String s) { + getDialogManager().dismissDialog(); + toast(ResUtil.getString(R.string.me_shield_success)); + adapter.remove(pos); + } + }); + }); + list.add(item); + } + if (!UserModel.get().isMyseft(bean.getUid())) { + ButtonItem blackListItem = ButtonItemFactory.createAddToBlackListItem( + getDialogManager(), String.valueOf(bean.getUid())); + list.add(blackListItem); + } + if (!UserModel.get().isMyseft(bean.getUid())) { + ButtonItem item = new ButtonItem(getString(R.string.me_report_dynamic), () -> { + UIHelper.showReportPage(getActivity(), bean.getUid(), + XConstants.REPORT_TYPE_DYNAMIC_SQUARE); + }); + list.add(item); + } + if (UserModel.get().isMyseft(bean.getUid()) || + isThisWorldOwner(bean)) { + ButtonItem item = new ButtonItem(getString(R.string.me_delete), () -> deleteDynamic(pos)); + list.add(item); + } + getDialogManager().showCommonPopupDialog(list, getString(R.string.cancel)); + } else if (view.getId() == R.id.ll_share) { + new ShareDynamicHelper(getActivity()).share(bean); + } else if (view.getId() == R.id.iv_in_room) { + if (bean.getInRoomUid() == null) { + return; + } + AVRoomActivity.start(mContext, bean.getInRoomUid()); + } + }); + + refreshLayout = mView.findViewById(R.id.refresh_layout); + refreshLayout.setOnRefreshListener(() -> { + loadData(true); + }); + + loadData(true); + } + + private void loadData(boolean isRefresh) { + if (isRefresh) { + nextDynamicId = null; + page = 1; + } else { + page++; + } + + Single single = null; + //推荐动态返回的是直接一个list,但是为了便于统一和关注动态列表的逻辑,我们包多一层 + //返回WorldDynamicListResult + if (squareType == SquareFragment.TAB_TYPE_ATTENT) { + single = SquareModel.get().getFollowerDynamics(nextDynamicId, + CommunityConstant.DYNAMIC_PAGE_SIZE); + } else if (squareType == SquareFragment.TAB_TYPE_RECOMMEND) { + single = SquareModel.get().getRecommendDynamics(page, CommunityConstant.DYNAMIC_PAGE_SIZE) + .map(list -> { + WorldDynamicListResult result = new WorldDynamicListResult(); + result.setDynamicList(list); + return result; + }); + } else { + single = SquareModel.get().getLatestDynamics(page, CommunityConstant.DYNAMIC_PAGE_SIZE, nextDynamicId); + } + + single.compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(WorldDynamicListResult result, String error) { + super.accept(result, error); + refreshLayout.setRefreshing(false); + if (error != null) { + if (!isRefresh) adapter.loadMoreFail(); + return; + } + //接口访问正确的处理 + nextDynamicId = String.valueOf(result.getNextDynamicId()); + List list = result.getDynamicList(); + if (list == null) { + list = new ArrayList<>(); + } + if (isRefresh) { + adapter.setNewData(list); + adapter.disableLoadMoreIfNotFullPage(); + if (list.isEmpty()) { + String emptyTips = getString(R.string.no_dynamic); + if (squareType == SquareFragment.TAB_TYPE_ATTENT) { + emptyTips = getString(R.string.recommend_to_have_a_look); + } + adapter.setEmptyView(EmptyViewHelper.createEmptyTextView(getContext(), emptyTips)); + } + } else { + if (list.isEmpty()) { + adapter.loadMoreEnd(true); + } else { + adapter.addData(list); + adapter.loadMoreComplete(); + } + } + } + }); + } + + /** + * 判断自己是不是该世界的创始人 + */ + private boolean isThisWorldOwner(WorldDynamicBean bean) { + return bean != null && bean.getWorldUid() == AuthModel.get().getCurrentUid(); + } + + private void deleteDynamic(int pos) { + getDialogManager().showOkCancelWithTitleDialog(getString(R.string.me_cannot_be_restored), + new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + WorldDynamicBean bean = adapter.getItem(pos); + if (bean == null) { + return; + } + DynamicModel.get().delete(bean.getWorldId(), bean.getDynamicId()) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String s, String error) { + super.accept(s, error); + if (error != null) { + toast(error); + } else { + toast(getString(R.string.me_successfully_delete)); + if (pos < adapter.getData().size()) { + if (Objects.equals(bean, adapter.getItem(pos))) { + adapter.remove(pos); + } + } + } + } + }); + + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onDynamicPublishEvent(DynamicPublishEvent event) { + if (squareType == SquareFragment.TAB_TYPE_ATTENT) { + loadData(true); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoadLoginUserInfoEvent(LoadLoginUserInfoEvent event) { + if (squareType == SquareFragment.TAB_TYPE_ATTENT) { + loadData(true); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onDynamicRefreshEvent(DynamicRefreshEvent event) { + loadData(true); + } + + @Override + public int getRootLayoutId() { + return 0; + } + + @Override + public void onDestroyView() { + EventBus.getDefault().unregister(this); + super.onDestroyView(); + } + + @Override + public void showNoData() { + + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/square/SquareFragment.java b/app/src/module_community/java/com/chwl/app/community/square/SquareFragment.java new file mode 100644 index 000000000..bcbfbb484 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/square/SquareFragment.java @@ -0,0 +1,193 @@ +package com.chwl.app.community.square; + +import static android.view.View.GONE; +import static android.view.View.VISIBLE; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.viewpager2.widget.ViewPager2; + +import com.chwl.app.R; +import com.chwl.app.avroom.adapter.CommonVPAdapter; +import com.chwl.app.base.BaseFragment; +import com.chwl.app.common.widget.DragLayout; +import com.chwl.app.community.publish.view.PublishActivity; +import com.chwl.app.home.activity.CommunityNoticeAct; +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.core.auth.AuthModel; +import com.chwl.core.community.event.UnReadCountEvent; +import com.chwl.core.home.model.HomeModel; +import com.chwl.core.user.event.LoadLoginUserInfoEvent; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +/** + * create by lvzebiao @2020/1/7 + */ + +public class SquareFragment extends BaseFragment implements ContactsIndicatorAdapter.OnItemSelectListener, View.OnClickListener { + public static final String TAG = "SquareFragment"; + /** + * 关注 + */ + public static final int TAB_TYPE_ATTENT = 0; + /** + * 推荐 + */ + public static final int TAB_TYPE_RECOMMEND = 1; + /** + * 最新 + */ + public static final int TAB_TYPE_NEW = 2; + + private MagicIndicator magicIndicator; + private ViewPager2 viewPager; + private DragLayout ivSquarePublish; + private FrameLayout flContactList; + private View tvCommunityUnread; + + public static SquareFragment newInstance() { + return new SquareFragment(); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mView = inflater.inflate(R.layout.fragment_square, container, false); + magicIndicator = mView.findViewById(R.id.magic_indicator); + viewPager = mView.findViewById(R.id.view_pager); + ivSquarePublish = mView.findViewById(R.id.iv_square_publish); + flContactList = mView.findViewById(R.id.fl_contact_list); + tvCommunityUnread = mView.findViewById(R.id.msg_number); + EventBus.getDefault().register(this); + return mView; + } + + @Override + public void initiate() { + List fragmentPos = new ArrayList<>(); + fragmentPos.add(TAB_TYPE_ATTENT); + fragmentPos.add(TAB_TYPE_RECOMMEND); + fragmentPos.add(TAB_TYPE_NEW); + List tagList = new ArrayList<>(); + List fragmentList = new ArrayList<>(); + for (Integer integer : fragmentPos) { + if (integer == TAB_TYPE_ATTENT) { + tagList.add(getResources().getString(R.string.dys_tab_attent)); + } else if (integer == TAB_TYPE_RECOMMEND) { + tagList.add(getResources().getString(R.string.dys_tab_recommend)); + } else if (integer == TAB_TYPE_NEW) { + tagList.add(getResources().getString(R.string.dys_tab_new)); + } + fragmentList.add(SquareDynamicFragment.newInstance(integer)); + } + + getUnReadCount(); + + //init viewpager + + viewPager.setAdapter(new CommonVPAdapter(getChildFragmentManager(), getLifecycle(), fragmentList)); + viewPager.setOffscreenPageLimit(3); + viewPager.setUserInputEnabled(false); + + CommonNavigator commonNavigator = new CommonNavigator(getContext()); + ContactsIndicatorAdapter magicIndicatorAdapter = new ContactsIndicatorAdapter(getContext(), tagList); + magicIndicatorAdapter.setOnItemSelectListener(this); + commonNavigator.setTitleWrapContent(true); + commonNavigator.setAdapter(magicIndicatorAdapter); + magicIndicator.setNavigator(commonNavigator); + commonNavigator.getTitleContainer().setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); + //init indicator + ViewPagerHelper.bind(magicIndicator, viewPager); + viewPager.post(new Runnable() { + @Override + public void run() { + viewPager.setCurrentItem(TAB_TYPE_RECOMMEND); + } + }); +// magicIndicator.onPageSelected(TAB_TYPE_RECOMMEND); + } + + @Override + public void onItemSelect(int position, TextView view) { + viewPager.setCurrentItem(position); + } + + @Override + public void onSetListener() { + if (ivSquarePublish != null) { + ivSquarePublish.setOnClickListener(this); + } + if (flContactList != null) { + flContactList.setOnClickListener(this); + } + if (ivSquarePublish != null) { + ivSquarePublish.setOnClickListener(this); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.iv_square_publish: + PublishActivity.start(getDialogManager()); + break; + + case R.id.fl_contact_list: + CommunityNoticeAct.start(mContext); + break; + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onUnReadCount(UnReadCountEvent event) { + setNumber(event.getTotal()); + } + + @SuppressLint("SetTextI18n") + public void setNumber(int number) { + tvCommunityUnread.setVisibility(number <= 0 ? GONE : VISIBLE); + } + + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLoginUserInfoUpdateEvent(LoadLoginUserInfoEvent event) { + getUnReadCount(); + } + + @SuppressWarnings("CheckResult") + private void getUnReadCount() { + HomeModel.INSTANCE.getUnreadCount(AuthModel.get().getCurrentUid()) + .compose(bindToLifecycle()) + .subscribe((integer, throwable) -> { + if (integer != null) { + EventBus.getDefault().post(new UnReadCountEvent(integer)); + } + }); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + EventBus.getDefault().unregister(this); + } + +} + diff --git a/app/src/module_community/java/com/chwl/app/community/square/adapter/SquareDynamicAdapter.java b/app/src/module_community/java/com/chwl/app/community/square/adapter/SquareDynamicAdapter.java new file mode 100644 index 000000000..64812c625 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/square/adapter/SquareDynamicAdapter.java @@ -0,0 +1,250 @@ +package com.chwl.app.community.square.adapter; + +import android.content.Context; +import android.text.TextUtils; +import android.util.SparseBooleanArray; +import android.util.SparseIntArray; +import android.view.View; +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.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.DynamicUiHelper; +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.GridImageWidget; +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.TimeUiUtils; +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 SquareDynamicAdapter extends BaseQuickAdapter { + + private SparseBooleanArray mCollapsedStatus = new SparseBooleanArray(); + private SparseIntArray mCollapsedHeightStatus = new SparseIntArray(2); + + private Context context; + + private int iconWidth; + + private int iconHeight; + + /** + * 有文本的图片布局的top-margin + */ + private int imageTmHasText; + /** + * 无文本的图片布局的top-margin + */ + private int imageTmNoText; + /** + * 图片的边界值 + */ + private int dividerDp; + + private int rvWidth; + + + public SquareDynamicAdapter(Context context) { + super(R.layout.item_square_dynamic); + this.context = context; + iconWidth = UIUtil.dip2px(context, 32); + iconHeight = UIUtil.dip2px(context, 15); + imageTmHasText = UIUtil.dip2px(context, 12f); + imageTmNoText = UIUtil.dip2px(context, 7.5f); + //0.68 + int screenWidth = UIUtil.getScreenWidth(context); + dividerDp = 9; + rvWidth = screenWidth - UIUtil.dip2px(context, 86); + } + + @Override + protected void convert(BaseViewHolder helper, WorldDynamicBean item) { + //这个值,有没有文本UI部分,改变图片部分的margin + boolean noTextUi = TextUtils.isEmpty(item.getContent()); + + helper.setText(R.id.tv_nick, item.getNick()); + GridImageWidget widgetImage = helper.getView(R.id.widget_image); + widgetImage.setDividerDp(dividerDp); + widgetImage.setRvWidth(rvWidth); + widgetImage.setData(item, noTextUi ? imageTmNoText : imageTmHasText); + + //头饰 贵族头饰 + ImageView ivHeadWear = helper.getView(R.id.iv_head_wear); + GlideApp.with(ivHeadWear.getContext()).clear(ivHeadWear); + String headwearEffect = item.getHeadwearEffect(); + String headwearPic = item.getHeadwearPic(); + String micDecorate = item.getMicDecorate(); + if (TextUtils.isEmpty(headwearEffect) && TextUtils.isEmpty(headwearPic) && TextUtils.isEmpty(micDecorate)) { + ivHeadWear.setVisibility(View.GONE); + } else { + ivHeadWear.setVisibility(View.VISIBLE); + } + + if (!TextUtils.isEmpty(headwearEffect)) { + NobleUtil.loadHeadWear(headwearEffect, ivHeadWear); + } else 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); + //widget.setTime(item.getPublishTime()); + final String time = TimeUiUtils.getDynamicUi(item.getPublishTime()); + helper.setGone(R.id.tv_time_publish, !TextUtils.isEmpty(time)); + helper.setText(R.id.tv_time_publish, time); + helper.setGone(R.id.iv_in_room, item.getInRoomUid() != null); + + ExpandableTextView etvContent = helper.getView(R.id.etv_content); + etvContent.setEventType(4); + if (noTextUi && item.getSquareTop() == 0) { + etvContent.setVisibility(View.GONE); + } else { + etvContent.setVisibility(View.VISIBLE); + CharSequence formatText = DynamicUiHelper.formatFirstDynamicContent( + item, etvContent.mTv, iconWidth, iconHeight); + if (item.getSquareTop() == 1) { + //置顶 + formatText = TopicUpTextWrapper.INSTANCE.wrapUp(formatText, context); + } + etvContent.setText(formatText, mCollapsedStatus, helper.getAdapterPosition(), mCollapsedHeightStatus); + } + + //标签 + final List labels = item.getLabelList(); + if (labels != null) { + ((TopicLabelWidget) helper.getView(R.id.topicView)).setLabels(labels); + } + + //评论 + 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(item.getWorldId(), item.getDynamicId(), item.getUid(), status, 4) + .compose(RxHelper.bindContext(context)) + .subscribe(new DontWarnObserver() { + @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.square_adapter_squaredynamicadapter_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(), item.getWorldId(), + helper.getAdapterPosition(), true, 6); + } + ); + + View.OnClickListener toDetailListener = v -> + DynamicDetailActivity.start(context, item.getDynamicId(), item.getWorldId(), + helper.getAdapterPosition(), false, 6); + + if (etvContent.mTv != null) { + etvContent.mTv.setOnClickListener(toDetailListener); + } + + //跳转去详情 + helper.itemView.setOnClickListener(toDetailListener); + + helper.addOnClickListener(R.id.iv_more) + .addOnClickListener(R.id.ll_share) + .addOnClickListener(R.id.iv_in_room); + + 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); + + //话题 + helper.setGone(R.id.tv_mini_world_name, false); + helper.setGone(R.id.space_view, false); +// helper.setGone(R.id.tv_mini_world_name, item.getWorldId() > 0); +// helper.setGone(R.id.space_view, item.getWorldId() > 0); +// helper.setText(R.id.tv_mini_world_name, item.getWorldName()); +// helper.getView(R.id.tv_mini_world_name).setOnClickListener(v -> { +// TopicMainActivity.start(context, String.valueOf(item.getWorldId())); +// }); + } + + 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) { + ivLikeAnim.setImageResource(R.drawable.icon_square_dynamic_like_checked); + } else { + ivLikeAnim.setImageResource(R.drawable.icon_square_dynamic_like_normal); + } + } + + 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); + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/user_dynamic/IUserDynamicView.java b/app/src/module_community/java/com/chwl/app/community/user_dynamic/IUserDynamicView.java new file mode 100644 index 000000000..e03531daf --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/user_dynamic/IUserDynamicView.java @@ -0,0 +1,17 @@ +package com.chwl.app.community.user_dynamic; + +import com.chwl.core.community.bean.WorldDynamicBean; +import com.chwl.library.base.IMvpBaseView; + +import java.util.List; + +public interface IUserDynamicView extends IMvpBaseView { + void refreshSuccess(List list); + void refreshFail(String error); + + void loadSuccess(List list); + void loadFail(String error); + + void deleteSuccess(long successId); + void deleteFail(String error); +} diff --git a/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicAdapter.java b/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicAdapter.java new file mode 100644 index 000000000..cd7f92bbe --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicAdapter.java @@ -0,0 +1,285 @@ +package com.chwl.app.community.user_dynamic; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.AnimationDrawable; +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.BaseMultiItemQuickAdapter; +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.chwl.app.R; +import com.chwl.app.community.helper.CalcSize; +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.widget.ExpandableTextView; +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil; +import com.chwl.app.ui.widget.recyclerview.decoration.GridSpacingItemDecoration; +import com.chwl.core.community.bean.DynamicMedia; +import com.chwl.core.community.bean.UserDynamicItem; +import com.chwl.core.community.bean.WorldDynamicBean; +import com.chwl.core.community.dynamic.DynamicModel; +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.ScreenUtils; +import com.chwl.library.utils.SingleToastUtil; +import com.chwl.library.utils.TimeUtils; + +import java.util.ArrayList; +import java.util.List; + +public class UserDynamicAdapter extends BaseMultiItemQuickAdapter { + private long currentUid; + private SparseBooleanArray mCollapsedStatus = new SparseBooleanArray(); + private SparseIntArray mCollapsedHeightStatus = new SparseIntArray(2); + + private int imageBorder; + /** + * 这个divider是因为使用的分割线 + * 默认为top和bottom添加了5dp + */ + private int divider; + + // 图片宽高一致 + private int mTwoImageHeight; + private int mThreeImageHeight; + + public UserDynamicAdapter(Context context, long currentUid) { + super(new ArrayList<>()); + this.currentUid = currentUid; + addItemType(UserDynamicItem.TYPE_DYNAMIC, R.layout.item_user_dynamic_list); + addItemType(UserDynamicItem.TYPE_EMPTY, R.layout.item_empty_list); + addItemType(UserDynamicItem.TYPE_FIRST_DIVIDER, R.layout.layout_divider_12); + imageBorder = (UIUtil.getScreenWidth(context) - UIUtil.dip2px(context, 17+29)) + * ImageUiHelper.BORDER_MIN / ImageUiHelper.BORDER_MAX; + divider = UIUtil.dip2px(context, 10); + + mTwoImageHeight = (ScreenUtils.getScreenWidth(context) - UIUtil.dip2px(context, 17 + 29 + 22.5 + 20 + 10)) / 2; + mThreeImageHeight = (ScreenUtils.getScreenWidth(context) - UIUtil.dip2px(context, 17 + 29 + 22.5 + 20 + 20)) / 3; + } + + @Override + protected void convert(BaseViewHolder helper, UserDynamicItem item) { + + if (item == null) { + return; + } + + switch (item.getItemType()) { + case UserDynamicItem.TYPE_DYNAMIC: + setDynamic(helper, item); + break; + + case UserDynamicItem.TYPE_EMPTY: + break; + } + } + + private void setDynamic(BaseViewHolder helper, UserDynamicItem item) { + WorldDynamicBean userDynamicInfo = (WorldDynamicBean) item.getData(); + if (userDynamicInfo == null) { + return; + } + + List list = getData(); + int position = list.indexOf(item); + helper.setGone(R.id.v_divider_user_dynamic, position != (list.size() - 1)); + + helper.setGone(R.id.rv_img, false); + helper.setGone(R.id.fl_multi_media_dynamic_list, false); + + switch (userDynamicInfo.getType()) { + case 0: + helper.setImageResource(R.id.iv_type_img_dynamic_list, R.drawable.ic_text_dynamic); + break; + case 1: + helper.setImageResource(R.id.iv_type_img_dynamic_list, R.drawable.ic_voice_dynamic); + break; + case 2: + helper.setImageResource(R.id.iv_type_img_dynamic_list, R.drawable.ic_img_dynamic) + .setGone(R.id.fl_multi_media_dynamic_list, true); + setPhoto(helper, userDynamicInfo); + break; + case 3: + helper.setImageResource(R.id.iv_type_img_dynamic_list, R.drawable.ic_video_dynamic); + break; + } + + if (userDynamicInfo.isSystemDynamic()) { // 系统为未发布过动态的用户自动生成的动态 + helper.setImageResource(R.id.iv_type_img_dynamic_list, R.drawable.ic_text_dynamic) + .setGone(R.id.cl_bottom_user_dynamic_list, false); + } else { + helper.setGone(R.id.cl_bottom_user_dynamic_list, true); + } + + + String time = TimeUtils.getTimeStringFromMillis(userDynamicInfo.getPublishTime()); + if (!TextUtils.isEmpty(time)) { + helper.setText(R.id.tv_time_dynamic_list, time); + } + + if (!TextUtils.isEmpty(userDynamicInfo.getTag())) { + helper.setText(R.id.tv_name_mini_world, userDynamicInfo.getTag()) + .setVisible(R.id.tv_name_mini_world, true); + } else { + helper.setVisible(R.id.tv_name_mini_world, false); + } + + ExpandableTextView etvTranslateContent = helper.getView(R.id.tv_content_dynamic_list); + etvTranslateContent.setEventType(2); + String content = userDynamicInfo.getContent(); + if (TextUtils.isEmpty(content)) { + etvTranslateContent.setVisibility(View.GONE); + } else { + etvTranslateContent.setVisibility(View.VISIBLE); + etvTranslateContent.setText(content, mCollapsedStatus, helper.getAdapterPosition(), mCollapsedHeightStatus); + } + + helper.setText(R.id.tv_comment_user_dynamic_list, getNumString(userDynamicInfo.getCommentCount())); + + helper.addOnClickListener(R.id.tv_comment_user_dynamic_list) + .addOnClickListener(R.id.iv_share_user_dynamic_list) + .addOnClickListener(R.id.iv_more_user_dynamic_list) + .addOnClickListener(R.id.cl_item_dynamic_list) + .addOnClickListener(R.id.tv_name_mini_world); + + setLikeCount(helper, userDynamicInfo.getLikeCount(), userDynamicInfo.isLike(), false); + LinearLayout llLike = helper.getView(R.id.ll_like_user_dynamic_list); + long worldId = userDynamicInfo.getWorldId(); + long dynamicId = userDynamicInfo.getDynamicId(); + // 点赞 + llLike.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + llLike.setEnabled(false); + int status = userDynamicInfo.isLike() ? 0 : 1; + DynamicModel.get().like(worldId, dynamicId, currentUid, status, 2) + .compose(RxHelper.bindContext(mContext)) + .subscribe(new DontWarnObserver() { + @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.community_user_dynamic_userdynamicadapter_01)); + if (status == 1) { + userDynamicInfo.setLikeCount(userDynamicInfo.getLikeCount() + 1); + } else { + userDynamicInfo.setLikeCount(userDynamicInfo.getLikeCount() - 1); + } + userDynamicInfo.setLike(status == 1); + setLikeCount(helper, userDynamicInfo.getLikeCount(), userDynamicInfo.isLike(), true); + } + } + }); + } + }); + + } + + private void setPhoto(BaseViewHolder helper, WorldDynamicBean userDynamicInfo) { + RecyclerView rvImage = helper.getView(R.id.rv_img); + rvImage.setNestedScrollingEnabled(false); + try { + rvImage.removeItemDecorationAt(0); + + } catch (Exception ex) { + ex.printStackTrace(); + } + List imageUrl = userDynamicInfo.getDynamicResList(); + if (imageUrl != null && imageUrl.size() > 0) { + 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; + params.height = calcSize.height + divider; + } + rvImage.setLayoutParams(params); + + rvImage.setVisibility(View.VISIBLE); + rvImage.setLayoutManager(new GridLayoutManager(mContext, imageUrl.size() > 2 ? 3 : imageUrl.size())); + rvImage.addItemDecoration(new GridSpacingItemDecoration(mContext, imageUrl.size() > 2 ? 3 : imageUrl.size(), 10)); + DynamicImageAdapter adapter = new DynamicImageAdapter(R.layout.item_user_dynamic_image, imageUrl); + adapter.setSingleImageHeight(calcSize.height); + adapter.setMTwoImageHeight(mTwoImageHeight); + adapter.setMThreeImageHeight(mThreeImageHeight); + adapter.setOnItemClickListener((adapter1, view, position) -> { + PagerOption option = new PagerOption().setSave(true); + BigPhotoActivity.start((Activity) mContext, ObjectTypeHelper.mediaToCustomList(imageUrl), + position, option); + } + ); + rvImage.setAdapter(adapter); + + } else { + rvImage.setVisibility(View.GONE); + + } + + } + + private String getNumString(int count) { + String countStr; + if (count < 0) { + countStr = "0"; + } else if (count >= 1000) { + countStr = "999+"; + } else { + countStr = String.valueOf(count); + } + + return countStr; + + } + + private void setLikeCount(BaseViewHolder helper, int likeCount, boolean isLike, boolean isAnim) { + TextView tvLike = helper.getView(R.id.tv_like_user_dynamic_list); + String likeCountStr = getNumString(likeCount); + tvLike.setText(likeCountStr); + + ImageView ivLikeAnim = helper.getView(R.id.iv_like_anim); + if (isLike) { + if (isAnim) { + AnimationDrawable drawable = (AnimationDrawable) mContext.getResources() + .getDrawable(R.drawable.anim_list_dy_like); + ivLikeAnim.setImageDrawable(drawable); + drawable.stop(); + drawable.start(); + } else { + ivLikeAnim.setImageResource(R.drawable.icon_dy_list_like_00013); + } + } else { + ivLikeAnim.setImageResource(R.drawable.icon_dy_list_like_false); + } + + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicFrg.java b/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicFrg.java new file mode 100644 index 000000000..2f956da02 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicFrg.java @@ -0,0 +1,258 @@ +package com.chwl.app.community.user_dynamic; + +import android.os.Bundle; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chwl.app.R; +import com.chwl.app.UIHelper; +import com.chwl.app.base.BaseMvpFragment; +import com.chwl.app.common.widget.dialog.DialogManager; +import com.chwl.app.community.dynamic.view.DynamicDetailActivity; +import com.chwl.app.community.helper.ShareDynamicHelper; +import com.chwl.app.ui.widget.ButtonItem; +import com.chwl.core.XConstants; +import com.chwl.core.auth.AuthModel; +import com.chwl.core.community.bean.UserDynamicItem; +import com.chwl.core.community.bean.WorldDynamicBean; +import com.chwl.library.base.factory.CreatePresenter; +import com.chwl.library.utils.ResUtil; + +import java.util.ArrayList; +import java.util.List; + +@CreatePresenter(UserDynamicPresenter.class) +public class UserDynamicFrg extends BaseMvpFragment implements IUserDynamicView { + + private UserDynamicAdapter mUserDynamicAdapter; + + private RecyclerView recyclerView; + private SwipeRefreshLayout swipeRefreshLayout; + + private WorldDynamicBean currentUserDynamic; + + public static UserDynamicFrg newInstance(long userId) { + UserDynamicFrg userDynamicFrg = new UserDynamicFrg(); + Bundle bundle = new Bundle(); + bundle.putLong("userId", userId); + userDynamicFrg.setArguments(bundle); + return userDynamicFrg; + } + + @Override + protected void onInitArguments(Bundle bundle) { + super.onInitArguments(bundle); + if (bundle != null) { + long userId = bundle.getLong("userId", 0); + getMvpPresenter().setUserId(userId); + } + } + + @Override + public int getRootLayoutId() { + return R.layout.frg_user_dynamic; + } + + @Override + public void onFindViews() { + recyclerView = mView.findViewById(R.id.recycler_view); + swipeRefreshLayout = mView.findViewById(R.id.srl_user_dynamic); + } + + @Override + public void onSetListener() { + + } + + @Override + public void initiate() { + getMvpPresenter().setFromUid(AuthModel.get().getCurrentUid()); + + swipeRefreshLayout.setOnRefreshListener(() -> getMvpPresenter().refreshData()); + + mUserDynamicAdapter = new UserDynamicAdapter(getActivity(), getMvpPresenter().getUserId()); + mUserDynamicAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() { + @Override + public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { + + List list = adapter.getData(); + if (position < list.size()) { + UserDynamicItem userDynamicItem = list.get(position); + if (userDynamicItem.getItemType() == UserDynamicItem.TYPE_DYNAMIC) { + WorldDynamicBean userDynamicInfo = (WorldDynamicBean) userDynamicItem.getData(); + if (userDynamicInfo != null) { + currentUserDynamic = userDynamicInfo; + + switch (view.getId()) { + // 点赞在adapter + case R.id.tv_comment_user_dynamic_list:// 评论 + DynamicDetailActivity.start(mContext, userDynamicInfo.getDynamicId(), + userDynamicInfo.getWorldId(), true, 2); + break; + + case R.id.iv_share_user_dynamic_list:// 分享 + if (currentUserDynamic.getStatus() == 1) { + new ShareDynamicHelper(getActivity()).share(userDynamicInfo, userDynamicInfo.getWorldId()); + } else if (currentUserDynamic.getStatus() == 0) { + toast(ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_03)); + } else if (currentUserDynamic.getStatus() == 2) { + toast(ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_04)); + } + break; + + case R.id.iv_more_user_dynamic_list: // 更多 + showMoreOptions(); + break; + +// case R.id.tv_name_mini_world: // 话题 +// TopicMainActivity.start(mContext, +// String.valueOf(currentUserDynamic.getWorldId())); +// break; + + case R.id.cl_item_dynamic_list: // 动态详情 + if (!userDynamicInfo.isSystemDynamic()) { + DynamicDetailActivity.start(mContext, userDynamicInfo.getDynamicId(), + userDynamicInfo.getWorldId(), 2); + } + break; + } + + } + } + } + } + }); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext, + LinearLayoutManager.VERTICAL, false)); + recyclerView.setAdapter(mUserDynamicAdapter); + mUserDynamicAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { + @Override + public void onLoadMoreRequested() { + getMvpPresenter().loadMore(); + + } + }, recyclerView); + + getMvpPresenter().refreshData(); + } + + @Override + public void refreshSuccess(List list) { + swipeRefreshLayout.setRefreshing(false); + if (mUserDynamicAdapter != null) { +// mUserDynamicAdapter.resetStatus(); + List tempList = getMvpPresenter().modifyData(list, true); + mUserDynamicAdapter.setNewData(tempList); + mUserDynamicAdapter.loadMoreComplete(); + } + + } + + @Override + public void refreshFail(String error) { + swipeRefreshLayout.setRefreshing(false); + List userDynamicItems = new ArrayList<>(1); + userDynamicItems.add(new UserDynamicItem(UserDynamicItem.TYPE_EMPTY)); + if (mUserDynamicAdapter != null) { + mUserDynamicAdapter.setNewData(userDynamicItems); + mUserDynamicAdapter.setEnableLoadMore(false); + } + + } + + @Override + public void loadSuccess(List list) { + mUserDynamicAdapter.loadMoreComplete(); + if (mUserDynamicAdapter != null) { + List tempList = getMvpPresenter().modifyData(list, false); + mUserDynamicAdapter.addData(tempList); + } + + } + + @Override + public void loadFail(String error) { + mUserDynamicAdapter.loadMoreComplete(); + mUserDynamicAdapter.loadMoreEnd(); + } + + @Override + public void deleteSuccess(long dynamicId) { + + if (mUserDynamicAdapter != null) { + List list = mUserDynamicAdapter.getData(); + + int currentPosition = -1; + for (int i = 0; i < list.size(); i++) { + WorldDynamicBean userDynamicInfo = (WorldDynamicBean) (list.get(i)).getData(); + // 第一个item为分割线,需要判断data是否为空 + if (userDynamicInfo != null && userDynamicInfo.getDynamicId() == dynamicId) { + currentPosition = i; + break; + } + } + + if (currentPosition > -1 && currentPosition < list.size()) { + mUserDynamicAdapter.remove(currentPosition); + } + } + + } + + @Override + public void deleteFail(String error) { + toast(error); + } + + private void showMoreOptions() { + if (getMvpPresenter().isOwner()) { + showDeleteOption(); + + } else { + showReportOption(); + } + + } + + private void showReportOption() { + ButtonItem buttonItem1 = new ButtonItem(ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_09), () -> { + if (currentUserDynamic != null) { + UIHelper.showReportPage(mContext, currentUserDynamic.getUid(), + XConstants.REPORT_TYPE_PERSONAL_DYNAMIC); + } + }); + List buttonItems = new ArrayList<>(); + buttonItems.add(buttonItem1); + getDialogManager().showCommonPopupDialog(buttonItems, ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_010), false); + + } + + private void showDeleteOption() { + ButtonItem buttonItem1 = new ButtonItem(ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_011), () -> { + secondDeleteDialog(); + }); + List buttonItems = new ArrayList<>(); + buttonItems.add(buttonItem1); + getDialogManager().showCommonPopupDialog(buttonItems, ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_012), false); + } + + private void secondDeleteDialog() { + getDialogManager().showOkCancelDialog(ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_013), + ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_014), + ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_015), ResUtil.getString(R.string.community_user_dynamic_userdynamicfrg_016), + new DialogManager.OkCancelDialogListener() { + @Override + public void onOk() { + if (currentUserDynamic != null) { + getMvpPresenter().deleteDynamic(currentUserDynamic.getWorldId(), + currentUserDynamic.getDynamicId()); + } + } + }); + + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicPresenter.java b/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicPresenter.java new file mode 100644 index 000000000..fbb50c264 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/user_dynamic/UserDynamicPresenter.java @@ -0,0 +1,146 @@ +package com.chwl.app.community.user_dynamic; + +import android.annotation.SuppressLint; + +import androidx.annotation.Keep; + +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpPresenter; +import com.chwl.core.Constants; +import com.chwl.core.community.bean.UserDynamicItem; +import com.chwl.core.community.bean.WorldDynamicBean; +import com.chwl.core.community.dynamic.DynamicModel; +import com.chwl.core.user.UserDynamicModel; +import com.chwl.library.utils.ResUtil; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.functions.BiConsumer; + +@Keep +public class UserDynamicPresenter extends BaseMvpPresenter { + + private int page = Constants.PAGE_START; + private int pageSize = Constants.PAGE_SIZE; + private String types = "0,2"; // 0-纯文本 1-语音 2-图片 3-视频 + private UserDynamicModel userDynamicModel = new UserDynamicModel(); + private long userId; + private long fromUid; + + @SuppressLint("CheckResult") + public void refreshData() { + page = Constants.PAGE_START; + + userDynamicModel.getMyDynamic(userId, types, page, pageSize, fromUid) + .compose(bindToLifecycle()) + .subscribe(new BiConsumer, Throwable>() { + @Override + public void accept(List userDynamicInfos, Throwable throwable) throws Exception { + if (throwable == null) { + if (userDynamicInfos != null && userDynamicInfos.size() > 0) { + if (mMvpView != null) { + mMvpView.refreshSuccess(userDynamicInfos); + } + } else { + if (mMvpView != null) { + mMvpView.refreshFail(ResUtil.getString(R.string.community_user_dynamic_userdynamicpresenter_01)); + } + + } + + } else { + if (mMvpView != null) { + mMvpView.refreshFail(throwable.getMessage()); + } + } + + } + }); + } + + @SuppressLint("CheckResult") + public void loadMore() { + page++; + + userDynamicModel.getMyDynamic(userId, types, page, pageSize, fromUid) + .compose(bindToLifecycle()) + .subscribe(new BiConsumer, Throwable>() { + @Override + public void accept(List userDynamicInfos, Throwable throwable) throws Exception { + if (throwable == null) { + if (userDynamicInfos != null && userDynamicInfos.size() > 0) { + if (mMvpView != null) { + mMvpView.loadSuccess(userDynamicInfos); + } + } else { + if (mMvpView != null) { + mMvpView.loadFail(ResUtil.getString(R.string.community_user_dynamic_userdynamicpresenter_02)); + } + } + + } else { + page--; + if (mMvpView != null) { + mMvpView.loadFail(throwable.getMessage()); + } + } + + } + }); + } + + public List modifyData(List list, boolean isFirst) { + List tempList = new ArrayList<>(); + if (isFirst) { + UserDynamicItem userDynamicItem = new UserDynamicItem(UserDynamicItem.TYPE_FIRST_DIVIDER); + tempList.add(userDynamicItem); + } + for (WorldDynamicBean userDynamicInfo : list) { + UserDynamicItem userDynamicItem = new UserDynamicItem(UserDynamicItem.TYPE_DYNAMIC, + userDynamicInfo); + tempList.add(userDynamicItem); + } + + return tempList; + } + + @SuppressLint("CheckResult") + public void deleteDynamic(long worldId, long dynamicId) { + DynamicModel.get().delete(worldId, dynamicId) + .compose(bindToLifecycle()) + .subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + + if (throwable == null) { + if (mMvpView != null) { + mMvpView.deleteSuccess(dynamicId); + } + } else { + if (mMvpView != null) { + mMvpView.deleteFail(throwable.getMessage()); + } + } + + } + }); + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public long getUserId() { + return userId; + } + + public void setFromUid(long fromUid) { + this.fromUid = fromUid; + } + + public boolean isOwner() { + return fromUid == userId; + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/utils/ObjectTypeHelper.java b/app/src/module_community/java/com/chwl/app/community/utils/ObjectTypeHelper.java new file mode 100644 index 000000000..933affb12 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/utils/ObjectTypeHelper.java @@ -0,0 +1,81 @@ +package com.chwl.app.community.utils; + +import com.chwl.core.community.bean.DynamicMedia; +import com.example.matisse.internal.entity.CustomItem; + +import java.util.ArrayList; +import java.util.List; + +/** + * create by lvzebiao @2019/11/19 + */ +public class ObjectTypeHelper { + + public static List customToStringList(List paramsList) { + List resultList = new ArrayList<>(); + if (paramsList == null) { + return resultList; + } + for (CustomItem item : paramsList) { + resultList.add(item.getPath()); + } + return resultList; + } + + public static List customToMediaList(List paramsList) { + List resultList = new ArrayList<>(); + if (paramsList == null) { + return resultList; + } + for (CustomItem item : paramsList) { + DynamicMedia media = new DynamicMedia(); + media.setLocalFilePath(item.getPath()); + media.setWidth(item.getWidth()); + media.setHeight(item.getHeight()); + media.setFormat(item.getFormat()); + resultList.add(media); + } + return resultList; + } + + public static List stringToCustomList(List paramsList) { + List resultList = new ArrayList<>(); + if (paramsList == null) { + return resultList; + } + for (String item : paramsList) { + resultList.add(new CustomItem(item, 0)); + } + return resultList; + } + + public static ArrayList mediaToCustomList(List paramsList) { + ArrayList resultList = new ArrayList<>(); + if (paramsList == null) { + return resultList; + } + for (DynamicMedia media : paramsList) { + CustomItem item = new CustomItem(); + item.setPath(media.getResUrl()); + item.setFileType(CustomItem.UNKOWN); + if (media.isJpgOrPng()) { + item.setFileType(CustomItem.IMAGE_NORMAL); + } else if (media.isGif()) { + item.setFileType(CustomItem.GIF); + } + item.setFormat(media.getFormat()); + resultList.add(item); + } + return resultList; + } + + public static ArrayList pathToCustomItems(String path) { + ArrayList resultList = new ArrayList<>(); + CustomItem item = new CustomItem(); + item.setPath(path); + item.setFileType(CustomItem.UNKOWN); + resultList.add(item); + return resultList; + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/utils/TopicUpTextWrapper.kt b/app/src/module_community/java/com/chwl/app/community/utils/TopicUpTextWrapper.kt new file mode 100644 index 000000000..2e92fffb2 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/utils/TopicUpTextWrapper.kt @@ -0,0 +1,34 @@ +package com.chwl.app.community.utils + +import android.content.Context +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.text.SpannableStringBuilder +import android.text.Spanned +import android.text.style.ForegroundColorSpan +import com.chwl.app.R +import com.chwl.app.common.widget.CustomImageSpan +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil +import com.chwl.library.utils.ResUtil + +object TopicUpTextWrapper { + + //置顶 后期优化结构 + fun wrapUp(originText: CharSequence, context: Context): SpannableStringBuilder? { + val drawable: Drawable = context.resources.getDrawable(R.drawable.topic_up_drawable) + drawable.setBounds(0, 0, UIUtil.dip2px(context, 10.0), UIUtil.dip2px(context, 12.0)) + val builder = SpannableStringBuilder() + builder.append("-") + builder.append(ResUtil.getString(R.string.community_utils_topicuptextwrapper_01)) + builder.setSpan(CustomImageSpan(drawable), 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) + builder.setSpan( + ForegroundColorSpan(Color.parseColor("#E84C46")), + 1, + builder.length, + Spanned.SPAN_INCLUSIVE_EXCLUSIVE + ) + builder.append(" ") + builder.append(originText) + return builder + } +} \ No newline at end of file diff --git a/app/src/module_community/java/com/chwl/app/community/widget/DynamicNickDetailWidget.java b/app/src/module_community/java/com/chwl/app/community/widget/DynamicNickDetailWidget.java new file mode 100644 index 000000000..e722a66d4 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/widget/DynamicNickDetailWidget.java @@ -0,0 +1,99 @@ +package com.chwl.app.community.widget; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.ColorInt; +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.netease.nim.uikit.support.glide.GlideApp; +import com.chwl.app.R; +import com.chwl.app.ui.utils.ImageLoadUtils; +import com.chwl.app.utils.NamePlateHelper; +import com.chwl.app.utils.RegexUtil; +import com.chwl.app.utils.TimeUiUtils; +import com.chwl.app.view.GenderAgeTextView; +import com.chwl.app.vip.util.VipHelper; +import com.chwl.core.user.bean.BaseUserInfo; +import com.chwl.library.widget.ShapeConstrainLayout; + +/** + * create by lvzebiao @2019/11/26 + */ +public class DynamicNickDetailWidget extends ShapeConstrainLayout { + + private TextView tvNick; + private GenderAgeTextView tvGenderAge; + private ImageView ivVipIcon; + + private ImageView ivUserWealthLevel; + private ImageView ivUserCharmLevel; + + private ConstraintLayout inOfficialMask; + + private TextView tvTime; + + private Context context; + + public DynamicNickDetailWidget(Context context) { + this(context, null); + } + + public DynamicNickDetailWidget(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DynamicNickDetailWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.context = context; + init(context); + } + + private void init(Context context) { + inflate(context, R.layout.layout_dy_nick_detail, this); + + tvNick = findViewById(R.id.tv_nick); + tvGenderAge = findViewById(R.id.tv_gender_age); + ivVipIcon = findViewById(R.id.iv_vip_icon); + ivUserWealthLevel = findViewById(R.id.iv_user_wealth_level); + ivUserCharmLevel = findViewById(R.id.iv_user_charm_level); + inOfficialMask = findViewById(R.id.in_official_mask); + tvTime = findViewById(R.id.tv_time); + } + + public void setNickColor(@ColorInt int color) { + if (tvNick != null) { + tvNick.setTextColor(color); + } + } + + public void setTimeColor(@ColorInt int color) { + if (tvTime != null) { + tvTime.setTextColor(color); + } + } + + public void setData(BaseUserInfo info) { + tvNick.setText(RegexUtil.getPrintableString(info.getNick())); + tvGenderAge.setText(String.valueOf(info.getAge())); + tvGenderAge.setGender(info.getGender()); + //财富等级 + ImageLoadUtils.loadImage(context, info.getExperLevelPic(), ivUserWealthLevel); + //魅力等级 + ImageLoadUtils.loadImage(context, info.getCharmLevelPic(), ivUserCharmLevel); + //铭牌 + NamePlateHelper.INSTANCE.load(inOfficialMask, inOfficialMask.findViewById(R.id.tv_official_mask), inOfficialMask.findViewById(R.id.iv_official_mask), info.getNameplateWord(), info.getNameplatePic(), info.isCustomWord()); + VipHelper.loadVipIcon(ivVipIcon, info.getUserVipInfoVO()); + } + + public void setTime(long time) { + tvTime.setVisibility(View.VISIBLE); + tvTime.setText(TimeUiUtils.getDynamicUi(time)); + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/widget/ExpandableTextView.java b/app/src/module_community/java/com/chwl/app/community/widget/ExpandableTextView.java new file mode 100644 index 000000000..b47bff879 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/widget/ExpandableTextView.java @@ -0,0 +1,533 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * Copyright 2014 Manabu Shimobe + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.chwl.app.community.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.SparseBooleanArray; +import android.util.SparseIntArray; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.Transformation; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.DrawableRes; +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.chwl.app.R; +import com.chwl.library.utils.ResUtil; + +import lombok.Setter; + + +public class ExpandableTextView extends LinearLayout implements View.OnClickListener { + + private static final String TAG = ExpandableTextView.class.getSimpleName(); + + private static final int EXPAND_INDICATOR_IMAGE_BUTTON = 0; + + private static final int EXPAND_INDICATOR_TEXT_VIEW = 1; + + private static final int DEFAULT_TOGGLE_TYPE = EXPAND_INDICATOR_IMAGE_BUTTON; + + /* The default number of lines */ + private static final int MAX_COLLAPSED_LINES = 8; + + /* The default animation duration */ + private static final int DEFAULT_ANIM_DURATION = 300; + + /* The default alpha value when the animation starts */ + private static final float DEFAULT_ANIM_ALPHA_START = 0.7f; + + public TextView mTv; + + protected View mToggleView; // View to expand/collapse + + private boolean mRelayout; + + private boolean mCollapsed = true; // Show short version as default. + + private int mCollapsedHeight; + + private int mTextHeightWithMaxLines; + + private int mMaxCollapsedLines; + + private int mMarginBetweenTxtAndBottom; + + private ExpandIndicatorController mExpandIndicatorController; + + private int mAnimationDuration; + + private float mAnimAlphaStart; + + private boolean mAnimating; + + @IdRes + private int mExpandableTextId = R.id.expandable_text; + + @IdRes + private int mExpandCollapseToggleId = R.id.expand_collapse; + + private boolean mExpandToggleOnTextClick; + + /* Listener for callback */ + private OnExpandStateChangeListener mListener; + + /* For saving collapsed status when used in ListView */ + private SparseBooleanArray mCollapsedStatus; + private int mPosition; + /** + * 用于列表,文字展开之后记录固定值:mCollapsedHeight, mMarginBetweenTxtAndBottom + * 点击收起按钮,避免固定值为0,文字不展示的情况 + */ + private SparseIntArray mCollapsedHeightStatus; + + private int mImageToggleId; + private ImageView mIvToggle; + /** + * 1、世界动态 2 个人主页 3-动态详情 4-动态广场 + */ + @Setter + private int eventType; + + public ExpandableTextView(Context context) { + this(context, null); + } + + public ExpandableTextView(Context context, AttributeSet attrs) { + super(context, attrs); + init(attrs); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public ExpandableTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(attrs); + } + + @Override + public void setOrientation(int orientation) { + if (LinearLayout.HORIZONTAL == orientation) { + throw new IllegalArgumentException("ExpandableTextView only supports Vertical Orientation."); + } + super.setOrientation(orientation); + } + + @Override + public void onClick(View view) { + if (mToggleView.getVisibility() != View.VISIBLE) { + return; + } + + mCollapsed = !mCollapsed; + mExpandIndicatorController.changeState(mCollapsed); + + if (mCollapsedStatus != null) { + mCollapsedStatus.put(mPosition, mCollapsed); + } + + // mark that the animation is in progress + mAnimating = true; + + Animation animation; + + if (mCollapsed) { + int height = getHeight(); + if (mCollapsedHeight == 0 && mCollapsedHeightStatus != null) { + mCollapsedHeight = mCollapsedHeightStatus.get(0); + } + + if (mMarginBetweenTxtAndBottom <= 0 && mCollapsedHeightStatus != null) { + mMarginBetweenTxtAndBottom = mCollapsedHeightStatus.get(1); + } + + animation = new ExpandCollapseAnimation(this, height, mCollapsedHeight); + } else { + String label = ResUtil.getString(R.string.community_widget_expandabletextview_01); + if (eventType == 2) { + label = ResUtil.getString(R.string.community_widget_expandabletextview_02); + } else if (eventType == 3) { + label = ResUtil.getString(R.string.community_widget_expandabletextview_03); + } else if (eventType == 4) { + label = ResUtil.getString(R.string.community_widget_expandabletextview_04); + } + + int height = getHeight(); + int tvHeight = mTv.getHeight(); + animation = new ExpandCollapseAnimation(this, height, height + + mTextHeightWithMaxLines - tvHeight); + + if (mCollapsedHeight > 0 && mCollapsedHeightStatus != null) { + mCollapsedHeightStatus.put(0, mCollapsedHeight); + } + if (mMarginBetweenTxtAndBottom > 0 && mCollapsedHeightStatus != null) { + mCollapsedHeightStatus.put(1, mMarginBetweenTxtAndBottom); + } + } + + animation.setFillAfter(true); + animation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + applyAlphaAnimation(mTv, mAnimAlphaStart); + } + + @Override + public void onAnimationEnd(Animation animation) { + // clear animation here to avoid repeated applyTransformation() calls + clearAnimation(); + // clear the animation flag + mAnimating = false; + + // notify the listener + if (mListener != null) { + mListener.onExpandStateChanged(mTv, !mCollapsed); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + + clearAnimation(); + startAnimation(animation); + + if (mImageToggleId != 0) { + mIvToggle.animate().rotationBy(180).setDuration(DEFAULT_ANIM_DURATION).start(); + } + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + // while an animation is in progress, intercept all the touch events to children to + // prevent extra clicks during the animation + return mAnimating; + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + findViews(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // If no change, measure and return + if (!mRelayout || getVisibility() == View.GONE) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; + } + mRelayout = false; + + // Setup with optimistic case + // i.e. Everything fits. No button needed + mToggleView.setVisibility(View.GONE); + if (mIvToggle != null) { + mIvToggle.setVisibility(GONE); + } + mTv.setMaxLines(Integer.MAX_VALUE); + + // Measure + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + // If the text fits in collapsed mode, we are done. + if (mTv.getLineCount() <= mMaxCollapsedLines) { + return; + } + + // Saves the text height w/ max lines + mTextHeightWithMaxLines = getRealTextViewHeight(mTv); + + // Doesn't fit in collapsed mode. Collapse text view as needed. Show + // button. + if (mCollapsed) { + mTv.setMaxLines(mMaxCollapsedLines); + } + mToggleView.setVisibility(View.VISIBLE); + if (mIvToggle != null) { + mIvToggle.setVisibility(VISIBLE); + } + + // Re-measure with new setup + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + if (mCollapsed) { + // Gets the margin between the TextView's bottom and the ViewGroup's bottom + mTv.post(new Runnable() { + @Override + public void run() { + mMarginBetweenTxtAndBottom = getHeight() - mTv.getHeight(); + } + }); + // Saves the collapsed height of this ViewGroup + mCollapsedHeight = getMeasuredHeight(); + } + } + + public void setOnExpandStateChangeListener(@Nullable OnExpandStateChangeListener listener) { + mListener = listener; + } + + public void setText(@Nullable CharSequence text) { + mRelayout = true; + mTv.setText(text); + setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE); + clearAnimation(); + getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; + requestLayout(); + } + + public void setText(@Nullable CharSequence text, @NonNull SparseBooleanArray collapsedStatus, int position) { + mCollapsedStatus = collapsedStatus; + mPosition = position; + boolean isCollapsed = collapsedStatus.get(position, true); + clearAnimation(); + mCollapsed = isCollapsed; + mExpandIndicatorController.changeState(mCollapsed); + setText(text); + } + + public void setText(@Nullable CharSequence text, @NonNull SparseBooleanArray collapsedStatus, int position, + @NonNull SparseIntArray mCollapsedHeightStatus) { + this.mCollapsedHeightStatus = mCollapsedHeightStatus; + setText(text, collapsedStatus, position); + } + + @Nullable + public CharSequence getText() { + if (mTv == null) { + return ""; + } + return mTv.getText(); + } + + private void init(AttributeSet attrs) { + TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ExpandableTextView); + mMaxCollapsedLines = typedArray.getInt(R.styleable.ExpandableTextView_maxCollapsedLines, MAX_COLLAPSED_LINES); + mAnimationDuration = typedArray.getInt(R.styleable.ExpandableTextView_animDuration, DEFAULT_ANIM_DURATION); + mAnimAlphaStart = typedArray.getFloat(R.styleable.ExpandableTextView_animAlphaStart, DEFAULT_ANIM_ALPHA_START); + mExpandableTextId = typedArray.getResourceId(R.styleable.ExpandableTextView_expandableTextId, R.id.expandable_text); + mExpandCollapseToggleId = typedArray.getResourceId(R.styleable.ExpandableTextView_expandCollapseToggleId, R.id.expand_collapse); + mExpandToggleOnTextClick = typedArray.getBoolean(R.styleable.ExpandableTextView_expandToggleOnTextClick, true); + + mExpandIndicatorController = setupExpandToggleController(getContext(), typedArray); + + mImageToggleId = typedArray.getResourceId(R.styleable.ExpandableTextView_imageToggleId, 0); + + typedArray.recycle(); + + // enforces vertical orientation + setOrientation(LinearLayout.VERTICAL); + + // default visibility is gone + setVisibility(GONE); + } + + private void findViews() { + mTv = (TextView) findViewById(mExpandableTextId); + if (mExpandToggleOnTextClick) { + mTv.setOnClickListener(this); + } else { + mTv.setOnClickListener(null); + } + mToggleView = findViewById(mExpandCollapseToggleId); + mExpandIndicatorController.setView(mToggleView); + mExpandIndicatorController.changeState(mCollapsed); + mToggleView.setOnClickListener(this); + if (mImageToggleId != 0) { + mIvToggle = findViewById(mImageToggleId); + } + } + + private static boolean isPostHoneycomb() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + } + + private static boolean isPostLolipop() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private static void applyAlphaAnimation(View view, float alpha) { + if (isPostHoneycomb()) { + view.setAlpha(alpha); + } else { + AlphaAnimation alphaAnimation = new AlphaAnimation(alpha, alpha); + // make it instant + alphaAnimation.setDuration(0); + alphaAnimation.setFillAfter(true); + view.startAnimation(alphaAnimation); + } + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private static Drawable getDrawable(@NonNull Context context, @DrawableRes int resId) { + Resources resources = context.getResources(); + if (isPostLolipop()) { + return resources.getDrawable(resId, context.getTheme()); + } else { + return resources.getDrawable(resId); + } + } + + private static int getRealTextViewHeight(@NonNull TextView textView) { + int textHeight = textView.getLayout().getLineTop(textView.getLineCount()); + int padding = textView.getCompoundPaddingTop() + textView.getCompoundPaddingBottom(); + return textHeight + padding; + } + + private static ExpandIndicatorController setupExpandToggleController(@NonNull Context context, TypedArray typedArray) { + final int expandToggleType = typedArray.getInt(R.styleable.ExpandableTextView_expandToggleType, DEFAULT_TOGGLE_TYPE); + final ExpandIndicatorController expandIndicatorController; + switch (expandToggleType) { + case EXPAND_INDICATOR_IMAGE_BUTTON: + Drawable expandDrawable = typedArray.getDrawable(R.styleable.ExpandableTextView_expandIndicator); + Drawable collapseDrawable = typedArray.getDrawable(R.styleable.ExpandableTextView_collapseIndicator); + + if (expandDrawable == null) { + expandDrawable = getDrawable(context, R.drawable.ic_back_dynamic); + } + if (collapseDrawable == null) { + collapseDrawable = getDrawable(context, R.drawable.ic_back_dynamic); + } + expandIndicatorController = new ImageButtonExpandController(expandDrawable, collapseDrawable); + break; + case EXPAND_INDICATOR_TEXT_VIEW: + String expandText = typedArray.getString(R.styleable.ExpandableTextView_expandIndicator); + String collapseText = typedArray.getString(R.styleable.ExpandableTextView_collapseIndicator); + expandIndicatorController = new TextViewExpandController(expandText, collapseText); + break; + default: + throw new IllegalStateException("Must be of enum: ExpandableTextView_expandToggleType, one of EXPAND_INDICATOR_IMAGE_BUTTON or EXPAND_INDICATOR_TEXT_VIEW."); + } + + return expandIndicatorController; + } + + class ExpandCollapseAnimation extends Animation { + private final View mTargetView; + private final int mStartHeight; + private final int mEndHeight; + + public ExpandCollapseAnimation(View view, int startHeight, int endHeight) { + mTargetView = view; + mStartHeight = startHeight; + mEndHeight = endHeight; + setDuration(mAnimationDuration); + } + + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + final int newHeight = (int) ((mEndHeight - mStartHeight) * interpolatedTime + mStartHeight); + mTv.setMaxHeight(newHeight - mMarginBetweenTxtAndBottom); + if (Float.compare(mAnimAlphaStart, 1.0f) != 0) { + applyAlphaAnimation(mTv, mAnimAlphaStart + interpolatedTime * (1.0f - mAnimAlphaStart)); + } + mTargetView.getLayoutParams().height = newHeight; + mTargetView.requestLayout(); + } + + @Override + public void initialize(int width, int height, int parentWidth, int parentHeight) { + super.initialize(width, height, parentWidth, parentHeight); + } + + @Override + public boolean willChangeBounds() { + return true; + } + } + + public interface OnExpandStateChangeListener { + /** + * Called when the expand/collapse animation has been finished + * + * @param textView - TextView being expanded/collapsed + * @param isExpanded - true if the TextView has been expanded + */ + void onExpandStateChanged(TextView textView, boolean isExpanded); + } + + public interface ExpandIndicatorController { + void changeState(boolean collapsed); + + void setView(View toggleView); + } + + static class ImageButtonExpandController implements ExpandIndicatorController { + + private final Drawable mExpandDrawable; + private final Drawable mCollapseDrawable; + + private ImageButton mImageButton; + + public ImageButtonExpandController(Drawable expandDrawable, Drawable collapseDrawable) { + mExpandDrawable = expandDrawable; + mCollapseDrawable = collapseDrawable; + } + + @Override + public void changeState(boolean collapsed) { + mImageButton.setImageDrawable(collapsed ? mExpandDrawable : mCollapseDrawable); + } + + @Override + public void setView(View toggleView) { + mImageButton = (ImageButton) toggleView; + } + } + + static class TextViewExpandController implements ExpandIndicatorController { + + private final String mExpandText; + private final String mCollapseText; + + private TextView mTextView; + + public TextViewExpandController(String expandText, String collapseText) { + mExpandText = expandText; + mCollapseText = collapseText; + } + + @Override + public void changeState(boolean collapsed) { + mTextView.setText(collapsed ? mExpandText : mCollapseText); + } + + @Override + public void setView(View toggleView) { + mTextView = (TextView) toggleView; + } + } +} \ No newline at end of file diff --git a/app/src/module_community/java/com/chwl/app/community/widget/GridImageWidget.java b/app/src/module_community/java/com/chwl/app/community/widget/GridImageWidget.java new file mode 100644 index 000000000..9a9cb20fe --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/widget/GridImageWidget.java @@ -0,0 +1,135 @@ +package com.chwl.app.community.widget; + +import android.app.Activity; +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.chwl.app.R; +import com.chwl.app.community.helper.CalcSize; +import com.chwl.app.community.helper.ImageUiHelper; +import com.chwl.app.photo.BigPhotoActivity; +import com.chwl.app.photo.DynamicImageAdapter; +import com.chwl.app.community.utils.ObjectTypeHelper; +import com.chwl.app.photo.PagerOption; +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil; +import com.chwl.app.ui.widget.recyclerview.decoration.GridVItemDecoration; +import com.chwl.core.community.bean.DynamicMedia; +import com.chwl.core.community.bean.WorldDynamicBean; +import com.chwl.library.utils.ListUtils; + +import java.util.List; + +import lombok.Setter; + +/** + * create by lvzebiao @2020/1/8 + */ +public class GridImageWidget extends FrameLayout { + + @Setter + private int maxWidth; + + @Setter + private int dividerDp; + + private RecyclerView rvImage; + + private Context context; + /** + * recycleView格子布局时的宽度 + * 用于计算item的高度 + */ + @Setter + private int rvWidth; + + public GridImageWidget(@NonNull Context context) { + this(context, null); + } + + public GridImageWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public GridImageWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + inflate(context, R.layout.widget_grid_image, this); + this.context = context; + maxWidth = UIUtil.getScreenWidth(context) * ImageUiHelper.BORDER_MIN / ImageUiHelper.BORDER_MAX; + dividerDp = 10; + rvImage = findViewById(R.id.rv_image); + } + + public void setData(WorldDynamicBean item, int topMargin) { + setVisibility(View.GONE); + List dynamicMediaList = item.getDynamicResList(); + if (item.getType() == WorldDynamicBean.TYPE_IMAGE + && dynamicMediaList != null && dynamicMediaList.size() > 0) { + setData(dynamicMediaList, topMargin); + } + } + + public void setData(List imageUrl, int topMargin) { + setVisibility(GONE); + if (ListUtils.isListEmpty(imageUrl)) { + return; + } + setVisibility(VISIBLE); + + CalcSize calcSize = new CalcSize(maxWidth); + 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, maxWidth); + params.width = calcSize.width; + params.height = calcSize.height; + } + params.topMargin = topMargin; + rvImage.setLayoutParams(params); + rvImage.setNestedScrollingEnabled(false); + int spanCount = imageUrl.size() > 2 ? 3 : imageUrl.size(); + if (rvImage.getTag() != null) { + if (rvImage.getTag() instanceof RecyclerView.ItemDecoration) { + rvImage.removeItemDecoration((RecyclerView.ItemDecoration) rvImage.getTag()); + } + rvImage.setTag(null); + } + GridVItemDecoration decoration = new GridVItemDecoration(context, dividerDp, spanCount); + rvImage.setTag(decoration); + rvImage.addItemDecoration(decoration); + + rvImage.setLayoutManager(new GridLayoutManager(context, spanCount)); + DynamicImageAdapter adapter = new DynamicImageAdapter(R.layout.item_grid_image_widget, imageUrl); + //当2列时的高度 + adapter.setMTwoImageHeight((rvWidth - UIUtil.dip2px(context, 10)) / 2); + //当3列时的高度 + adapter.setMThreeImageHeight((rvWidth - UIUtil.dip2px(context, 20)) / 3); + adapter.setSingleImageHeight(calcSize.height); + adapter.setOnItemClickListener((adapter1, view, position) -> { + PagerOption option = new PagerOption().setSave(true); + BigPhotoActivity.start((Activity) context, ObjectTypeHelper.mediaToCustomList(imageUrl), + position, option); + } + ); + rvImage.setAdapter(adapter); + + } + +} diff --git a/app/src/module_community/java/com/chwl/app/community/widget/TopicLabelWidget.kt b/app/src/module_community/java/com/chwl/app/community/widget/TopicLabelWidget.kt new file mode 100644 index 000000000..868fcc4eb --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/widget/TopicLabelWidget.kt @@ -0,0 +1,50 @@ +package com.chwl.app.community.widget + +import android.content.Context +import android.os.Build +import android.util.AttributeSet +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.annotation.Nullable +import com.chwl.app.ui.utils.ImageLoadUtilsV2 +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil + +class TopicLabelWidget(context: Context, @Nullable attrs: AttributeSet) : + LinearLayout(context, attrs) { + private val leftMargin = UIUtil.dip2px(context, 4.toDouble()) + + init { + orientation = HORIZONTAL + } + + fun setLabels(labels: List) { + if (childCount != 0) { + removeAllViews() + } + val width = UIUtil.dip2px(context, 28.0) + val height = UIUtil.dip2px(context, 14.0) + for ((index, item) in labels.withIndex()) { + val imageView = ImageView(context) + val layoutParams = MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + if (index != 0) { + layoutParams.leftMargin = leftMargin + } + imageView.maxWidth = width + imageView.maxHeight = height + imageView.scaleType=ImageView.ScaleType.CENTER_INSIDE + imageView.layoutParams = layoutParams + addView(imageView) + ImageLoadUtilsV2.loadImage(imageView, item) + } + } + + override fun generateLayoutParams(lp: ViewGroup.LayoutParams?): LayoutParams { + if (lp is LayoutParams && Build.VERSION.SDK_INT >= 19) { + return LayoutParams(lp) + }else if (lp is ViewGroup.MarginLayoutParams) { + return LayoutParams(lp) + } + return super.generateLayoutParams(lp) + } +} \ No newline at end of file diff --git a/app/src/module_community/java/com/chwl/app/community/widget/TouchHideKeyboardView.java b/app/src/module_community/java/com/chwl/app/community/widget/TouchHideKeyboardView.java new file mode 100644 index 000000000..ce1a93411 --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/widget/TouchHideKeyboardView.java @@ -0,0 +1,36 @@ +package com.chwl.app.community.widget; + +import android.app.Activity; +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.chwl.library.utils.keyboard.KeyboardUtil; + +/** + * create by lvzebiao @2019/11/28 + */ +public class TouchHideKeyboardView extends ConstraintLayout { + + public TouchHideKeyboardView(Context context) { + super(context); + } + + public TouchHideKeyboardView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public TouchHideKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (getContext() instanceof Activity) { + KeyboardUtil.hideKeyboard((Activity) getContext()); + } + return super.dispatchTouchEvent(ev); + } +} diff --git a/app/src/module_community/java/com/chwl/app/community/widget/ZoomImageView.java b/app/src/module_community/java/com/chwl/app/community/widget/ZoomImageView.java new file mode 100644 index 000000000..40cbf8bca --- /dev/null +++ b/app/src/module_community/java/com/chwl/app/community/widget/ZoomImageView.java @@ -0,0 +1,476 @@ +package com.chwl.app.community.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.View; +import android.view.ViewTreeObserver; +import android.widget.ImageView; + +import com.netease.nim.uikit.common.util.log.LogUtil; + + +public class ZoomImageView extends ImageView implements ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener { + + private static final String TAG = ZoomImageView.class.getSimpleName(); + public static final float SCALE_MAX = 3.0f; + private static final float SCALE_MID = 1.5f; + + /** + * 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0 + */ + private float initScale = 1.0f; + private boolean once = true; + + /** + * 用于存放矩阵的9个值 + */ + private final float[] matrixValues = new float[9]; + + /** + * 缩放的手势检测 + */ + private ScaleGestureDetector mScaleGestureDetector = null; + private final Matrix mScaleMatrix = new Matrix(); + + /** + * 用于双击检测 + */ + private GestureDetector mGestureDetector; + private boolean isAutoScale; + + private int mTouchSlop; + + private float mLastX; + private float mLastY; + + private boolean isCanDrag; + private int lastPointerCount; + + private boolean isCheckTopAndBottom = true; + private boolean isCheckLeftAndRight = true; + private OnClickListener onClickListener; + private OnLongClickListener onLongClickListener; + + public ZoomImageView(Context context) { + this(context, null); + } + + public ZoomImageView(Context context, AttributeSet attrs) { + super(context, attrs); + super.setScaleType(ScaleType.MATRIX); + mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + if (onClickListener != null) { + onClickListener.onClick(ZoomImageView.this); + return true; + } + return super.onSingleTapConfirmed(e); + } + + @Override + public void onLongPress(MotionEvent e) { + if (onLongClickListener != null) { + onLongClickListener.onLongClick(ZoomImageView.this); + } + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + if (isAutoScale) + return true; + + float x = e.getX(); + float y = e.getY(); + LogUtil.print("DoubleTap, " + getScale() + " , " + initScale); + if (getScale() < SCALE_MID) { + //postDelayed(); 16 :多久实现一次的定时器操作 + ZoomImageView.this.postDelayed(new AutoScaleRunnable(SCALE_MID, x, y), 16); + isAutoScale = true; + } /*else if (getScale() >= SCALE_MID //连续双击放大 可放开 + && getScale() < SCALE_MAX) { + ZoomImageView.this.postDelayed(new AutoScaleRunnable(SCALE_MAX, x, y), 16); + isAutoScale = true; + }*/ else { + ZoomImageView.this.postDelayed(new AutoScaleRunnable(initScale, x, y), 16); + isAutoScale = true; + } + + return true; + } + }); + mScaleGestureDetector = new ScaleGestureDetector(context, this); + this.setOnTouchListener(this); + } + + /** + * 自动缩放的任务 + * + * @author zhy + */ + private class AutoScaleRunnable implements Runnable { + static final float BIGGER = 1.07f; + static final float SMALLER = 0.93f; + private float mTargetScale; + private float tmpScale; + + /** + * 缩放的中心 + */ + private float x; + private float y; + + /** + * 传入目标缩放值,根据目标值与当前值,判断应该放大还是缩小 + * + * @param targetScale + */ + public AutoScaleRunnable(float targetScale, float x, float y) { + this.mTargetScale = targetScale; + this.x = x; + this.y = y; + if (getScale() < mTargetScale) { + tmpScale = BIGGER; + } else { + tmpScale = SMALLER; + } + } + + @Override + public void run() { + // 进行缩放 + mScaleMatrix.postScale(tmpScale, tmpScale, x, y); + checkBorderAndCenterWhenScale(); + setImageMatrix(mScaleMatrix); + + final float currentScale = getScale(); + // 如果值在合法范围内,继续缩放 + if (((tmpScale > 1f) && (currentScale < mTargetScale)) || ((tmpScale < 1f) && (mTargetScale < currentScale))) { + + ZoomImageView.this.postDelayed(this, 16); + } else { + // 设置为目标的缩放比例 + final float deltaScale = mTargetScale / currentScale; + mScaleMatrix.postScale(deltaScale, deltaScale, x, y); + checkBorderAndCenterWhenScale(); + setImageMatrix(mScaleMatrix); + isAutoScale = false; + } + } + } + + /** + * 对图片进行缩放的控制,首先进行缩放范围的判断,然后设置mScaleMatrix的scale值 + * + * @param detector + * @return + */ + @SuppressLint("NewApi") + @Override + public boolean onScale(ScaleGestureDetector detector) { + float scale = getScale(); + float scaleFactor = detector.getScaleFactor(); + + if (getDrawable() == null) + return true; + + /** + * 缩放的范围控制 + */ + if ((scale < SCALE_MAX && scaleFactor > 1.0f) || (scale > initScale && scaleFactor < 1.0f)) { + /** + * 最大值最小值判断 + */ + if (scaleFactor * scale < initScale) { + scaleFactor = initScale / scale; + } + if (scaleFactor * scale > SCALE_MAX) { + scaleFactor = SCALE_MAX / scale; + } + /** + * 设置缩放比例 + */ + mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY()); + + checkBorderAndCenterWhenScale(); + setImageMatrix(mScaleMatrix); + } + return true; + } + + /** + * 在缩放时,进行图片显示范围的控制 + */ + private void checkBorderAndCenterWhenScale() { + + RectF rect = getMatrixRectF(); + float deltaX = 0; + float deltaY = 0; + + int width = getWidth(); + int height = getHeight(); + + // 如果宽或高大于屏幕,则控制范围 + if (rect.width() >= width) { + if (rect.left > 0) { + deltaX = -rect.left; + } + if (rect.right < width) { + deltaX = width - rect.right; + } + } + if (rect.height() >= height) { + if (rect.top > 0) { + deltaY = -rect.top; + } + if (rect.bottom < height) { + deltaY = height - rect.bottom; + } + } + // 如果宽或高小于屏幕,则让其居中 + if (rect.width() < width) { + deltaX = width * 0.5f - rect.right + 0.5f * rect.width(); + } + if (rect.height() < height) { + deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height(); + } + + + mScaleMatrix.postTranslate(deltaX, deltaY); + + } + + /** + * 根据当前图片的Matrix获得图片的范围 + * + * @return + */ + private RectF getMatrixRectF() { + Matrix matrix = mScaleMatrix; + RectF rect = new RectF(); + Drawable d = getDrawable(); + if (null != d) { + rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); + matrix.mapRect(rect); + } + return rect; + } + + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + return true; + } + + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + } + + /** + * 我们让OnTouchListener的MotionEvent交给ScaleGestureDetector进行处理 + * public boolean onTouch(View v, MotionEvent event){ + * return mScaleGestureDetector.onTouchEvent(event); + * } + */ + @Override + public boolean onTouch(View v, MotionEvent event) { + + if (mGestureDetector.onTouchEvent(event)) + return true; + mScaleGestureDetector.onTouchEvent(event); + + float x = 0, y = 0; + // 拿到触摸点的个数 + final int pointerCount = event.getPointerCount(); + // 得到多个触摸点的x与y均值 + for (int i = 0; i < pointerCount; i++) { + x += event.getX(i); + y += event.getY(i); + } + x = x / pointerCount; + y = y / pointerCount; + + /** + * 每当触摸点发生变化时,重置mLasX , mLastY + */ + if (pointerCount != lastPointerCount) { + isCanDrag = false; + mLastX = x; + mLastY = y; + } + + lastPointerCount = pointerCount; + RectF rectF = getMatrixRectF(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (rectF.width() > getWidth() || rectF.height() > getHeight()) { + getParent().requestDisallowInterceptTouchEvent(true); + } + break; + case MotionEvent.ACTION_MOVE: + if (rectF.width() > getWidth() || rectF.height() > getHeight()) { + getParent().requestDisallowInterceptTouchEvent(true); + } + + float dx = x - mLastX; + float dy = y - mLastY; + + if (!isCanDrag) { + isCanDrag = isCanDrag(dx, dy); + } + if (isCanDrag) { + + if (getDrawable() != null) { + // if (getMatrixRectF().left == 0 && dx > 0) + // { + // getParent().requestDisallowInterceptTouchEvent(false); + // } + // + // if (getMatrixRectF().right == getWidth() && dx < 0) + // { + // getParent().requestDisallowInterceptTouchEvent(false); + // } + isCheckLeftAndRight = isCheckTopAndBottom = true; + // 如果宽度小于屏幕宽度,则禁止左右移动 + if (rectF.width() < getWidth()) { + dx = 0; + isCheckLeftAndRight = false; + } + // 如果高度小雨屏幕高度,则禁止上下移动 + if (rectF.height() < getHeight()) { + dy = 0; + isCheckTopAndBottom = false; + } + + //设置偏移量 + mScaleMatrix.postTranslate(dx, dy); + //再次校验 + checkMatrixBounds(); + setImageMatrix(mScaleMatrix); + } + } + mLastX = x; + mLastY = y; + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + + lastPointerCount = 0; + break; + } + return true; + } + + /** + * 获得当前的缩放比例 + * + * @return + */ + public final float getScale() { + mScaleMatrix.getValues(matrixValues); + return matrixValues[Matrix.MSCALE_X]; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + getViewTreeObserver().addOnGlobalLayoutListener(this); + } + + @SuppressWarnings("deprecation") + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + + /** + * 根据图片的宽和高以及屏幕的宽和高,对图片进行缩放以及移动至屏幕的中心。 + * 如果图片很小,那就正常显示,不放大了~ + */ + @Override + public void onGlobalLayout() { + if (once) { + Drawable d = getDrawable(); + if (d == null) + return; + + int width = getWidth(); + int height = getHeight(); + // 拿到图片的宽和高 + int dw = d.getIntrinsicWidth(); + int dh = d.getIntrinsicHeight(); + float scale = 1.0f; + // 如果图片的宽或者高大于屏幕,则缩放至屏幕的宽或者高 + if (dw > width && dh <= height) { + scale = width * 1.0f / dw; + } + if (dh > height && dw <= width) { + scale = height * 1.0f / dh; + } + // 如果宽和高都大于屏幕,则让其按按比例适应屏幕大小 + if (dw > width && dh > height) { + scale = Math.min(width * 1.0f / dw, height * 1.0f / dh); + } + initScale = scale; + + mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2); + mScaleMatrix.postScale(scale, scale, getWidth() / 2, getHeight() / 2); + // 图片移动至屏幕中心 + setImageMatrix(mScaleMatrix); + once = false; + } + } + + /** + * 移动时,进行边界判断,主要判断宽或高大于屏幕的 + */ + private void checkMatrixBounds() { + RectF rect = getMatrixRectF(); + + float deltaX = 0, deltaY = 0; + final float viewWidth = getWidth(); + final float viewHeight = getHeight(); + // 判断移动或缩放后,图片显示是否超出屏幕边界 + if (rect.top > 0 && isCheckTopAndBottom) { + deltaY = -rect.top; + } + if (rect.bottom < viewHeight && isCheckTopAndBottom) { + deltaY = viewHeight - rect.bottom; + } + if (rect.left > 0 && isCheckLeftAndRight) { + deltaX = -rect.left; + } + if (rect.right < viewWidth && isCheckLeftAndRight) { + deltaX = viewWidth - rect.right; + } + mScaleMatrix.postTranslate(deltaX, deltaY); + } + + /** + * 是否是推动行为 + * + * @param dx + * @param dy + * @return + */ + private boolean isCanDrag(float dx, float dy) { + return Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop; + } + + public void setOnClickListener(OnClickListener onClickListener) { + this.onClickListener = onClickListener; + } + + public void setOnLongClickListener(OnLongClickListener onLongClickListener) { + this.onLongClickListener = onLongClickListener; + } +} diff --git a/app/src/module_community/res/drawable-xhdpi/bg_dy_popup_comment.png b/app/src/module_community/res/drawable-xhdpi/bg_dy_popup_comment.png new file mode 100644 index 000000000..96f394a08 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/bg_dy_popup_comment.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/bg_dy_popup_comment_three.png b/app/src/module_community/res/drawable-xhdpi/bg_dy_popup_comment_three.png new file mode 100644 index 000000000..b517938d9 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/bg_dy_popup_comment_three.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_back_dynamic.webp b/app/src/module_community/res/drawable-xhdpi/ic_back_dynamic.webp new file mode 100644 index 000000000..4b92b8b35 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_back_dynamic.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_box_dynamic.png b/app/src/module_community/res/drawable-xhdpi/ic_box_dynamic.png new file mode 100644 index 000000000..de1c33bad Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_box_dynamic.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_close_publish.png b/app/src/module_community/res/drawable-xhdpi/ic_close_publish.png new file mode 100644 index 000000000..3b7da1944 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_close_publish.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_communicate_community_list.png b/app/src/module_community/res/drawable-xhdpi/ic_communicate_community_list.png new file mode 100644 index 000000000..21cf88050 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_communicate_community_list.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_dy_square_in_room.webp b/app/src/module_community/res/drawable-xhdpi/ic_dy_square_in_room.webp new file mode 100644 index 000000000..80482d0c1 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_dy_square_in_room.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_female_age_community_notice.png b/app/src/module_community/res/drawable-xhdpi/ic_female_age_community_notice.png new file mode 100644 index 000000000..f6bb44d5b Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_female_age_community_notice.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_img_dynamic.png b/app/src/module_community/res/drawable-xhdpi/ic_img_dynamic.png new file mode 100644 index 000000000..5a1ad4096 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_img_dynamic.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_like_community_list.png b/app/src/module_community/res/drawable-xhdpi/ic_like_community_list.png new file mode 100644 index 000000000..70e759ca0 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_like_community_list.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_male_community_notice.png b/app/src/module_community/res/drawable-xhdpi/ic_male_community_notice.png new file mode 100644 index 000000000..8656a04cf Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_male_community_notice.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_more_community_list.png b/app/src/module_community/res/drawable-xhdpi/ic_more_community_list.png new file mode 100644 index 000000000..0fdfd0093 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_more_community_list.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_name_community_notice_list.png b/app/src/module_community/res/drawable-xhdpi/ic_name_community_notice_list.png new file mode 100644 index 000000000..83d70842c Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_name_community_notice_list.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_share_community_list.png b/app/src/module_community/res/drawable-xhdpi/ic_share_community_list.png new file mode 100644 index 000000000..b61233a31 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_share_community_list.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_square_live.png b/app/src/module_community/res/drawable-xhdpi/ic_square_live.png new file mode 100644 index 000000000..6cc68589b Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_square_live.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_square_publish.webp b/app/src/module_community/res/drawable-xhdpi/ic_square_publish.webp new file mode 100644 index 000000000..37f190964 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_square_publish.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_text_dynamic.png b/app/src/module_community/res/drawable-xhdpi/ic_text_dynamic.png new file mode 100644 index 000000000..6389e0335 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_text_dynamic.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_topic_close.png b/app/src/module_community/res/drawable-xhdpi/ic_topic_close.png new file mode 100644 index 000000000..825e49056 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_topic_close.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_translate_dynamic.png b/app/src/module_community/res/drawable-xhdpi/ic_translate_dynamic.png new file mode 100644 index 000000000..3ba63302a Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_translate_dynamic.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_translate_selected_dynamic.webp b/app/src/module_community/res/drawable-xhdpi/ic_translate_selected_dynamic.webp new file mode 100644 index 000000000..24b168315 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_translate_selected_dynamic.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_video_dynamic.png b/app/src/module_community/res/drawable-xhdpi/ic_video_dynamic.png new file mode 100644 index 000000000..a5bc7306b Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_video_dynamic.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/ic_voice_dynamic.png b/app/src/module_community/res/drawable-xhdpi/ic_voice_dynamic.png new file mode 100644 index 000000000..bca20e20a Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/ic_voice_dynamic.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_detail_comment.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_detail_comment.png new file mode 100644 index 000000000..bd09941b1 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_detail_comment.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_detail_share.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_detail_share.png new file mode 100644 index 000000000..5c15b6b55 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_detail_share.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_dynamic_publisher.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_dynamic_publisher.png new file mode 100644 index 000000000..49491e058 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_dynamic_publisher.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_emoji.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_emoji.png new file mode 100644 index 000000000..ff5c90c1f Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_emoji.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_first_dynamic.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_first_dynamic.png new file mode 100644 index 000000000..48c50bdb2 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_first_dynamic.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_item_more.webp b/app/src/module_community/res/drawable-xhdpi/icon_dy_item_more.webp new file mode 100644 index 000000000..cc950ad3f Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_item_more.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_comment.webp b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_comment.webp new file mode 100644 index 000000000..0f74d2b7d Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_comment.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_female.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_female.png new file mode 100644 index 000000000..235275bb4 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_female.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like.webp b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like.webp new file mode 100644 index 000000000..3e9df0182 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00000.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00000.png new file mode 100644 index 000000000..2c7a0559c Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00000.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00001.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00001.png new file mode 100644 index 000000000..a9c96ee38 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00001.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00002.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00002.png new file mode 100644 index 000000000..c6014dc7d Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00002.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00003.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00003.png new file mode 100644 index 000000000..95cc50924 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00003.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00004.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00004.png new file mode 100644 index 000000000..935b88743 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00004.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00005.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00005.png new file mode 100644 index 000000000..faae9e673 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00005.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00006.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00006.png new file mode 100644 index 000000000..6e28f3062 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00006.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00007.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00007.png new file mode 100644 index 000000000..a4956ba94 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00007.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00008.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00008.png new file mode 100644 index 000000000..3fd37d60c Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00008.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00009.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00009.png new file mode 100644 index 000000000..37389ff93 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00009.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00010.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00010.png new file mode 100644 index 000000000..00d484521 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00010.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00011.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00011.png new file mode 100644 index 000000000..47ea42305 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00011.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00012.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00012.png new file mode 100644 index 000000000..b7686370f Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00012.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00013.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00013.png new file mode 100644 index 000000000..2c7a0559c Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_00013.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_false.webp b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_false.webp new file mode 100644 index 000000000..5f6802834 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_false.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_true.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_true.png new file mode 100644 index 000000000..5881cc041 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_like_true.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_male.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_male.png new file mode 100644 index 000000000..82e6dd8b6 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_male.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_list_share.webp b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_share.webp new file mode 100644 index 000000000..6fbf2d0c3 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_list_share.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_miniworld.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_miniworld.png new file mode 100644 index 000000000..41316ad8e Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_miniworld.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_copy.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_copy.png new file mode 100644 index 000000000..d0321a5e7 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_copy.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_delete.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_delete.png new file mode 100644 index 000000000..e74532c11 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_delete.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_report.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_report.png new file mode 100644 index 000000000..4ad26c307 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_popup_report.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_examine.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_examine.png new file mode 100644 index 000000000..243d470a0 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_examine.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_false.png b/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_false.png new file mode 100644 index 000000000..356fec169 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_false.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_true.webp b/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_true.webp new file mode 100644 index 000000000..f5e1edd5c Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_dy_publish_true.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_comment.webp b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_comment.webp new file mode 100644 index 000000000..84cb5597d Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_comment.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_like_checked.webp b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_like_checked.webp new file mode 100644 index 000000000..32be4b625 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_like_checked.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_like_normal.webp b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_like_normal.webp new file mode 100644 index 000000000..ddf8316d5 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_like_normal.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_more.png b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_more.png new file mode 100644 index 000000000..0f65acbd5 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_more.png differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_share.webp b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_share.webp new file mode 100644 index 000000000..e75cf61ee Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_square_dynamic_share.webp differ diff --git a/app/src/module_community/res/drawable-xhdpi/icon_top.png b/app/src/module_community/res/drawable-xhdpi/icon_top.png new file mode 100644 index 000000000..46d1f4eb7 Binary files /dev/null and b/app/src/module_community/res/drawable-xhdpi/icon_top.png differ diff --git a/app/src/module_community/res/drawable/anim_list_dy_like.xml b/app/src/module_community/res/drawable/anim_list_dy_like.xml new file mode 100644 index 000000000..de7ec3e39 --- /dev/null +++ b/app/src/module_community/res/drawable/anim_list_dy_like.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/bg_round_1affbc51_9_4.xml b/app/src/module_community/res/drawable/bg_round_1affbc51_9_4.xml new file mode 100644 index 000000000..da38d7295 --- /dev/null +++ b/app/src/module_community/res/drawable/bg_round_1affbc51_9_4.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/btn_translate_dynamic_selector.xml b/app/src/module_community/res/drawable/btn_translate_dynamic_selector.xml new file mode 100644 index 000000000..d7ccf828a --- /dev/null +++ b/app/src/module_community/res/drawable/btn_translate_dynamic_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/divider_flexlayout.xml b/app/src/module_community/res/drawable/divider_flexlayout.xml new file mode 100644 index 000000000..ef1416188 --- /dev/null +++ b/app/src/module_community/res/drawable/divider_flexlayout.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/selector_dy_publish_btn_status.xml b/app/src/module_community/res/drawable/selector_dy_publish_btn_status.xml new file mode 100644 index 000000000..6dee3582d --- /dev/null +++ b/app/src/module_community/res/drawable/selector_dy_publish_btn_status.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/shape_bg_mini_world_added.xml b/app/src/module_community/res/drawable/shape_bg_mini_world_added.xml new file mode 100644 index 000000000..58591efa7 --- /dev/null +++ b/app/src/module_community/res/drawable/shape_bg_mini_world_added.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/shape_bg_mini_world_name.xml b/app/src/module_community/res/drawable/shape_bg_mini_world_name.xml new file mode 100644 index 000000000..dc4afa03e --- /dev/null +++ b/app/src/module_community/res/drawable/shape_bg_mini_world_name.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/shape_bg_square_list.xml b/app/src/module_community/res/drawable/shape_bg_square_list.xml new file mode 100644 index 000000000..5671ff429 --- /dev/null +++ b/app/src/module_community/res/drawable/shape_bg_square_list.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/shape_round.xml b/app/src/module_community/res/drawable/shape_round.xml new file mode 100644 index 000000000..44a080885 --- /dev/null +++ b/app/src/module_community/res/drawable/shape_round.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/module_community/res/drawable/topic_up_drawable.xml b/app/src/module_community/res/drawable/topic_up_drawable.xml new file mode 100644 index 000000000..25905721e --- /dev/null +++ b/app/src/module_community/res/drawable/topic_up_drawable.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/activity_dynamic_detail.xml b/app/src/module_community/res/layout/activity_dynamic_detail.xml new file mode 100644 index 000000000..9d4281a91 --- /dev/null +++ b/app/src/module_community/res/layout/activity_dynamic_detail.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/activity_publish.xml b/app/src/module_community/res/layout/activity_publish.xml new file mode 100644 index 000000000..50b03ada0 --- /dev/null +++ b/app/src/module_community/res/layout/activity_publish.xml @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/dialog_dy_publish_success.xml b/app/src/module_community/res/layout/dialog_dy_publish_success.xml new file mode 100644 index 000000000..6d1bbdd70 --- /dev/null +++ b/app/src/module_community/res/layout/dialog_dy_publish_success.xml @@ -0,0 +1,50 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/dy_empty_dynamic_comment.xml b/app/src/module_community/res/layout/dy_empty_dynamic_comment.xml new file mode 100644 index 000000000..0e15efa1d --- /dev/null +++ b/app/src/module_community/res/layout/dy_empty_dynamic_comment.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/dy_footer_loadmore.xml b/app/src/module_community/res/layout/dy_footer_loadmore.xml new file mode 100644 index 000000000..bc98eebb0 --- /dev/null +++ b/app/src/module_community/res/layout/dy_footer_loadmore.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/fragment_square.xml b/app/src/module_community/res/layout/fragment_square.xml new file mode 100644 index 000000000..4ecd096be --- /dev/null +++ b/app/src/module_community/res/layout/fragment_square.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/fragment_square_dynamic.xml b/app/src/module_community/res/layout/fragment_square_dynamic.xml new file mode 100644 index 000000000..ed55cf0a9 --- /dev/null +++ b/app/src/module_community/res/layout/fragment_square_dynamic.xml @@ -0,0 +1,27 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/frg_user_dynamic.xml b/app/src/module_community/res/layout/frg_user_dynamic.xml new file mode 100644 index 000000000..62c4e38ee --- /dev/null +++ b/app/src/module_community/res/layout/frg_user_dynamic.xml @@ -0,0 +1,23 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/frg_worlds_choose.xml b/app/src/module_community/res/layout/frg_worlds_choose.xml new file mode 100644 index 000000000..2b42dc392 --- /dev/null +++ b/app/src/module_community/res/layout/frg_worlds_choose.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/head_dynamic_detail.xml b/app/src/module_community/res/layout/head_dynamic_detail.xml new file mode 100644 index 000000000..cb3b94e71 --- /dev/null +++ b/app/src/module_community/res/layout/head_dynamic_detail.xml @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_dy_comment.xml b/app/src/module_community/res/layout/item_dy_comment.xml new file mode 100644 index 000000000..b72093265 --- /dev/null +++ b/app/src/module_community/res/layout/item_dy_comment.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_dy_reply.xml b/app/src/module_community/res/layout/item_dy_reply.xml new file mode 100644 index 000000000..7ea890f7e --- /dev/null +++ b/app/src/module_community/res/layout/item_dy_reply.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_dynamic_image.xml b/app/src/module_community/res/layout/item_dynamic_image.xml new file mode 100644 index 000000000..2fb7e88d8 --- /dev/null +++ b/app/src/module_community/res/layout/item_dynamic_image.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_dynamic_sys.xml b/app/src/module_community/res/layout/item_dynamic_sys.xml new file mode 100644 index 000000000..b6b7d91ab --- /dev/null +++ b/app/src/module_community/res/layout/item_dynamic_sys.xml @@ -0,0 +1,39 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_grid_image_widget.xml b/app/src/module_community/res/layout/item_grid_image_widget.xml new file mode 100644 index 000000000..01ded47fb --- /dev/null +++ b/app/src/module_community/res/layout/item_grid_image_widget.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_label_mini_world.xml b/app/src/module_community/res/layout/item_label_mini_world.xml new file mode 100644 index 000000000..170b8f33f --- /dev/null +++ b/app/src/module_community/res/layout/item_label_mini_world.xml @@ -0,0 +1,16 @@ + + + diff --git a/app/src/main/res/layout/item_publish_image.xml b/app/src/module_community/res/layout/item_publish_image.xml similarity index 100% rename from app/src/main/res/layout/item_publish_image.xml rename to app/src/module_community/res/layout/item_publish_image.xml diff --git a/app/src/module_community/res/layout/item_reply_footer_view.xml b/app/src/module_community/res/layout/item_reply_footer_view.xml new file mode 100644 index 000000000..c5586316a --- /dev/null +++ b/app/src/module_community/res/layout/item_reply_footer_view.xml @@ -0,0 +1,10 @@ + + diff --git a/app/src/module_community/res/layout/item_square_dynamic.xml b/app/src/module_community/res/layout/item_square_dynamic.xml new file mode 100644 index 000000000..8b520eeb0 --- /dev/null +++ b/app/src/module_community/res/layout/item_square_dynamic.xml @@ -0,0 +1,274 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_user_dynamic_image.xml b/app/src/module_community/res/layout/item_user_dynamic_image.xml new file mode 100644 index 000000000..00b96779b --- /dev/null +++ b/app/src/module_community/res/layout/item_user_dynamic_image.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/app/src/module_community/res/layout/item_user_dynamic_list.xml b/app/src/module_community/res/layout/item_user_dynamic_list.xml new file mode 100644 index 000000000..4f5b40292 --- /dev/null +++ b/app/src/module_community/res/layout/item_user_dynamic_list.xml @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_world_dynamic.xml b/app/src/module_community/res/layout/item_world_dynamic.xml new file mode 100644 index 000000000..a15145ce9 --- /dev/null +++ b/app/src/module_community/res/layout/item_world_dynamic.xml @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/item_worlds_choose.xml b/app/src/module_community/res/layout/item_worlds_choose.xml new file mode 100644 index 000000000..a3e73742b --- /dev/null +++ b/app/src/module_community/res/layout/item_worlds_choose.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/layout_dy_nick_detail.xml b/app/src/module_community/res/layout/layout_dy_nick_detail.xml new file mode 100644 index 000000000..2e711be81 --- /dev/null +++ b/app/src/module_community/res/layout/layout_dy_nick_detail.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/popup_dy_comment.xml b/app/src/module_community/res/layout/popup_dy_comment.xml new file mode 100644 index 000000000..633e06c99 --- /dev/null +++ b/app/src/module_community/res/layout/popup_dy_comment.xml @@ -0,0 +1,51 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/view_holder_world_dynamic_share.xml b/app/src/module_community/res/layout/view_holder_world_dynamic_share.xml new file mode 100644 index 000000000..767baafe6 --- /dev/null +++ b/app/src/module_community/res/layout/view_holder_world_dynamic_share.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/layout/widget_grid_image.xml b/app/src/module_community/res/layout/widget_grid_image.xml new file mode 100644 index 000000000..eb49035d7 --- /dev/null +++ b/app/src/module_community/res/layout/widget_grid_image.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/values-ar/strings.xml b/app/src/module_community/res/values-ar/strings.xml new file mode 100644 index 000000000..6b16ca61f --- /dev/null +++ b/app/src/module_community/res/values-ar/strings.xml @@ -0,0 +1,20 @@ + + + نشر الرسومات والنصوص + نشر + سجل حياتك في الوقت الحالي وشاركها مع الأشخاص المثيرين للاهتمام + نشر التعليقات + تكبير + غلق + يُمنع الإعلانات التجارية وأرقام الهواتف والألفاظ البذيئة والإباحية والمخيفة والعنيفة والمهينة، وسيتم حظر حساباتهم! + %s رد + تعال واحصل على مقعدك + قم بتكبير %sالردود + تعليق + ترشيح + متابعة + الأحدث + الساحة + اذهب والقى نظرة + + \ No newline at end of file diff --git a/app/src/module_community/res/values-zh-rTW/strings.xml b/app/src/module_community/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..e639d258c --- /dev/null +++ b/app/src/module_community/res/values-zh-rTW/strings.xml @@ -0,0 +1,19 @@ + + + 圖文發佈 + 發布 + 記錄你此刻生活,分享給有趣的人看... + 發表評論 + 展開 + 收起 + 禁止出現商業廣告、電話號碼, 以及低俗、色情、恐怖、暴力和具有侮辱性語言等內容,違規者封號處理 ! + 回復 %s + 快來搶占沙發吧~ + 展開%s條回復 + 評論 + 推薦 + 關註 + 最新 + 廣場 + 去看看 + \ No newline at end of file diff --git a/app/src/module_community/res/values/attrs.xml b/app/src/module_community/res/values/attrs.xml new file mode 100644 index 000000000..cc7f0fd93 --- /dev/null +++ b/app/src/module_community/res/values/attrs.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_community/res/values/dimens.xml b/app/src/module_community/res/values/dimens.xml new file mode 100644 index 000000000..56a345bd6 --- /dev/null +++ b/app/src/module_community/res/values/dimens.xml @@ -0,0 +1,9 @@ + + + + 51.5dp + 70dp + 2.5dp + 7dp + + \ No newline at end of file diff --git a/app/src/module_community/res/values/strings.xml b/app/src/module_community/res/values/strings.xml new file mode 100644 index 000000000..49393faf2 --- /dev/null +++ b/app/src/module_community/res/values/strings.xml @@ -0,0 +1,19 @@ + + + Post graphics and text + Post + Record your life at this moment and share it with interesting people... + Comment + Expand + Close + Commercial advertisements, phone numbers, and content that is vulgar, pornographic, terrifying, violent, and insulting are prohibited. Violators will be blocked! + Reply %s + Come and have your seat + Expand %s replies + Comment + Recommend + Follow + Newest + Square + Go to see + \ No newline at end of file diff --git a/core/src/main/java/com/chwl/core/XConstants.java b/core/src/main/java/com/chwl/core/XConstants.java index 27fbcc9d6..577f8ae3b 100644 --- a/core/src/main/java/com/chwl/core/XConstants.java +++ b/core/src/main/java/com/chwl/core/XConstants.java @@ -61,7 +61,10 @@ public class XConstants { public static final String REPORT_TYPE_ROOM = "room"; // 房間 public static final String REPORT_TYPE_VOICE = "voice"; // 聲音瓶子 public static final String REPORT_TYPE_USERCARD = "USERCARD"; // 資料卡片 - + public static final String REPORT_TYPE_WORLDDYNAMIC = "WORLDDYNAMIC"; // 世界動態 + public static final String REPORT_TYPE_DYNAMICCOMMENT = "DYNAMICCOMMENT"; // 世界動態 + public static final String REPORT_TYPE_PERSONAL_DYNAMIC = "PERSONAL_DYNAMIC"; // 個人頁動態 + public static final String REPORT_TYPE_DYNAMIC_SQUARE = "DYNAMIC_SQUARE";//廣場動態 /** * Referer (DEBUG) */ diff --git a/core/src/main/java/com/chwl/core/home/bean/MainTabType.java b/core/src/main/java/com/chwl/core/home/bean/MainTabType.java index bb13e4ff5..6bd2a4a01 100644 --- a/core/src/main/java/com/chwl/core/home/bean/MainTabType.java +++ b/core/src/main/java/com/chwl/core/home/bean/MainTabType.java @@ -1,10 +1,11 @@ package com.chwl.core.home.bean; public interface MainTabType { - //tabType(1-派对,2-广场,3-赛事,4-消息,5-我的) - int TAB_TYPE_STAR = 1; - int TAB_TYPE_HOME = 2; - int TAB_TYPE_MSG = 3; - int TAB_TYPE_ME = 4; - int TAB_TYPE_GAME = 5; + // int TAB_TYPE_STAR = 1; + int TAB_TYPE_HOME = 1; + int TAB_TYPE_GAME = 2; + int TAB_TYPE_SQUARE = 3; + int TAB_TYPE_MSG = 4; + int TAB_TYPE_ME = 5; + } diff --git a/core/src/main/java/com/chwl/core/initial/InitialModel.java b/core/src/main/java/com/chwl/core/initial/InitialModel.java index 9ab1cb4ab..223a87c15 100644 --- a/core/src/main/java/com/chwl/core/initial/InitialModel.java +++ b/core/src/main/java/com/chwl/core/initial/InitialModel.java @@ -395,8 +395,8 @@ public class InitialModel extends BaseModel implements IInitialModel { new MainTabInfo( "", "", - "Star", - MainTabType.TAB_TYPE_STAR, + ResUtil.getString(R.string.xchat_android_core_initial_initialmodel_03), + MainTabType.TAB_TYPE_HOME, null ), new MainTabInfo( @@ -409,8 +409,8 @@ public class InitialModel extends BaseModel implements IInitialModel { new MainTabInfo( "", "", - ResUtil.getString(R.string.xchat_android_core_initial_initialmodel_03), - MainTabType.TAB_TYPE_HOME, + "Square", + MainTabType.TAB_TYPE_SQUARE, null ), new MainTabInfo( diff --git a/core/src/main/java/com/chwl/core/user/bean/BaseUserInfo.java b/core/src/main/java/com/chwl/core/user/bean/BaseUserInfo.java index fc27c375f..84fba2176 100644 --- a/core/src/main/java/com/chwl/core/user/bean/BaseUserInfo.java +++ b/core/src/main/java/com/chwl/core/user/bean/BaseUserInfo.java @@ -47,6 +47,7 @@ public class BaseUserInfo implements Serializable { // 铭牌文字 private String nameplateWord; + private boolean isCustomWord; // 在哪个房间id private Long inRoomUid; diff --git a/core/src/model_community/java/com/chwl/core/community/attachment/DynamicSysAttachment.java b/core/src/model_community/java/com/chwl/core/community/attachment/DynamicSysAttachment.java index 1aa98c68b..81f39b5e0 100644 --- a/core/src/model_community/java/com/chwl/core/community/attachment/DynamicSysAttachment.java +++ b/core/src/model_community/java/com/chwl/core/community/attachment/DynamicSysAttachment.java @@ -1,10 +1,13 @@ package com.chwl.core.community.attachment; +import androidx.annotation.Keep; + import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; import com.chwl.core.im.custom.bean.CustomAttachment; import com.chwl.core.msg.sys.bean.ErbanSysMsgInfo; +@Keep public class DynamicSysAttachment extends CustomAttachment { private ErbanSysMsgInfo erbanSysMsgInfo; diff --git a/core/src/model_community/java/com/chwl/core/community/attachment/UnReadCountAttachment.java b/core/src/model_community/java/com/chwl/core/community/attachment/UnReadCountAttachment.java index 3bc008efa..6feead31e 100644 --- a/core/src/model_community/java/com/chwl/core/community/attachment/UnReadCountAttachment.java +++ b/core/src/model_community/java/com/chwl/core/community/attachment/UnReadCountAttachment.java @@ -1,8 +1,11 @@ package com.chwl.core.community.attachment; +import androidx.annotation.Keep; + import com.alibaba.fastjson.JSONObject; import com.chwl.core.im.custom.bean.CustomAttachment; +@Keep public class UnReadCountAttachment extends CustomAttachment { private int total; diff --git a/core/src/model_community/java/com/chwl/core/community/im/DynamicImMsg.java b/core/src/model_community/java/com/chwl/core/community/im/DynamicImMsg.java index ffbc83872..6d211c0d6 100644 --- a/core/src/model_community/java/com/chwl/core/community/im/DynamicImMsg.java +++ b/core/src/model_community/java/com/chwl/core/community/im/DynamicImMsg.java @@ -1,5 +1,7 @@ package com.chwl.core.community.im; +import androidx.annotation.Keep; + import com.chwl.core.community.bean.WorldDynamicBean; import java.io.Serializable; @@ -10,6 +12,7 @@ import lombok.Data; * create by lvzebiao @2019/11/22 */ @Data +@Keep public class DynamicImMsg implements Serializable { private long dynamicId; diff --git a/core/src/model_community/java/com/chwl/core/community/im/WorldDynamicAttachment.java b/core/src/model_community/java/com/chwl/core/community/im/WorldDynamicAttachment.java index 46b885e58..adf6fe958 100644 --- a/core/src/model_community/java/com/chwl/core/community/im/WorldDynamicAttachment.java +++ b/core/src/model_community/java/com/chwl/core/community/im/WorldDynamicAttachment.java @@ -1,5 +1,7 @@ package com.chwl.core.community.im; +import androidx.annotation.Keep; + import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.netease.nimlib.sdk.msg.MessageBuilder; @@ -13,6 +15,7 @@ import lombok.Setter; /** * create by lvzebiao @2019/11/22 */ +@Keep public class WorldDynamicAttachment extends CustomAttachment { @Setter diff --git a/library/src/main/java/com/chwl/library/utils/TimeUtils.java b/library/src/main/java/com/chwl/library/utils/TimeUtils.java index a973e4c7b..cf81d12f3 100644 --- a/library/src/main/java/com/chwl/library/utils/TimeUtils.java +++ b/library/src/main/java/com/chwl/library/utils/TimeUtils.java @@ -196,6 +196,7 @@ public class TimeUtils { return null; } final Calendar cal = Calendar.getInstance(); + cal.setTimeZone(TimeZone.getTimeZone("GMT+8")); cal.setTimeInMillis(timeMillis); int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH) + 1; @@ -205,7 +206,7 @@ public class TimeUtils { int sec = cal.get(Calendar.SECOND); String timeString = null; try { - timeString = String.format(format, year, month, day, hour, min, sec); + timeString = String.format(Locale.ENGLISH, format, year, month, day, hour, min, sec); } catch (IllegalFormatException e) { MLog.error("TimeUtils", "getTimeStringFromMillis error! " + e.toString()); } diff --git a/app/src/main/java/com/chwl/app/common/photo/PhotoProvider.kt b/library/src/module_common/java/com/chwl/library/common/photo/PhotoProvider.kt similarity index 87% rename from app/src/main/java/com/chwl/app/common/photo/PhotoProvider.kt rename to library/src/module_common/java/com/chwl/library/common/photo/PhotoProvider.kt index ce52cea6d..ebb2afa6b 100644 --- a/app/src/main/java/com/chwl/app/common/photo/PhotoProvider.kt +++ b/library/src/module_common/java/com/chwl/library/common/photo/PhotoProvider.kt @@ -11,14 +11,20 @@ import com.chwl.library.common.application.BaseApp import com.chwl.library.common.delegate.SpDelegate import com.chwl.library.common.file.FileHelper import com.chwl.library.common.glide.GlideEngine -import com.chwl.library.common.util.LibLogger import com.chwl.library.easyphoto.EasyPhotos import com.chwl.library.easyphoto.models.album.entity.Photo import com.chwl.library.utils.TimeUtils import com.chwl.library.utils.TimeUtils.TIME_FORMAT +import com.example.lib_utils.log.LogUtil import kotlinx.coroutines.* import java.io.File +/** + * Created by wushaocheng on 2022/11/15 + * Desc:图片选择二次封装 + */ + + /** * Created by wushaocheng on 2022/11/15 * Desc:图片选择二次封装 @@ -58,11 +64,11 @@ object PhotoProvider { withContext(Dispatchers.IO) { clearCache() } } EasyPhotos.createAlbum(activity, false, false, GlideEngine()) - .setCount(maxSelect)//参数说明:最大可选数,默认1 - .setPuzzleMenu(false) - .onlyVideo() - .setCleanMenu(false) - .start(resultCode) + .setCount(maxSelect)//参数说明:最大可选数,默认1 + .setPuzzleMenu(false) + .onlyVideo() + .setCleanMenu(false) + .start(resultCode) } } @@ -85,13 +91,25 @@ object PhotoProvider { @JvmStatic @JvmOverloads - fun photoProvider(activity: FragmentActivity, maxSelect: Int = 1, canChooseGif: Boolean = false, resultCode: Int, isClearCache: Boolean = true) { + fun photoProvider( + activity: FragmentActivity, + maxSelect: Int = 1, + canChooseGif: Boolean = false, + resultCode: Int, + isClearCache: Boolean = true, + useWidth: Boolean = false + ) { cancelJop() mPhotoJob = MainScope().launch { if (isClearCache && isClearByTime()) { withContext(Dispatchers.IO) { clearCache() } } - EasyPhotos.createAlbum(activity, false, false, GlideEngine())//参数说明:上下文,是否显示相机按钮,是否使用宽高数据(false时宽高数据为0,扫描速度更快),[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93) + EasyPhotos.createAlbum( + activity, + false, + useWidth, + GlideEngine() + )//参数说明:上下文,是否显示相机按钮,是否使用宽高数据(false时宽高数据为0,扫描速度更快),[配置Glide为图片加载引擎](https://github.com/HuanTanSheng/EasyPhotos/wiki/12-%E9%85%8D%E7%BD%AEImageEngine%EF%BC%8C%E6%94%AF%E6%8C%81%E6%89%80%E6%9C%89%E5%9B%BE%E7%89%87%E5%8A%A0%E8%BD%BD%E5%BA%93) .setCount(maxSelect)//参数说明:最大可选数,默认1 .setGif(canChooseGif) .setPuzzleMenu(false) @@ -158,7 +176,7 @@ object PhotoProvider { val path = "$foldPath${it.name}" if (FileHelper.copyFileFromUri(it.uri, path, true)) { it.path = path - LibLogger.debug(TAG, "path: ${it.path} , displayName: ${it.name} , newPath: $path ") + LogUtil.d(TAG, "path: ${it.path} , displayName: ${it.name} , newPath: $path ") } } } @@ -172,7 +190,7 @@ object PhotoProvider { * 清除复制缓存 */ fun clearCache() { - LibLogger.debug( + LogUtil.d( TAG, "clearCache => mLastSelectTime: ${TimeUtils.getDateTimeString( mLastSelectTime, TIME_FORMAT)}") FileHelper.removeAllFile(getInternalPath() + File.separator)