/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2015 Umeng, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.umeng.comm.ui.fragments;
import java.util.List;
import android.annotation.TargetApi;
import android.os.Build;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ListView;
import android.widget.TextView;
import com.umeng.comm.core.beans.CommConfig;
import com.umeng.comm.core.beans.CommUser;
import com.umeng.comm.core.beans.Comment;
import com.umeng.comm.core.beans.FeedItem;
import com.umeng.comm.core.constants.Constants;
import com.umeng.comm.core.constants.HttpProtocol;
import com.umeng.comm.core.listeners.Listeners;
import com.umeng.comm.core.listeners.Listeners.LoginOnViewClickListener;
import com.umeng.comm.core.listeners.Listeners.OnItemViewClickListener;
import com.umeng.comm.core.utils.ResFinder;
import com.umeng.comm.core.utils.ResFinder.ResType;
import com.umeng.comm.core.utils.ToastMsg;
import com.umeng.comm.ui.adapters.FeedCommentAdapter;
import com.umeng.comm.ui.adapters.viewholders.FavouriteFeedItemViewHolder;
import com.umeng.comm.ui.mvpview.MvpCommentView;
import com.umeng.comm.ui.mvpview.MvpFeedDetailView;
import com.umeng.comm.ui.mvpview.MvpLikeView;
import com.umeng.comm.ui.presenter.impl.FeedDetailPresenter;
import com.umeng.comm.ui.utils.BroadcastUtils;
import com.umeng.comm.ui.utils.BroadcastUtils.BROADCAST_TYPE;
import com.umeng.comm.ui.utils.BroadcastUtils.DefalutReceiver;
import com.umeng.comm.ui.utils.ViewFinder;
import com.umeng.comm.ui.widgets.LikeView;
import com.umeng.comm.ui.widgets.RefreshLayout.OnLoadListener;
import com.umeng.comm.ui.widgets.RefreshLvLayout;
/**
* 该类是某条Feed的详情页面,使用FeedItemViewParser解析单项的Feed数据.Feed相关的信息显示在评论列表的Header中,
* 该页面会展示该条Feed的Like用户以及评论。
*/
public class FeedDetailFragment extends CommentEditFragment<List<FeedItem>, FeedDetailPresenter>
implements MvpCommentView, MvpLikeView, MvpFeedDetailView {
/**
* 点击评论某项时的回调。用于在评论的EditView中显示回复XXX
*/
private OnItemViewClickListener<String> mCommentClickListener;
/**
* 点击的评论的item view
*/
protected View mClickItemView;
/**
* 当前点击的消息流的某一项
*/
protected int mCurFeedItemIndex = 0;
/**
* 弹出评论EditVIew时,某项feed的滚动距离
*/
protected int mScrollDis = 0;
FavouriteFeedItemViewHolder mFeedViewHolder;
// 由于开发者可能直接使用Fragment,在退出登录的时候,我们需要回到该Activity
protected String mContainerClass = null;
TextView mLikeTextView;
// 赞的用户列表
LikeView mLikeView;
// 评论数量
TextView mCommentCountTextView;
// 转发数量
TextView mForwardCountTextView;
/**
* 页面下部的Like、评论、转发三个视图的根布局
*/
View mActionsLayout;
/**
* LIKE视图布局
*/
View mLikeActionLayout;
/**
* LIKE视图
*/
TextView mLikeActionView;
/**
* 转发视图
*/
View mForwardActionLayout;
/**
* 评论视图
*/
View mCommentActionLayout;
/**
* 下拉刷新布局,评论ListView的parent
*/
RefreshLvLayout mRefreshLayout;
/**
* 评论ListView
*/
private ListView mCommentListView;
/**
* 评论ListView Adapter
*/
FeedCommentAdapter mCommentAdapter;
/**
* 创建一个FeedDetailFragment对象,在feedDetailActivity使用
*
* @param feedItem
* @return
*/
public static FeedDetailFragment newFeedDetailFragment(FeedItem feedItem) {
FeedDetailFragment fragment = new FeedDetailFragment();
fragment.mFeedItem = feedItem;
return fragment;
}
@Override
protected int getFragmentLayout() {
return ResFinder.getLayout("umeng_comm_feed_detail_fragment");
}
@Override
protected FeedDetailPresenter createPresenters() {
super.createPresenters();
return new FeedDetailPresenter(this, this, this, mFeedItem);
}
@Override
protected void initWidgets() {
super.initWidgets();
View headerView = initFeedContentView();
initRefreshLayout(headerView);
initActionsView();
BroadcastUtils.registerFeedBroadcast(getActivity(), mReceiver);
}
@Override
protected void setupOthers() {
mContainerClass = getActivity().getClass().getName();
// 填充数据
setFeedItemData(mFeedItem);
}
public void updateFeedItem(FeedItem feedItem) {
if (mFeedItem != null && feedItem != null) {
mFeedItem.text = feedItem.text;
mFeedItem.publishTime = feedItem.publishTime;
mFeedItem.likeCount = feedItem.likeCount;
mFeedItem.commentCount = feedItem.commentCount;
mFeedItem.forwardCount = feedItem.forwardCount;
mFeedItem.imageUrls = feedItem.imageUrls ;
mFeedItem.category = feedItem.category;
} else {
mFeedItem = feedItem;
}
setFeedItemData(mFeedItem);
}
@Override
public void onStart() {
super.onStart();
boolean isScroll = getArguments().getBoolean(Constants.TAG_IS_SCROLL, false);
if (!isScroll) {
return;
}
mCommentCountTextView.postDelayed(new Runnable() {
@Override
public void run() {
executeScroll();
}
}, 300);
}
/**
* 执行滚动操作</br>
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void executeScroll() {
int scrollDis = mCommentCountTextView.getHeight() - mCommentCountTextView.getPaddingTop()
+ 26;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mCommentListView.smoothScrollToPositionFromTop(1, scrollDis);
} else {
mCommentListView.smoothScrollToPosition(1);
}
}
/**
* 加载Feed详情页面的Feed视图,该视图添加到评论列表的Header中
*
* @return
*/
private View initFeedContentView() {
ViewFinder headerViewFinder = new ViewFinder(getActivity(),
ResFinder.getLayout("umeng_comm_feed_detail_header"));
// 显示Feed的Header View
View headerView = headerViewFinder.findViewById(ResFinder
.getId("umeng_comm_feed_content_layout"));
// 构造FeedItemViewHolder用于对Feed进行控制
mFeedViewHolder = new FavouriteFeedItemViewHolder(getActivity(), headerView);
mFeedViewHolder.setShowFavouriteView(true);
mFeedViewHolder.setContainerClass(mContainerClass);
mFeedViewHolder.hideActionButtons();
mFeedViewHolder.setShareActivity(getActivity());
mFeedViewHolder.setFeedItem(mFeedItem);
// Like数量TextView
mLikeTextView = headerViewFinder.findViewById(ResFinder.getId("umeng_comm_like_count_tv"));
mLikeView = headerViewFinder.findViewById(ResFinder
.getId("umeng_comm_like_users_layout"));
mCommentCountTextView = headerViewFinder.findViewById(ResFinder
.getId("umeng_comm_comment_count_tv"));
mForwardCountTextView = headerViewFinder.findViewById(ResFinder
.getId("umeng_comm_forward_count_tv"));
return headerViewFinder.getRootView();
}
private void initRefreshLayout(View headerView) {
mRefreshLayout = mViewFinder.findViewById(ResFinder
.getId("umeng_comm_feed_refresh_layout"));
mRefreshLayout.setRefreshing(false);
mRefreshLayout.setEnabled(false);
// 添加footer
if (mFeedItem.commentCount > Constants.COUNT) {
mRefreshLayout.setDefaultFooterView();
}
mRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
mRefreshLayout.setRefreshing(false);
}
});
mRefreshLayout.setOnLoadListener(new OnLoadListener() {
@Override
public void onLoad() {
mPresenter.loadMoreComments();
}
});
headerView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mCommentLayout.getVisibility() == View.VISIBLE) {
hideCommentLayout();
return true;
}
return false;
}
});
mCommentListView = mViewFinder.findViewById(ResFinder.getId("umeng_comm_comments_list"));
mCommentListView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mCommentLayout.getVisibility() == View.VISIBLE) {
hideCommentLayout();
return true;
}
return false;
}
});
mCommentListView.setOnItemClickListener(new Listeners.OnItemClickLoginListener() {
@Override
protected void doAfterLogin(View v, int position) {
if (position == 0) {
return;
}
final int realPosition = position - 1;
replayComment(realPosition);
}
});
// 添加header
mCommentListView.addHeaderView(headerView);
}
private void replayComment(int position) {
Comment comment = mCommentAdapter.getItem(position);
mCommentPresenter.clickCommentItem(position, comment);
}
private void showCommentLayoutWitdCommentId() {
// 从消息通知的评论页面进来该页面时需要弹出评论框
if (mFeedItem.extraData.containsKey(HttpProtocol.COMMENT_ID_KEY)) {
String commentId = mFeedItem.extraData.getString(HttpProtocol.COMMENT_ID_KEY);
if (TextUtils.isEmpty(commentId)) {
return;
}
int position = getCommentPosition(commentId);
if (position >= 0) {
mFeedItem.extraData.remove(HttpProtocol.COMMENT_ID_KEY);
final Comment item = mCommentAdapter.getItem(position);
if (item.creator.id.equals(CommConfig.getConfig().loginedUser.id)) {
ToastMsg.showShortMsgByResName("umeng_comm_do_not_reply_yourself");
} else {
showCommentLayout(position, item);
}
}
}
}
private int getCommentPosition(String commentId) {
List<Comment> feedComments = mFeedItem.comments;
for (int i = 0; i < feedComments.size(); i++) {
final Comment item = feedComments.get(i);
if (commentId.equals(item.id)) {
return i;
}
}
return -1;
}
private void initActionsView() {
mActionsLayout = mViewFinder.findViewById(ResFinder.getId("umeng_comm_action_layout"));
// 操作区域
mLikeActionLayout = mViewFinder.findViewById(ResFinder.getId("umeng_comm_like_layout"));
mLikeActionLayout.setOnClickListener(new LoginOnViewClickListener() {
@Override
protected void doAfterLogin(View v) {
mPresenter.setFeedItem(mFeedItem);
if (mFeedItem.isLiked) {
mPresenter.postUnlike(mFeedItem.id);
} else {
mPresenter.postLike(mFeedItem.id);
}
}
});
// 赞的TextView
mLikeActionView = mViewFinder.findViewById(ResFinder.getId("umeng_comm_like_action_tv"));
setupLikeView(mFeedItem.isLiked);
mForwardActionLayout = mViewFinder.findViewById(ResFinder
.getId("umeng_comm_forward_layout"));
mForwardActionLayout.setOnClickListener(new LoginOnViewClickListener() {
@Override
protected void doAfterLogin(View v) {
mPresenter.gotoForwardActivity(mFeedItem);
}
});
mCommentActionLayout = mViewFinder.findViewById(ResFinder
.getId("umeng_comm_comment_layout"));
mCommentActionLayout.setOnClickListener(new LoginOnViewClickListener() {
@Override
protected void doAfterLogin(View v) {
showCommentLayout();
}
});
}
private void setupLikeView(boolean isLiked) {
if (isLiked) {
mLikeActionView.setCompoundDrawablesWithIntrinsicBounds(
ResFinder.getResourceId(ResType.DRAWABLE, "umeng_comm_like_pressed"), 0, 0, 0);
mLikeActionView.setText(ResFinder.getString("umeng_comm_unlike"));
} else {
mLikeActionView.setCompoundDrawablesWithIntrinsicBounds(
ResFinder.getResourceId(ResType.DRAWABLE, "umeng_comm_like_normal"), 0, 0, 0);
mLikeActionView.setText(ResFinder.getString("umeng_comm_like"));
}
}
@Override
protected void postComment(String text) {
mPresenter.postComment(text, mReplyUser, mReplyCommentId);
}
@Override
public void showCommentLayout(int realPosition, Comment comment) {
String hintString = getReplyPrefix(comment.creator);
mReplyUser = comment.creator;
mReplyCommentId = comment.id;
mCommentEditText.setHint(hintString);
mCommentListView.smoothScrollToPosition(realPosition);
showCommentLayout();
}
protected void showCommentLayout() {
super.showCommentLayout();
mActionsLayout.setVisibility(View.GONE);
}
protected void hideCommentLayout() {
super.hideCommentLayout();
mActionsLayout.setVisibility(View.VISIBLE);
}
private void initLikeUserLayout(String nextUrl) {
if (mFeedItem.likes.size() > 0) {
mLikeView.setVisibility(View.VISIBLE);
mLikeView.addLikeUsers(mFeedItem, nextUrl);
setLikeCount(mFeedItem.likes.size());
} else {
mLikeView.setVisibility(View.GONE);
}
}
/**
* 填充消息流ListView每项的数据
*
* @param viewHolder
* @param item
*/
private void setFeedItemData(final FeedItem feedItem) {
if (TextUtils.isEmpty(feedItem.id)) {
return;
}
// 设置Feed Content View
mFeedViewHolder.setFeedItem(feedItem);
setLikeCount(feedItem.likeCount);
setCommentCount(feedItem.commentCount);
setForwardCount(feedItem.forwardCount);
// 初始化评论列表
initCommentListView(feedItem);
}
private void setCommentCount(int count) {
mCommentCountTextView.setText(String.format("评论(%d)", count));
}
private void setLikeCount(int count) {
if (mFeedItem.likeCount < 0) {
mFeedItem.likeCount = 0;
}
mLikeTextView.setText("" + mFeedItem.likeCount);
}
private void setForwardCount(int count) {
mForwardCountTextView.setText(String.format("转发(%d)", count));
}
private void initCommentListView(FeedItem item) {
mCommentAdapter = new FeedCommentAdapter(getActivity());
mCommentAdapter.addDatasOnly(item.comments);
mCommentListView.setAdapter(mCommentAdapter);
}
/*
* 显示输入评论内容的布局
*/
protected void showCommentLayout(int pos, boolean fromClickBtn) {
if (mCommentClickListener != null) {
mCommentClickListener.onItemClick(0, "");
}
}
/**
* 获取显示在EditText中显示的评论文本。不如:回复XXX</br>
*
* @return
*/
private String getReplyPrefix(CommUser replyUser) {
if (replyUser == null) {
return "";
}
String replyText = ResFinder.getString("umeng_comm_reply");
String colon = ResFinder.getString("umeng_comm_colon");
return replyText + replyUser.name + colon;
}
@Override
public void postCommentSuccess(Comment comment, CommUser replyUser) {
mReplyCommentId = "";
mReplyUser = null;
if (mCommentAdapter == null) {
return;
}
comment.replyUser = replyUser;
mCommentAdapter.addToFirst(comment);
setCommentCount(mFeedItem.commentCount);
mCommentEditText.setText("");
mCommentEditText.setHint("");
}
@Override
public void loadMoreComment(List<Comment> comments) {
mRefreshLayout.setLoading(false);
comments.removeAll(mCommentAdapter.getDataSource());
mCommentAdapter.addData(comments);
// 存储数据
mFeedItem.comments.addAll(comments);
}
@Override
public void onRefreshEnd() {
mRefreshLayout.setLoading(false);
mRefreshLayout.setRefreshing(false);
}
public void fetchLikesComplete(String nexturl) {
// 赞的用户列表
initLikeUserLayout(nexturl);
}
@Override
public void fetchCommentsComplete() {
mCommentAdapter.updateListViewData(mFeedItem.comments);
}
@Override
public void like(boolean isLiked) {
setupLikeView(isLiked);
}
@Override
public void updateLikeView(String nextUrl) {
initLikeUserLayout(nextUrl);
setLikeCount(mFeedItem.likeCount);
}
@Override
public void updateCommentView() {
mCommentAdapter.updateListViewData(mFeedItem.comments);
showCommentLayoutWitdCommentId();
}
@Override
public void onCommentDeleted(Comment comment) {
mCommentAdapter.removeItem(comment);
setCommentCount(mFeedItem.commentCount);
BroadcastUtils.sendFeedUpdateBroadcast(getActivity(), mFeedItem);
}
@Override
public void onDestroy() {
BroadcastUtils.unRegisterBroadcast(getActivity(), mReceiver);
super.onDestroy();
}
private DefalutReceiver mReceiver = new DefalutReceiver() {
public void onReceiveFeed(android.content.Intent intent) {
FeedItem feedItem = getFeed(intent);
if (feedItem == null) {
return;
}
BROADCAST_TYPE type = getType(intent);
if (BROADCAST_TYPE.TYPE_FEED_POST == type) {
updateForwarCount(feedItem, 1);
} else if (BROADCAST_TYPE.TYPE_FEED_DELETE == type) {
updateForwarCount(feedItem, -1);
}
}
};
private void updateForwarCount(FeedItem item, int count) {
if (TextUtils.isEmpty(item.sourceFeedId)) {
return;
}
mFeedItem.forwardCount = mFeedItem.forwardCount + count;
setForwardCount(mFeedItem.forwardCount);
}
@Override
public void onRefreshStart() {
}
}