feat : app/src/module_community

This commit is contained in:
eggmanQQQ2
2025-07-07 10:36:32 +08:00
parent 490cce1256
commit 7f1dc54d7f
136 changed files with 8199 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -0,0 +1,166 @@
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.ImageLoadUtils;
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<Comment, BaseViewHolder> {
public CommentAdapter() {
super(R.layout.item_dy_comment);
}
@Override
protected void convert(BaseViewHolder helper, Comment item) {
ImageLoadUtils.loadAvatar( item.getAvatar(),helper.getView(R.id.iv_avatar));
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<Comment> 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<Comment> 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<Comment> list = getData();
if (pos >= 0 && pos < list.size()) {
list.remove(pos);
notifyDataSetChanged();
}
}
}

View File

@@ -0,0 +1,75 @@
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.ImageLoadUtils;
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<Reply, BaseViewHolder> {
private boolean hasExpandFooter;
public CommentReplyAdapter(boolean hasExpandFooter) {
super(R.layout.item_dy_reply);
this.hasExpandFooter = hasExpandFooter;
}
@Override
protected void convert(BaseViewHolder helper, Reply item) {
ImageLoadUtils.loadAvatar(item.getAvatar(),helper.getView(R.id.iv_avatar));
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);
}
}
}
}

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,134 @@
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.fastjson2.JSON;
import com.chwl.core.msg.sys.bean.ErbanSysMsgComponent;
import com.chwl.core.msg.sys.bean.ErbanSysMsgInfo;
import com.chwl.library.utils.json.JsonUtils;
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<ErbanSysMsgComponent> 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)));
}
}
}

View File

@@ -0,0 +1,104 @@
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.chwl.app.ui.utils.ImageLoadUtils;
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();
ImageLoadUtils.loadAvatar(dynamicImMsg.getImageUrl(),rivCover);
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();
}
}
}

View File

@@ -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<PublishItem, BaseViewHolder> {
public ImageAdapter(int layoutResId, @Nullable List<PublishItem> 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);
}
}

View File

@@ -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<IPublishView> {
private PublishBody publishBody;
private Disposable mImageUploadSubscribe;
private boolean isOriginalImage;
private MiniWorldChooseInfo miniWorldChooseInfo = new MiniWorldChooseInfo();
public void publishDy(List<DynamicMedia> list, long worldId, String content, boolean isOriginalImage) {
publishBody = new PublishBody();
List<DynamicMedia> 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<String, SingleSource<String>>) s ->
PublishModel.get().publish(publishBody))
.subscribe(new DontWarnObserver<String>() {
@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<String> uploadImage(List<DynamicMedia> 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<DynamicMedia> imagePaths) {
if (imagePaths == null || imagePaths.size() == 0) {
return;
}
DynamicMedia item = imagePaths.get(0);
String file = item.getLocalFilePath();
Single.create((SingleOnSubscribe<String>) 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<String, SingleSource<String>>)
path -> FileModel.get().uploadFile(path))
.compose(bindUntilEvent(PresenterEvent.DESTROY))
.subscribe(new DontWarnObserver<String>() {
@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<List<MiniWorldChooseInfo>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(List<MiniWorldChooseInfo> 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();
}
}

View File

@@ -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<IWorldsChooseView> {
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<List<MiniWorldChooseInfo>>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(List<MiniWorldChooseInfo> 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;
}
}

View File

@@ -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<MiniWorldChooseInfo> list);
void recommendWorldsFails(String error);
}

View File

@@ -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<MiniWorldChooseInfo> list);
void squareWorldsFails(String error);
}

View File

@@ -0,0 +1,568 @@
package com.chwl.app.community.publish.view;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
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.R;
import com.chwl.app.base.BaseMvpActivity;
import com.chwl.app.base.PhotoPickActivity;
import com.chwl.app.common.widget.dialog.DialogManager;
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.photo.BigPhotoActivity;
import com.chwl.app.photo.PagerOption;
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.CoreTextUtils;
import com.chwl.core.utils.myutil.MyUriUtils;
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.util.PhotoCompressUtil;
import com.chwl.library.common.util.PhotosCompressCallback;
import com.chwl.library.utils.ResUtil;
import com.chwl.library.utils.SingleToastUtil;
import com.example.matisse.internal.entity.CustomItem;
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 java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import kotlinx.coroutines.Job;
/**
* create by lvzebiao @2019/11/11
*/
@CreatePresenter(PublishPresenter.class)
public class PublishActivity extends BaseMvpActivity<IPublishView, PublishPresenter>
implements IPublishView, WorldsChooseFrg.ChooseWorldCallback,
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<PublishItem> imageShowList = new ArrayList<>();
private List<CustomItem> 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<CustomItem>) 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<PublishItem> 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
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<Long>() {
@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<MiniWorldChooseInfo> 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<MiniWorldChooseInfo> miniWorldChooseInfoList;
private void addMiniWorldList(List<MiniWorldChooseInfo> 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);
}
private void checkStoragePermission() {
PhotoPickActivity.start(this, PhotoPickActivity.IMG);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case PhotoPickActivity.PICK_ACT_RESULT:
if (data == null) {
return;
}
Uri uri = data.getData();
if (uri != null && uri.getPath() != null) {
if (MyUriUtils.INSTANCE.isGif(context, uri)) {
ToastUtils.show(R.string.error_file_type);
return;
}
File file = MyUriUtils.INSTANCE.copyFile(PublishActivity.this, uri);
if (file != null) {
LogUtil.e("选择 file = " + file.getName());
LogUtil.e("选择 file = " + file.getPath());
if (mJob != null) {
mJob.cancel(null);
}
ArrayList<String> pathList = new ArrayList<>();
pathList.add(file.getPath());
mJob = PhotoCompressUtil.compress(PublishActivity.this, pathList,
PhotoCompressUtil.getCompressCachePath("publish")
, new PhotosCompressCallback() {
@Override
public void onSuccess(@NonNull ArrayList<String> compressedImgList) {
List<CustomItem> pathResult = new ArrayList<>();
for (int i = 0; i < compressedImgList.size(); i++) {
if (i < pathList.size()) {
List<String> fileInfo = MyUriUtils.INSTANCE.getFileInfo(file);
if (fileInfo != null) {
pathResult.add(new CustomItem(compressedImgList.get(i), CustomItem.IMAGE_NORMAL, fileInfo.get(2), Integer.parseInt(fileInfo.get(0)), Integer.parseInt(fileInfo.get(1))));
}
}
}
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);
} else {
ToastUtils.show(R.string.exception_try_again);
}
}
break;
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mJob != null) {
mJob.cancel(null);
}
}
}

View File

@@ -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<MiniWorldChooseInfo, BaseViewHolder> {
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);
}
}

View File

@@ -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<IWorldsChooseView, WorldChoosePresenter> 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<MiniWorldChooseInfo> 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<MiniWorldChooseInfo> 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);
}
}

View File

@@ -0,0 +1,318 @@
package com.chwl.app.community.square;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.chwl.app.base.BaseFragment;
import com.chwl.library.widget.SVGAView;
import com.chwl.core.XConstants;
import com.trello.rxlifecycle3.android.FragmentEvent;
import com.chwl.app.R;
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;
private SVGAView.SVGACache svgaCache;
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(), svgaCache);
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<ButtonItem> 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<String>() {
@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);
}
public void setSvgaCache(SVGAView.SVGACache svgaCache) {
this.svgaCache = svgaCache;
}
private void loadData(boolean isRefresh) {
if (isRefresh) {
nextDynamicId = null;
page = 1;
} else {
page++;
}
Single<WorldDynamicListResult> 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<WorldDynamicListResult>() {
@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<WorldDynamicBean> 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<String>() {
@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() {
}
}

View File

@@ -0,0 +1,205 @@
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.app.utils.HomeUIManager;
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 com.chwl.library.language.LanguageHelper;
import com.chwl.library.widget.SVGAView;
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 = 1;
/**
* 推荐
*/
public static final int TAB_TYPE_RECOMMEND = 0;
/**
* 最新
*/
public static final int TAB_TYPE_NEW = 2;
private MagicIndicator magicIndicator;
private ViewPager2 viewPager;
private DragLayout ivSquarePublish;
private FrameLayout flContactList;
private View tvCommunityUnread;
private SVGAView.SVGACache svgaCache = SVGAView.newCache(10);
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() {
HomeUIManager.INSTANCE.setHomeUI(mView);
List<Integer> fragmentPos = new ArrayList<>();
fragmentPos.add(TAB_TYPE_RECOMMEND);
fragmentPos.add(TAB_TYPE_ATTENT);
fragmentPos.add(TAB_TYPE_NEW);
List<String> tagList = new ArrayList<>();
List<Fragment> 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));
}
SquareDynamicFragment fragment = SquareDynamicFragment.newInstance(integer);
fragment.setSvgaCache(svgaCache);
fragmentList.add(fragment);
}
getUnReadCount();
//init viewpager
viewPager.setAdapter(new CommonVPAdapter(getChildFragmentManager(), getLifecycle(), fragmentList));
viewPager.setOffscreenPageLimit(3);
viewPager.setUserInputEnabled(false);
CommonNavigator commonNavigator = new CommonNavigator(getContext());
if (LanguageHelper.INSTANCE.getCurrentLanguageType().equals("EN")) {
commonNavigator.setLeftPadding(40);
}
ContactsIndicatorAdapter magicIndicatorAdapter = new ContactsIndicatorAdapter(getContext(), tagList);
magicIndicatorAdapter.setOnItemSelectListener(this);
commonNavigator.setTitleWrapContent(false);
commonNavigator.setAdapter(magicIndicatorAdapter);
magicIndicator.setNavigator(commonNavigator);
commonNavigator.getTitleContainer().setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING);
//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);
svgaCache.clear();
}
}

View File

@@ -0,0 +1,265 @@
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.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.chwl.app.ui.utils.ImageLoadUtils;
import com.chwl.app.utils.AvatarHelper;
import com.chwl.library.widget.SVGAView;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nim.uikit.support.glide.GlideApp;
import com.chwl.app.R;
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<WorldDynamicBean, BaseViewHolder> {
private SparseBooleanArray mCollapsedStatus = new SparseBooleanArray();
private SparseIntArray mCollapsedHeightStatus = new SparseIntArray(2);
private Context context;
private SVGAView.SVGACache svgaCache;
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, SVGAView.SVGACache svgaCache) {
super(R.layout.item_square_dynamic);
this.context = context;
this.svgaCache = svgaCache;
iconWidth = UIUtil.dip2px(context, 32);
iconHeight = UIUtil.dip2px(context, 15);
imageTmHasText = UIUtil.dip2px(context, 12f);
imageTmNoText = UIUtil.dip2px(context, 7.5f);
//0.68
int screenWidth = UIUtil.getScreenWidth(context);
dividerDp = 9;
rvWidth = screenWidth - UIUtil.dip2px(context, 86);
}
@Override
protected BaseViewHolder onCreateDefViewHolder(ViewGroup parent, int viewType) {
BaseViewHolder holder = super.onCreateDefViewHolder(parent, viewType);
SVGAView ivHeadWear = holder.getView(R.id.iv_head_wear);
ivHeadWear.bindCache(svgaCache);
return holder;
}
@Override
protected void convert(BaseViewHolder helper, WorldDynamicBean item) {
//这个值有没有文本UI部分改变图片部分的margin
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);
//头饰 贵族头饰
SVGAView ivHeadWear = helper.getView(R.id.iv_head_wear);
GlideApp.with(ivHeadWear.getContext()).clear(ivHeadWear);
String headwearEffect = item.getHeadwearEffect();
String headwearPic = item.getHeadwearPic();
int headwearType = item.getHeadwearType();
String micDecorate = item.getMicDecorate();
if (TextUtils.isEmpty(headwearEffect) && TextUtils.isEmpty(headwearPic) && TextUtils.isEmpty(micDecorate)) {
ivHeadWear.setVisibility(View.GONE);
} else {
ivHeadWear.setVisibility(View.VISIBLE);
}
if (!TextUtils.isEmpty(headwearEffect)) {
AvatarHelper.loadAvatarFrame(ivHeadWear, headwearEffect, headwearType);
} else if (!TextUtils.isEmpty(headwearPic)) {
AvatarHelper.loadAvatarFrame(ivHeadWear, headwearPic, headwearType);
} else if (!TextUtils.isEmpty(micDecorate)) {
NobleUtil.loadResource(micDecorate, ivHeadWear);
} else {
ivHeadWear.setImageDrawable(null);
}
//头像
ImageLoadUtils.loadAvatar( item.getAvatar() ,helper.getView(R.id.iv_avatar));
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<String> 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<String>() {
@Override
public void accept(String s, String error) {
super.accept(s, error);
llLike.setEnabled(true);
if (error != null) {
SingleToastUtil.showToast(error);
} else {
LogUtil.print(ResUtil.getString(R.string.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);
}
}

View File

@@ -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<WorldDynamicBean> list);
void refreshFail(String error);
void loadSuccess(List<WorldDynamicBean> list);
void loadFail(String error);
void deleteSuccess(long successId);
void deleteFail(String error);
}

View File

@@ -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<UserDynamicItem, BaseViewHolder> {
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<UserDynamicItem> 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<String>() {
@Override
public void accept(String s, String error) {
super.accept(s, error);
llLike.setEnabled(true);
if (error != null) {
SingleToastUtil.showToast(error);
} else {
LogUtil.print(ResUtil.getString(R.string.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<DynamicMedia> 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);
}
}
}

View File

@@ -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<IUserDynamicView, UserDynamicPresenter> 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<UserDynamicItem> 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<WorldDynamicBean> list) {
swipeRefreshLayout.setRefreshing(false);
if (mUserDynamicAdapter != null) {
// mUserDynamicAdapter.resetStatus();
List<UserDynamicItem> tempList = getMvpPresenter().modifyData(list, true);
mUserDynamicAdapter.setNewData(tempList);
mUserDynamicAdapter.loadMoreComplete();
}
}
@Override
public void refreshFail(String error) {
swipeRefreshLayout.setRefreshing(false);
List<UserDynamicItem> 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<WorldDynamicBean> list) {
mUserDynamicAdapter.loadMoreComplete();
if (mUserDynamicAdapter != null) {
List<UserDynamicItem> 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<UserDynamicItem> 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<ButtonItem> 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<ButtonItem> 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());
}
}
});
}
}

View File

@@ -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<IUserDynamicView> {
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<List<WorldDynamicBean>, Throwable>() {
@Override
public void accept(List<WorldDynamicBean> 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<List<WorldDynamicBean>, Throwable>() {
@Override
public void accept(List<WorldDynamicBean> 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<UserDynamicItem> modifyData(List<WorldDynamicBean> list, boolean isFirst) {
List<UserDynamicItem> 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<String, Throwable>() {
@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;
}
}

View File

@@ -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<String> customToStringList(List<CustomItem> paramsList) {
List<String> resultList = new ArrayList<>();
if (paramsList == null) {
return resultList;
}
for (CustomItem item : paramsList) {
resultList.add(item.getPath());
}
return resultList;
}
public static List<DynamicMedia> customToMediaList(List<CustomItem> paramsList) {
List<DynamicMedia> 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<CustomItem> stringToCustomList(List<String> paramsList) {
List<CustomItem> resultList = new ArrayList<>();
if (paramsList == null) {
return resultList;
}
for (String item : paramsList) {
resultList.add(new CustomItem(item, 0));
}
return resultList;
}
public static ArrayList<CustomItem> mediaToCustomList(List<DynamicMedia> paramsList) {
ArrayList<CustomItem> 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<CustomItem> pathToCustomItems(String path) {
ArrayList<CustomItem> resultList = new ArrayList<>();
CustomItem item = new CustomItem();
item.setPath(path);
item.setFileType(CustomItem.UNKOWN);
resultList.add(item);
return resultList;
}
}

View File

@@ -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
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}
}

View File

@@ -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<DynamicMedia> dynamicMediaList = item.getDynamicResList();
if (item.getType() == WorldDynamicBean.TYPE_IMAGE
&& dynamicMediaList != null && dynamicMediaList.size() > 0) {
setData(dynamicMediaList, topMargin);
}
}
public void setData(List<DynamicMedia> 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);
}
}

View File

@@ -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<String>) {
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)
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item
android:drawable="@drawable/icon_dy_list_like_00000"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00001"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00002"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00003"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00004"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00005"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00006"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00007"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00008"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00009"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00010"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00011"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00012"
android:duration="@integer/dy_like_anim_duration" />
<item
android:drawable="@drawable/icon_dy_list_like_00013"
android:duration="@integer/dy_like_anim_duration" />
</animation-list>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1AFFBC51" />
<corners
android:bottomLeftRadius="@dimen/dp_9"
android:bottomRightRadius="@dimen/dp_9"
android:topLeftRadius="@dimen/dp_9"
android:topRightRadius="@dimen/dp_4" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_translate_dynamic" android:state_selected="true" />
<item android:drawable="@drawable/ic_translate_selected_dynamic" />
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:width="10dp"
android:height="10dp"/>
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_dy_publish_false" android:state_enabled="false" />
<item android:drawable="@drawable/icon_dy_publish_true" android:state_enabled="true" />
</selector>

Some files were not shown because too many files have changed in this diff Show More