项目地址.
我们这一篇主要是完成添加评论和删除评论,我们先看下效果
我们首先看下添加评论,点击输入布局底部弹出一个对话框
它有4部分组成:1.可以使一张图片或者一个视频;2.输入框;3.拍摄视频;4.发送按钮
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:animateLayoutChanges="false"
android:background="@color/color_white"
android:orientation="vertical">
<FrameLayout
android:id="@+id/comment_ext_layout"
android:layout_width="@dimen/dp_60"
android:layout_height="@dimen/dp_60"
android:layout_marginLeft="@dimen/dimen_10"
android:layout_marginTop="@dimen/dp_5"
android:layout_marginBottom="@dimen/dp_5"
android:visibility="gone"
tools:visibility="visible">
<com.mooc.ppjoke.view.PPImageView
android:id="@+id/comment_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop">com.mooc.ppjoke.view.PPImageView>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/comment_icon_video"
android:layout_width="@dimen/dimen_20"
android:layout_height="@dimen/dimen_20"
android:layout_gravity="center"
android:src="@drawable/icon_video_play"
android:visibility="gone">androidx.appcompat.widget.AppCompatImageView>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/comment_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|top"
android:paddingLeft="@dimen/dp_3"
app:srcCompat="@drawable/icon_close"
app:tint="@color/color_white">androidx.appcompat.widget.AppCompatImageView>
FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/color_gray2">View>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_45"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="@dimen/dimen_10"
android:paddingRight="@dimen/dimen_10">
<com.mooc.libcommon.view.PPEditTextView
android:id="@+id/input_view"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_weight="1"
android:background="@drawable/bg_edit_view"
android:gravity="center_vertical"
android:hint="@string/comment_hint"
android:paddingLeft="@dimen/sp_10"
android:textColor="@color/color_333"
android:textColorHint="@color/color_999"
android:textSize="@dimen/sp_12">com.mooc.libcommon.view.PPEditTextView>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/comment_video"
android:layout_width="@dimen/dp_36"
android:layout_height="@dimen/dp_36"
android:layout_marginLeft="@dimen/dp_5"
android:src="@drawable/icon_publish_video">androidx.appcompat.widget.AppCompatImageView>
<com.google.android.material.button.MaterialButton
android:id="@+id/comment_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dimen_10"
android:gravity="center"
android:paddingLeft="@dimen/dp_11"
android:paddingTop="@dimen/dp_3"
android:paddingRight="@dimen/dp_11"
android:paddingBottom="@dimen/dp_3"
android:text="@string/comment_send_text"
android:textColorHint="@color/color_white"
app:backgroundTint="@color/color_theme"
app:cornerRadius="@dimen/dp_6">com.google.android.material.button.MaterialButton>
LinearLayout>
LinearLayout>
layout>
我们这个底部对话框使用DialogFragment
实现
public class CommentDialog extends AppCompatDialogFragment
添加评论肯定需要整条帖子的id
,所以需要给我们的CommentDialog
传一个值
public static CommentDialog newInstance(long itemId) {
Bundle args = new Bundle();
args.putLong(KEY_ITEM_ID, itemId);
CommentDialog fragment = new CommentDialog();
fragment.setArguments(args);
return fragment;
}
拍摄视频我们下一篇再说,我们这一篇主要就是添加和删除评论,我们为这个发送写一个点击事件
mBinding.commentSend.setOnClickListener(this);
@Override
public void onClick(View v) {
if (v.getId() == R.id.comment_send) {
publishComment();
}
}
private void publishComment() {
if (TextUtils.isEmpty(mBinding.inputView.getText())) {
return;
}
String commentText = mBinding.inputView.getText().toString();
ApiService.post("/comment/addComment")
.addParam("userId", UserManager.get().getUserId())
.addParam("itemId", itemId)
.addParam("commentText", commentText)
.addParam("image_url", isVideo ? coverUrl : fileUrl)
.addParam("video_url", isVideo ? fileUrl : null)
.addParam("width", width)
.addParam("height", height)
.execute(new JsonCallback<Comment>() {
@Override
public void onSuccess(ApiResponse<Comment> response) {
onCommentSuccess(response.body);
dismissLoadingDialog();
}
@Override
public void onError(ApiResponse<Comment> response) {
showToast("评论失败:" + response.message);
dismissLoadingDialog();
}
});
}
private void onCommentSuccess(Comment body) {
showToast("评论发布成功");
ArchTaskExecutor.getMainThreadExecutor().execute(() -> {
if (mListener != null) {
mListener.onAddComment(body);
}
dismiss();
});
}
我们评论评论成功之后需要把值回调给外面,所以这里写了一个接口
private OnCommentAddListener mListener;
public interface OnCommentAddListener {
void onAddComment(Comment comment);
}
public void setCommentAddListener(OnCommentAddListener listener) {
mListener = listener;
}
Ok,接着我们在需要弹出这个对话框的地方补上我们的点击事件,在我们的ViewHandler
这个类中添加对输入View
的点击事件
mInateractionBinding.inputView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showCommentDialog();
}
});
private void showCommentDialog() {
if (commentDialog == null) {
commentDialog = CommentDialog.newInstance(mFeed.itemId);
}
commentDialog.setCommentAddListener(comment -> {
handleEmpty(true);
listAdapter.addAndRefreshList(comment);
});
commentDialog.show(mActivity.getSupportFragmentManager(), "comment_dialog");
}
我们主要是看下handleEmpty
和addAndRefreshList
这两个方法
handleEmpty
是我们在没有评论的时候需要展示空布局,有数据时不展示这个空布局
public void handleEmpty(boolean hasData) {
if (hasData) {
if (mEmptyView != null) {
listAdapter.removeHeaderView(mEmptyView);
}
} else {
if (mEmptyView == null) {
mEmptyView = new EmptyView(mActivity);
RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.topMargin = PixUtils.dp2px(40);
mEmptyView.setLayoutParams(layoutParams);
mEmptyView.setTitle(mActivity.getString(R.string.feed_comment_empty));
}
listAdapter.addHeaderView(mEmptyView);
}
}
主要是这个addAndRefreshList
方法,我们每次添加完一条评论,这条评论就会在最上面,同时我们这个评论是可以上拉加载的,我们在首页帖子列表那里处理过上拉加载和下拉刷新,思路和那个差不多,就是上拉的时候,我们重新构建PageList
,然后调用submitList
方法刷新数据.
public void addAndRefreshList(Comment comment) {
PagedList<Comment> currentList = getCurrentList();
MutableItemKeyedDataSource<Integer, Comment> mutableItemKeyedDataSource = new MutableItemKeyedDataSource<Integer, Comment>((ItemKeyedDataSource) currentList.getDataSource()) {
@NonNull
@Override
public Integer getKey(@NonNull Comment item) {
return item.id;
}
};
mutableItemKeyedDataSource.data.add(comment);
mutableItemKeyedDataSource.data.addAll(currentList);
PagedList<Comment> pagedList = mutableItemKeyedDataSource.buildNewPagedList(currentList.getConfig());
submitList(pagedList);
}
这样基本上添加评论就写完了,然后我们就开始写删除评论,这个稍微简单点,就是调用相应接口就行
//删除某个帖子的一个评论
public static LiveData<Boolean> deleteFeedComment(Context context, long itemId, long commentId) {
MutableLiveData<Boolean> liveData = new MutableLiveData<>();
new AlertDialog.Builder(context)
.setNegativeButton("删除", (dialog, which) -> {
dialog.dismiss();
deleteFeedCommentInternal(liveData, itemId, commentId);
}).setPositiveButton("取消", (dialog, which) -> dialog.dismiss()).setMessage("确定要删除这条评论吗?").create().show();
return liveData;
}
private static void deleteFeedCommentInternal(LiveData liveData, long itemId, long commentId) {
ApiService.get("/comment/deleteComment")
.addParam("userId", UserManager.get().getUserId())
.addParam("commentId", commentId)
.addParam("itemId", itemId)
.execute(new JsonCallback<JSONObject>() {
@Override
public void onSuccess(ApiResponse<JSONObject> response) {
if (response.body != null) {
boolean result = response.body.getBooleanValue("result");
((MutableLiveData) liveData).postValue(result);
showToast("评论删除成功");
}
}
@Override
public void onError(ApiResponse<JSONObject> response) {
showToast(response.message);
}
});
}
这个点击事件在FeedCommentAdapter
中,只有自己的评论我们才能删除
holder.mBinding.commentDelete.setOnClickListener(v ->
InteractionPresenter.deleteFeedComment(mContext, item.itemId, item.commentId)
.observe((LifecycleOwner) mContext, success -> {
if (success) {
deleteAndRefreshList(item);
}
}));
public void deleteAndRefreshList(Comment item) {
MutableItemKeyedDataSource<Integer, Comment> dataSource = new MutableItemKeyedDataSource<Integer, Comment>((ItemKeyedDataSource) getCurrentList().getDataSource()) {
@NonNull
@Override
public Integer getKey(@NonNull Comment item) {
return item.id;
}
};
PagedList<Comment> currentList = getCurrentList();
for (Comment comment : currentList) {
if (comment != item) {
dataSource.data.add(comment);
}
}
PagedList<Comment> pagedList = dataSource.buildNewPagedList(getCurrentList().getConfig());
submitList(pagedList);
}
删除成功之后,和添加正好相反,我们需要把我们的这条评论从列表中删除