上一篇我们已经写完图文详情的布局展示,这一篇我们将完成图文详情的数据展示 因为我们这个详情分为图文和视频,所以我们采用组合方式实现,相同的部分我们提取自父类中去完成 我们跳转到详情需要这个帖子的相关信息,所以我们需要传过来一个 然后我们根据帖子 这个的这个 然后我们回到 这里我们需要这个列表写一个适配器 然后我们写这个适配器的 我们写完评论列表之后,先完成图文详情页的头部数据绑定,并且给这个 这里我们是监听列表的滑动,滑动一定的距离后我们就需要改变UI样式 OK,接着我们就可以写网络请求了,首先是获取评论列表,我们新建一个 然后我们回到 接着就是在 然后我们就要写底部互动区域的行为事件了,我们先看下都有哪些 和我们之前写过了,我们主要就是写和关注以及删除,我们还是在 这里主要实现和之前差不多,就不说明了,然后我们在对应的 我们给我们的详情页添加一个跳转方法 OK,然后我们运行下看看效果
前言
实现
Feed
对象 Feed feed = (Feed) getIntent().getSerializableExtra(KEY_FEED); if (feed == null) { finish(); return; }
ItemType
来区分 if (feed.itemType == Feed.TYPE_IMAGE_TEXT) { viewHandler = new ImageViewHandler(this); } else { viewHandler = new VideoViewHandler(this); }
viewHandler
是ViewHandler
这个类,这个类是处理相同逻辑部分的,它对应的就是两个子类ImageViewHandler
和VideoViewHandler
,接着我们就通过bindInitData
方法对ViewHandler
设置,所以我们详情页的onCreate
方法如下 @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Feed feed = (Feed) getIntent().getSerializableExtra(KEY_FEED); if (feed == null) { finish(); return; } if (feed.itemType == Feed.TYPE_IMAGE_TEXT) { viewHandler = new ImageViewHandler(this); } else { viewHandler = new VideoViewHandler(this); } viewHandler.bindInitData(feed); }
ViewHandler
这个类中,这个类我们需要做列表数据绑定,底部互动绑定以及行为处理,所以这个类里面需要有RecyclerView
对象和底部DataBinding
对象,并且我们在我们的bindInitData
方法中初始化一下 protected FragmentActivity mActivity; protected Feed mFeed; protected RecyclerView mRecyclerView; protected LayoutFeedDetailBottomInateractionBinding mInateractionBinding; protected FeedCommentAdapter mListAdapter; public ViewHandler(FragmentActivity activity) { mActivity = activity;; } @CallSuper public void bindInitData(Feed feed) { mInateractionBinding.setOwner(mActivity); mFeed = feed; mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity, LinearLayoutManager.VERTICAL, false)); mRecyclerView.setItemAnimator(null); mListAdapter = new FeedCommentAdapter(mActivity); mRecyclerView.setAdapter(mListAdapter); }
FeedCommentAdapter
,列表大概样式如下
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools"> <data> <variable name="comment" type="com.mooc.ppjoke.model.Comment" /> <import type="android.text.TextUtils"/> <import type="android.view.View"/> <import type="com.mooc.ppjoke.ui.login.UserManager"/> <import type="com.mooc.ppjoke.utils.TimeUtils"/> <import type="com.mooc.ppjoke.ui.InterActionPresenter"/> <variable name="owner" type="androidx.lifecycle.LifecycleOwner" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingBottom="@dimen/dp_10"> <com.mooc.libcommon.view.PPImageView android:id="@+id/author_avatar" android:layout_width="@dimen/dp_40" android:layout_height="@dimen/dp_40" android:layout_marginLeft="@dimen/dp_16" android:layout_marginTop="@dimen/dp_16" app:image_url="@{comment.author.avatar}" app:isCircle="@{true}" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" tools:src="@drawable/splash"/> <TextView android:id="@+id/author_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/dp_10" android:layout_marginTop="@dimen/dp_16" android:text="@{comment.author.name}" android:textColor="@color/color_000" android:textSize="@dimen/sp_12" app:layout_constraintLeft_toRightOf="@+id/author_avatar" app:layout_constraintTop_toTopOf="parent" tools:text="神秘的jetpack"/> <com.google.android.material.button.MaterialButton android:id="@+id/label_author" android:layout_width="wrap_content" android:layout_height="@dimen/dp_14" android:layout_marginLeft="@dimen/dp_10" android:layout_marginTop="@dimen/dp_16" android:gravity="center" android:includeFontPadding="false" android:paddingLeft="@dimen/dp_5" android:paddingTop="@dimen/dp_0" android:paddingRight="@dimen/dp_5" android:paddingBottom="@dimen/dp_0" android:stateListAnimator="@null" android:text="@string/author" android:textColor="@color/color_white" android:textSize="10sp" app:backgroundTint="@color/color_theme" app:cornerRadius="@dimen/dp_3" app:layout_constraintBaseline_toBaselineOf="@+id/author_name" app:layout_constraintLeft_toRightOf="@+id/author_name" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/create_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/dp_10" android:layout_marginTop="@dimen/dp_16" android:text="@{TimeUtils.calculate(comment.createTime)}" android:textColor="@color/color_999" android:textSize="10sp" app:layout_constraintBaseline_toBaselineOf="@+id/author_name" app:layout_constraintLeft_toRightOf="@+id/label_author" app:layout_constraintTop_toTopOf="parent" tools:text="12天前"/> <TextView android:id="@+id/comment_like" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dp_16" android:layout_marginRight="16dp" android:drawableRight="@{comment.ugc.hasLiked?@drawable/icon_cell_liked:@drawable/icon_cell_like}" android:drawablePadding="@dimen/dp_3" android:gravity="center_vertical" android:includeFontPadding="false" android:onClick="@{()->InterActionPresenter.toggleCommentLike(owner,comment)}" android:text="@{String.valueOf(comment.ugc.likeCount)}" android:textColor="@{comment.ugc.hasLiked?@color/color_theme:@color/color_999}" android:textSize="@dimen/sp_10" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" tools:drawableRight="@drawable/icon_cell_liked_large" tools:text="1000"/> <ImageView android:id="@+id/comment_delete" android:layout_width="@dimen/dp_14" android:layout_height="@dimen/dp_14" android:layout_marginRight="@dimen/dp_10" android:src="@drawable/icon_item_cell_delete" app:layout_constraintBottom_toBottomOf="@id/comment_like" app:layout_constraintRight_toLeftOf="@+id/comment_like" app:layout_constraintTop_toTopOf="@id/comment_like"/> <TextView android:id="@+id/comment_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/dp_10" android:layout_marginTop="@dimen/dp_5" android:gravity="center_vertical" android:includeFontPadding="false" android:text="@{comment.commentText}" android:textColor="@color/color_333" android:textSize="@dimen/sp_14" app:layout_constraintHorizontal_weight="1" app:layout_constraintLeft_toRightOf="@+id/author_avatar" app:layout_constraintRight_toLeftOf="@+id/comment_like" app:layout_constraintTop_toBottomOf="@+id/author_name" tools:text="comment.commentText"/> <FrameLayout android:id="@+id/comment_ext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/dp_10" android:layout_marginTop="@dimen/dp_10" app:layout_constraintLeft_toRightOf="@+id/author_avatar" app:layout_constraintTop_toBottomOf="@id/comment_text"> <com.mooc.libcommon.view.PPImageView android:id="@+id/comment_cover" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@color/color_gray2" android:scaleType="center" tools:layout_height="100dp" tools:layout_width="100dp"> </com.mooc.libcommon.view.PPImageView> <ImageView android:id="@+id/video_icon" android:layout_width="@dimen/dp_25" android:layout_height="@dimen/dp_25" android:layout_gravity="center" android:src="@drawable/icon_video_play"/> </FrameLayout> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
Java
代码public class FeedCommentAdapter extends AbsPagedListAdapter<Comment, FeedCommentAdapter.ViewHolder> { private LayoutInflater mInflater; private Context mContext; protected FeedCommentAdapter(Context context) { super(new DiffUtil.ItemCallback<Comment>() { @Override public boolean areItemsTheSame(@NonNull Comment oldItem, @NonNull Comment newItem) { return oldItem.id == newItem.id; } @Override public boolean areContentsTheSame(@NonNull Comment oldItem, @NonNull Comment newItem) { return oldItem.equals(newItem); } }); mContext = context; mInflater = LayoutInflater.from(context); } @Override protected ViewHolder onCreateViewHolder2(ViewGroup parent, int viewType) { LayoutFeedCommentListItemBinding binding = LayoutFeedCommentListItemBinding.inflate(mInflater, parent, false); return new ViewHolder(binding.getRoot(), binding); } @Override protected void onBindViewHolder2(ViewHolder holder, int position) { Comment item = getItem(position); holder.bindData(item); } public class ViewHolder extends RecyclerView.ViewHolder { private LayoutFeedCommentListItemBinding mBinding; public ViewHolder(@NonNull View itemView, LayoutFeedCommentListItemBinding binding) { super(itemView); mBinding = binding; } public void bindData(Comment item) { mBinding.setComment(item); boolean self = item.author != null && UserManager.get().getUserId() == item.author.userId; mBinding.labelAuthor.setVisibility(self ? View.VISIBLE : View.GONE); mBinding.commentDelete.setVisibility(self ? View.VISIBLE : View.GONE); if (!TextUtils.isEmpty(item.imageUrl)) { mBinding.commentExt.setVisibility(View.VISIBLE); mBinding.commentCover.setVisibility(View.VISIBLE); mBinding.commentCover.bindData(item.width, item.height, 0, PixUtils.dp2px(200), PixUtils.dp2px(200), item.imageUrl); if (!TextUtils.isEmpty(item.videoUrl)) { mBinding.videoIcon.setVisibility(View.VISIBLE); } else { mBinding.videoIcon.setVisibility(View.GONE); } } else { mBinding.commentCover.setVisibility(View.GONE); mBinding.videoIcon.setVisibility(View.GONE); mBinding.commentExt.setVisibility(View.GONE); } } } }
RecyclerView
添加这个头部,我们回到ImageViewHandler
这个类,这里有两个DataBinding
,一个是图文详情的,我们通过这个拿到列表和底部互动布局,一个是头部的public class ImageViewHandler extends ViewHandler { protected ActivityFeedDetailTypeImageBinding mImageBinding; protected LayoutFeedDetailTypeImageHeaderBinding mHeaderBinding; public ImageViewHandler(FragmentActivity activity) { super(activity); mImageBinding = DataBindingUtil.setContentView(activity, R.layout.activity_feed_detail_type_image); mInateractionBinding = mImageBinding.interactionLayout; mRecyclerView = mImageBinding.recyclerView; } @Override public void bindInitData(Feed feed) { super.bindInitData(feed); mImageBinding.setFeed(mFeed); mHeaderBinding = LayoutFeedDetailTypeImageHeaderBinding.inflate(LayoutInflater.from(mActivity), mRecyclerView, false); mHeaderBinding.setFeed(mFeed); PPImageView headerImage = mHeaderBinding.headerImage; headerImage.bindData(mFeed.width, mFeed.height, mFeed.width > mFeed.height ? 0 : 16, mFeed.cover); mListAdapter.addHeaderView(mHeaderBinding.getRoot()); mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); boolean visible = mHeaderBinding.getRoot().getTop() <= -mImageBinding.titleLayout.getMeasuredHeight(); mImageBinding.authorInfoLayout.getRoot().setVisibility(visible ? View.VISIBLE : View.GONE); mImageBinding.title.setVisibility(visible ? View.GONE : View.VISIBLE); } }); } }
ViewModel
,在这个类里面做数据请求public class FeedDetailViewModel extends AbsViewModel<Comment> { private long itemId; @Override public DataSource createDataSource() { return new DataSource(); } public void setItemId(long itemId) { this.itemId = itemId; } class DataSource extends ItemKeyedDataSource<Integer, Comment> { @Override public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull LoadInitialCallback<Comment> callback) { loadData(params.requestedInitialKey, params.requestedLoadSize, callback); } @Override public void loadAfter(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Comment> callback) { if (params.key > 0) { loadData(params.key, params.requestedLoadSize, callback); } } private void loadData(Integer key, int requestedLoadSize, LoadCallback<Comment> callback) { ApiResponse<List<Comment>> response = ApiService.get("/comment/queryFeedComments") .addParam("id", key) .addParam("itemId", itemId) .addParam("userId", UserManager.get().getUserId()) .addParam("pageCount", requestedLoadSize) .responseType(new TypeReference<ArrayList<Comment>>() { }.getType()) .execute(); List<Comment> list = response.body == null ? Collections.emptyList() : response.body; callback.onResult(list); } @Override public void loadBefore(@NonNull LoadParams<Integer> params, @NonNull LoadCallback<Comment> callback) { callback.onResult(Collections.emptyList()); } @NonNull @Override public Integer getKey(@NonNull Comment item) { return item.id; } } }
ViewHandler
中触发加载逻辑
首先通过ViewModelProviders
拿到我们的ViewModel
对象 public ViewHandler(FragmentActivity activity) { mActivity = activity; viewModel = ViewModelProviders.of(activity).get(FeedDetailViewModel.class); }
bindInitData
触发 viewModel.setItemId(mFeed.itemId); viewModel.getPageData().observe(mActivity, new Observer<PagedList<Comment>>() { @Override public void onChanged(PagedList<Comment> comments) { mListAdapter.submitList(comments); handleEmpty(comments.size() > 0); } });
private EmptyView mEmptyView; public void handleEmpty(boolean hasData) { if (hasData) { if (mEmptyView != null) { mListAdapter.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)); } mListAdapter.addHeaderView(mEmptyView); } }
InterActionPresenter
这个类中完成 ///取消一个帖子 public static void toggleFeedFavorite(LifecycleOwner owner, Feed feed) { if (!isLogin(owner, new Observer<User>() { @Override public void onChanged(User user) { toggleFeedFavorite(feed); } })) { } else { toggleFeedFavorite(feed); } } private static void toggleFeedFavorite(Feed feed) { ApiService.get("/ugc/toggleFavorite") .addParam("itemId", feed.itemId) .addParam("userId", UserManager.get().getUserId()) .execute(new JsonCallback<JSONObject>() { @Override public void onSuccess(ApiResponse<JSONObject> response) { if (response.body != null) { boolean hasFavorite = response.body.getBooleanValue("hasFavorite"); feed.getUgc().setHasFavorite(hasFavorite); } } @Override public void onError(ApiResponse<JSONObject> response) { showToast(response.message); } }); } //关注/取消关注一个用户 public static void toggleFollowUser(LifecycleOwner owner, Feed feed) { if (!isLogin(owner, new Observer<User>() { @Override public void onChanged(User user) { toggleFollowUser(feed); } })) { } else { toggleFollowUser(feed); } } private static void toggleFollowUser(Feed feed) { ApiService.get("/ugc/toggleUserFollow") .addParam("followUserId", UserManager.get().getUserId()) .addParam("userId", feed.author.userId) .execute(new JsonCallback<JSONObject>() { @Override public void onSuccess(ApiResponse<JSONObject> response) { if (response.body != null) { boolean hasFollow = response.body.getBooleanValue("hasLiked"); feed.getAuthor().setHasFollow(hasFollow); } } @Override public void onError(ApiResponse<JSONObject> response) { showToast(response.message); } }); }
xml
中添加上点击事件即可,做完这些之后我们把帖子列表的Item
点击事件加上FeedAdapter
中 @Override protected void onBindViewHolder2(ViewHolder holder, int position) { final Feed feed = getItem(position); holder.bindData(feed); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { FeedDetailActivity.startFeedDetailActivity(mContext, feed, mCategory); } }); }
private static final String KEY_FEED = "key_feed"; public static final String KEY_CATEGORY = "key_category"; public static void startFeedDetailActivity(Context context, Feed item, String category) { Intent intent = new Intent(context, FeedDetailActivity.class); intent.putExtra(KEY_FEED, item); intent.putExtra(KEY_CATEGORY, category); context.startActivity(intent); }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算