/* * 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.adapters.viewholders; import java.util.Date; import java.util.List; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewStub; import android.view.animation.ScaleAnimation; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.umeng.comm.core.beans.CommUser; import com.umeng.comm.core.beans.FeedItem; import com.umeng.comm.core.beans.ImageItem; import com.umeng.comm.core.beans.ShareContent; import com.umeng.comm.core.constants.Constants; import com.umeng.comm.core.db.ctrl.impl.DatabaseAPI; import com.umeng.comm.core.imageloader.ImgDisplayOption; 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.listeners.Listeners.OnResultListener; import com.umeng.comm.core.sdkmanager.ShareSDKManager; import com.umeng.comm.core.utils.ResFinder; import com.umeng.comm.core.utils.ResFinder.ResType; import com.umeng.comm.core.utils.TimeUtils; import com.umeng.comm.ui.activities.LocationFeedActivity; import com.umeng.comm.ui.adapters.FeedImageAdapter; import com.umeng.comm.ui.emoji.EmojiTextView; import com.umeng.comm.ui.mvpview.MvpLikeView; import com.umeng.comm.ui.presenter.impl.FeedContentPresenter; import com.umeng.comm.ui.presenter.impl.LikePresenter; import com.umeng.comm.ui.utils.FeedViewRender; import com.umeng.comm.ui.utils.ViewFinder; import com.umeng.comm.ui.widgets.NetworkImageView; import com.umeng.comm.ui.widgets.RoundImageView; import com.umeng.comm.ui.widgets.WrapperGridView; /** * ListView的Feed Item View解析器. ( 将试图的显示和解析解耦, 便于测试, 也便于复用. ) */ public class FeedItemViewHolder extends ViewHolder implements MvpLikeView { private static final String M = "m"; public ImageView mFeedTypeImgView; public RoundImageView mProfileImgView; public TextView mShareBtn; public TextView mUserNameTv; public EmojiTextView mFeedTextTv; public ImageView mLocationImgView; public TextView mLocationTv; public RelativeLayout mForwardLayout; public TextView mForwardTextTv; public ViewStub mImageGvViewStub; public WrapperGridView mImageGv; public LinearLayout mButtomLayout; public TextView mTimeTv; public TextView mLikeCountTextView; public TextView mForwardCountTextView; public TextView mCommentCountTextView; public TextView mDistanceTextView; protected FeedItem mFeedItem; FeedContentPresenter mPresenter; LikePresenter mLikePresenter; private String mContainerClzName; private boolean mIsShowDistance = false; OnItemViewClickListener<FeedItem> mItemViewClickListener; public FeedItemViewHolder() { } public FeedItemViewHolder(Context context, View rootView) { mContext = context; itemView = rootView; mViewFinder = new ViewFinder(rootView); initWidgets(); } @Override protected int getItemLayout() { return ResFinder.getLayout("umeng_comm_feed_lv_item"); } @Override protected void initWidgets() { inflateFromXML(); initEventHandle(); initPresenters(); } protected void initPresenters() { mPresenter = new FeedContentPresenter(); mPresenter.attach(mContext); mLikePresenter = new LikePresenter(this); mLikePresenter.attach(mContext); mLikePresenter.setFeedItem(mFeedItem); } public void setContainerClass(String clz) { mContainerClzName = clz; } private void setupImageGridView() { if (mFeedItem.getImages() != null && mFeedItem.getImages().size() > 0) { showImageGridView(); } else { hideImageGridView(); } } public void showImageGridView() { // 显示转发的布局 mForwardLayout.setVisibility(View.VISIBLE); if (mImageGvViewStub.getVisibility() == View.GONE) { mImageGvViewStub.setVisibility(View.VISIBLE); int imageGvResId = ResFinder.getId("umeng_comm_msg_gridview"); mImageGv = (WrapperGridView) findViewById(imageGvResId); mImageGv.hasScrollBar = true; } mImageGv.setBackgroundColor(Color.TRANSPARENT); mImageGv.setVisibility(View.VISIBLE); // adapter FeedImageAdapter gridviewAdapter = new FeedImageAdapter(mContext); gridviewAdapter.addDatasOnly(mFeedItem.getImages()); // 设置图片 mImageGv.setAdapter(gridviewAdapter); // 计算列数 mImageGv.updateColumns(3); // 图片GridView mImageGv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int pos, long id) { mPresenter.jumpToImageBrowser(mFeedItem.getImages(), pos); } }); } private void hideImageGridView() { if (mImageGv != null) { mImageGv.setAdapter(new FeedImageAdapter(mContext)); mImageGv.setVisibility(View.GONE); } } protected void inflateFromXML() { int feedTypeResId = ResFinder.getId("feed_type_img_btn"); int userIconResId = ResFinder.getId("user_portrait_img_btn"); int userNameResId = ResFinder.getId("umeng_comm_msg_user_name"); int textResId = ResFinder.getId("umeng_comm_msg_text"); int timeResId = ResFinder.getId("umeng_comm_msg_time_tv"); int locResId = ResFinder.getId("umeng_comm_msg_location"); int locTextResId = ResFinder.getId("umeng_comm_msg_location_text"); int gvStubResId = ResFinder.getId("umeng_comm_msg_images_gv_viewstub"); int forwardgvResId = ResFinder.getId("forward_image_gv_layout"); int forwardTextResId = ResFinder.getId("umeng_comm_forard_text_tv"); int distanceTextResId = ResFinder.getId("umeng_comm_distance"); // 公告或者好友feed的图标 mFeedTypeImgView = findViewById(feedTypeResId); // 用户头像 mProfileImgView = findViewById(userIconResId); // 发布该消息的昵称 mUserNameTv = findViewById(userNameResId); // 文本内容 mFeedTextTv = findViewById(textResId); // feed底部的time、赞、转发、评论的父视图 mButtomLayout = findViewById(ResFinder.getId("umeng_comm_feed_action_layout")); // 更新时间 mTimeTv = findViewById(timeResId); // 位置图标 mLocationImgView = findViewById(locResId); // 地理位置 mLocationTv = findViewById(locTextResId); /** * 九宫格图片的View Stub */ mImageGvViewStub = findViewById(gvStubResId); // 操作栏, 点击时出现一个包含转发、评论、赞功能的popupwindow // mOpetationBtn = findViewById(commentBtnResId); // 转发时候的text和图片gv mForwardLayout = findViewById(forwardgvResId); // 转发文本内容 mForwardTextTv = findViewById(forwardTextResId); // 弹出举报、删除feed对话框的按钮 mShareBtn = findViewById(ResFinder.getId("umeng_comm_dialog_btn")); mLikeCountTextView = findViewById(ResFinder.getId("umeng_comm_like_tv")); mForwardCountTextView = findViewById(ResFinder.getId("umeng_comm_forward_tv")); mCommentCountTextView = findViewById(ResFinder.getId("umeng_comm_comment_tv")); mDistanceTextView = findViewById(distanceTextResId); } protected void initEventHandle() { mLikeCountTextView.setOnClickListener(new LoginOnViewClickListener() { @Override protected void doAfterLogin(View v) { clickAnima(mLikeCountTextView); mLikePresenter.setFeedItem(mFeedItem); if (mFeedItem.isLiked) { mLikePresenter.postUnlike(mFeedItem.id); } else { mLikePresenter.postLike(mFeedItem.id); } } }); // 转发按钮 mForwardCountTextView.setOnClickListener(new LoginOnViewClickListener() { @Override protected void doAfterLogin(View v) { clickAnima(mForwardCountTextView); mPresenter.gotoForwardActivity(mFeedItem); } }); mLocationImgView.setOnClickListener(mLocationClickListener); mLocationTv.setOnClickListener(mLocationClickListener); } /** * 点击地理位置的回调,跳转至LocationFeedActivity页面 */ private OnClickListener mLocationClickListener = new Listeners.LoginOnViewClickListener() { @Override protected void doAfterLogin(View v) { Intent intent = new Intent(mContext, LocationFeedActivity.class); intent.putExtra(Constants.FEED, mFeedItem); mContext.startActivity(intent); } }; private void clickAnima(View targetView) { ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.1f, 1.0f, 1.1f); scaleAnimation.setDuration(100); targetView.startAnimation(scaleAnimation); } public void setShareActivity(final Activity activity) { mShareBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { shareToSns(activity); } }); } private void shareToSns(Activity activity) { ShareContent shareItem = new ShareContent(); shareItem.mText = mFeedItem.text; List<ImageItem> imageItems = mFeedItem.imageUrls; if (mFeedItem.sourceFeed != null) { imageItems = mFeedItem.sourceFeed.imageUrls; } if (imageItems.size() > 0) { shareItem.mImageItem = imageItems.get(0); } shareItem.mTargetUrl = mFeedItem.shareLink; if (TextUtils.isEmpty(shareItem.mTargetUrl) && mFeedItem.sourceFeed != null) { shareItem.mTargetUrl = mFeedItem.sourceFeed.shareLink; } shareItem.mFeedId = mFeedItem.id; shareItem.mTitle = mFeedItem.text; ShareSDKManager.getInstance().getCurrentSDK().share(activity, shareItem); } /** * 填充消息流ListView每项的数据 * * @param viewHolder * @param item */ protected void bindFeedItemData() { if (TextUtils.isEmpty(mFeedItem.id)) { return; } // 设置基础信息 setBaseFeeditemInfo(); // 设置图片 setupImageGridView(); // 设置feed图片 // 转发的feed if (mFeedItem.sourceFeed != null) { // 转发视图 setForwardViewVisibility(mFeedItem); // 设置转发视图的数据 setForwardItemData(mFeedItem); } else { // 设置普通类型feed的item view的可见性 setCommFeedViewVisibility(mFeedItem); } mLikeCountTextView.setText("" + mFeedItem.likeCount); mCommentCountTextView.setText("" + mFeedItem.commentCount); mForwardCountTextView.setText("" + mFeedItem.forwardCount); like(mFeedItem.isLiked); } /** * 设置普通feed视图的可见性 * * @param viewHolder */ private void setCommFeedViewVisibility(FeedItem item) { // 修改转发视图的背景为透明 mForwardLayout.setBackgroundColor(Color.TRANSPARENT); // mForwardLayout.setVisibility(View.GONE); mForwardLayout.setPadding(0, 0, 0, 0); if (mImageGv != null) { mImageGv.setPadding(0, 0, 0, 0); } // 隐藏转发视图 mForwardTextTv.setVisibility(View.GONE); // 显示时间视图 mTimeTv.setVisibility(View.VISIBLE); // 昵称 mUserNameTv.setVisibility(View.VISIBLE); // 加载头像视图设置为可见 mProfileImgView.setVisibility(View.VISIBLE); } /** * 设置转发的数据 * * @param viewHolder 视图Holder * @param item 转发的feed item */ private void setForwardItemData(FeedItem item) { // @原始feed的创建者 atOriginFeedCreator(item.sourceFeed); // 大于等于2表示该feed已经被删除 if (item.sourceFeed.status >= FeedItem.STATUS_SPAM || isDeleted(item.sourceFeed)) { mForwardTextTv.setGravity(Gravity.CENTER); mForwardTextTv.setText(ResFinder.getString("umeng_comm_feed_deleted")); if (mImageGv != null) { mImageGv.setVisibility(View.GONE); } // 如果该feed是收藏,且转发feed、原feed都被删除,则不显示原feed的状态 if (item.status >= FeedItem.STATUS_SPAM && item.sourceFeed.status >= FeedItem.STATUS_SPAM) { mForwardLayout.setVisibility(View.GONE); } else { // 删除被转发的feed deleteInvalidateFeed(item.sourceFeed); } } else { mForwardTextTv.setGravity(Gravity.LEFT | Gravity.CENTER); // 解析被转发的@和话题 FeedViewRender.parseTopicsAndFriends(mForwardTextTv, item.sourceFeed); if (mImageGv != null) { mImageGv.setVisibility(View.VISIBLE); } } } /** * @param feedItem */ protected void deleteInvalidateFeed(FeedItem feedItem) { DatabaseAPI.getInstance().getFeedDBAPI().deleteFeedFromDB(feedItem.id); } /** * 被转发的原始feed的创建者在转发时会被@,因此将其名字设置到文本中,然后将其添加到@的好友中. * * @param feedItem */ protected void atOriginFeedCreator(FeedItem feedItem) { String contextText = feedItem.text; // @前缀 final String atPrefix = "@" + feedItem.creator.name + ": "; if (!contextText.contains(atPrefix)) { feedItem.text = atPrefix + contextText; feedItem.atFriends.add(feedItem.creator); } } /** * 判断该feed是否被删除,本地[目前暂时按照从方法判断]</br> * * @param item * @return */ private boolean isDeleted(FeedItem item) { if (TextUtils.isEmpty(item.publishTime)) { return true; } return false; } /** * 设置转发feed的视图的可见性 */ @SuppressWarnings("deprecation") private void setForwardViewVisibility(FeedItem item) { // 显示转发视图 mForwardLayout.setVisibility(View.VISIBLE); mForwardLayout.setPadding(10, 10, 10, 10); mForwardLayout.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mPresenter.clickOriginFeedItem(mFeedItem); } }); if (mImageGv != null) { mImageGv.setPadding(10, 2, 10, 10); } // 转发视图的背景 mForwardLayout.setBackgroundDrawable(ResFinder .getDrawable("umeng_comm_forward_bg")); // 被转发的文本 mForwardTextTv.setVisibility(View.VISIBLE); mForwardTextTv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mPresenter.clickOriginFeedItem(mFeedItem); } }); // 隐藏位置图标 mLocationImgView.setVisibility(View.GONE); mLocationTv.setVisibility(View.GONE); } /** * 设置feedItem的基本信息(头像,昵称,内容、位置)</br> * * @param viewHolder * @param feedItem */ protected void setBaseFeeditemInfo() { // 设置feed类型图标 setTypeIcon(); // 用户头像 setupUserIcon(mProfileImgView, mFeedItem.creator); // 昵称 mUserNameTv.setText(mFeedItem.creator.name); // 更新时间 Date date = new Date(Long.parseLong(mFeedItem.publishTime)); mTimeTv.setText(TimeUtils.format(date)); // feed的文本内容 FeedViewRender.parseTopicsAndFriends(mFeedTextTv, mFeedItem); // 地理位置信息 if (TextUtils.isEmpty(mFeedItem.locationAddr)) { mLocationTv.setVisibility(View.GONE); mLocationImgView.setVisibility(View.GONE); } else { mLocationTv.setVisibility(View.VISIBLE); mLocationImgView.setVisibility(View.VISIBLE); mLocationTv.setText(mFeedItem.locationAddr); } // 内容为空时Text隐藏布局,这种情况出现在转发时没有文本的情况 if (TextUtils.isEmpty(mFeedItem.text)) { mFeedTextTv.setVisibility(View.GONE); } else { mFeedTextTv.setVisibility(View.VISIBLE); } mFeedTextTv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mPresenter.clickFeedItem(); } }); if (mIsShowDistance) { mDistanceTextView.setText(mFeedItem.distance + M); } } /** * 设置feed 类型的icon</br> * * @param viewHolder * @param feedItem */ private void setTypeIcon() { Drawable drawable = null; if (mFeedItem.type == FeedItem.ANNOUNCEMENT_FEED && mFeedItem.isTop == FeedItem.TOP_FEED) { // 设置feed类型图标 drawable = ResFinder.getDrawable("umeng_comm_top_announce"); } else if (mFeedItem.type == FeedItem.ANNOUNCEMENT_FEED) { // 设置feed类型图标 drawable = ResFinder.getDrawable("umeng_comm_announce"); } else if (mFeedItem.isTop == FeedItem.TOP_FEED) { // feed 置顶图标 drawable = ResFinder.getDrawable("umeng_comm_top"); mFeedTypeImgView.setVisibility(View.VISIBLE); mFeedTypeImgView.setImageDrawable(drawable); } else { // 设置feed类型图标 [ 目前只标识公告类型 ] mFeedTypeImgView.setVisibility(View.INVISIBLE); return; } mFeedTypeImgView.setVisibility(View.VISIBLE); mFeedTypeImgView.setImageDrawable(drawable); } /** * 设置用户头像 * * @param userIconImageView 用户头像的SquareImageView * @param iconUrl 用户头像的url */ private void setupUserIcon(final NetworkImageView userIconImageView, final CommUser user) { if (user == null || userIconImageView == null) { return; } ImgDisplayOption option = ImgDisplayOption.getOptionByGender(user.gender); userIconImageView.setImageUrl(user.iconUrl, option); userIconImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 跳转用户中心前检查是否登录 mPresenter.gotoUserInfoActivity(user, mContainerClzName); } }); } public void setFeedItem(FeedItem feedItem) { mFeedItem = feedItem; mPresenter.setFeedItem(mFeedItem); bindFeedItemData(); } public FeedItem getFeedItem() { return mFeedItem; } /** * 在feed详情页面隐藏赞、评论、转发三个按钮 */ public void hideActionButtons() { mLikeCountTextView.setVisibility(View.GONE); mCommentCountTextView.setVisibility(View.GONE); mForwardCountTextView.setVisibility(View.GONE); } public void setOnItemViewClickListener(final int position,final OnItemViewClickListener<FeedItem> listener) { mItemViewClickListener = listener; mCommentCountTextView.setOnClickListener(new LoginOnViewClickListener() { @Override protected void doAfterLogin(View v) { clickAnima(mCommentCountTextView); if (mItemViewClickListener != null) { mItemViewClickListener.onItemClick(position, mFeedItem); } } }); } public void setOnUpdateListener(OnResultListener listener) { mLikePresenter.setResultListener(listener); } @Override public void like(boolean isLiked) { mFeedItem.isLiked = isLiked; if (mFeedItem.isLiked) { mLikeCountTextView.setCompoundDrawablesWithIntrinsicBounds( ResFinder.getResourceId(ResType.DRAWABLE, "umeng_comm_like_pressed"), 0, 0, 0); } else { mLikeCountTextView.setCompoundDrawablesWithIntrinsicBounds( ResFinder.getResourceId(ResType.DRAWABLE, "umeng_comm_like_normal"), 0, 0, 0); } } @Override public void updateLikeView(String nextUrl) { } public void setShowDistance() { mIsShowDistance = true; mDistanceTextView.setVisibility(View.VISIBLE); } }