RecyclerView使用(一)(仿微博首页UI设置)
来源:互联网 发布:老师知乎 编辑:程序博客网 时间:2024/05/17 03:13
RecyclerView的使用(仿微博首页UI设置)
1 导入包
包一定要导入,并且版本要适配 否则第二步的XML配置中,RecyclerView会提示找不到
compile 'com.android.support:recyclerview-v7:26.1.0'
2 MAinActivity的XML中
<android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" android:layout_below="@id/ll_1" android:layout_above="@+id/ll_2" > </android.support.v7.widget.RecyclerView>
3 MainActivity.java中
private RecyclerView mRecyclerView; mRecyclerView = findViewById(R.id.recyclerView);initData();initView();
4.1 initData() 实现
private RecyclerView.LayoutManager mLayoutManager;private RecyclerView.Adapter mAdapter;private void initData() { mAdapter = new ItemAdapter(getData()); }
数据载入见第6点先介绍布局
5.1 initView() 实现
设置布局管理器 进行布局的分隔线样式设置 设置适配器
private void initView() { //设置纵向滚动的 即item是横向分布的 mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); //设置布局管理器 mRecyclerView.setLayoutManager(mLayoutManager); //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能 mRecyclerView.setHasFixedSize(true); //设置adapter mRecyclerView.setAdapter(mAdapter); //添加分割线 mRecyclerView.addItemDecoration(new MyDividerItemDecoration( this, DividerItemDecoration.VERTICAL)); }
5.2分隔线样式设计
5.2.1使用系统默认的分隔线样式:
package com.scnu.sihao.sinaweibodemo;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.support.v4.view.ViewCompat;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;public class MyDividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; /** * 用于绘制间隔样式 */ private Drawable mDivider; /** * 列表的方向,水平/竖直 */ private int mOrientation; public MyDividerItemDecoration(Context context, int orientation) { // 获取默认主题的属性 final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { // 绘制间隔 if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } } private void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } /** * 绘制间隔 */ private void drawVertical(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child)); final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } /** * 绘制间隔 */ private void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child)); final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } }}
RecyclerView在绘制的时候,去会绘制decorator,即调用该类的onDraw和onDrawOver方法,
onDraw方法先于drawChildren
onDrawOver在drawChildren之后,一般我们选择复写其中一个即可。
getItemOffsets 可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator
5.2.2 添加自定义的分隔线样式设计
5.2.2.1 在styles.xml中
加一句
<item name="android:listDivider">@drawable/divider_bg</item>
使用自定义的xml文件设置样式
5.2.2.2 在drawable中 创建一个divider_bg.xml文件
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:centerColor="#7F7F7F" android:endColor="#7F7F7F" android:startColor="#7F7F7F" android:type="linear" /> <size android:height="6dp"/> </shape>
6 单个数据载入
6.1 数据传输
private ArrayList<String> getData() { ArrayList<String> screenName = new ArrayList<>(); for(int i = 0; i < RetrofitUtil.COUNT; i++) { userName[i]=retrofitUtil2.screen_name[i]; screenName.add(userName[i]); Log.i("GetUserName",userName[i]); } return screenName; }
6.2数据接收处理
package com.scnu.sihao.sinaweibodemo;import android.net.Uri;import android.support.v7.widget.RecyclerView;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import android.widget.VideoView;import java.util.ArrayList; // 创建ItemAdapter public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder>{ private ArrayList<String> mData; // 构造方法 传入数组 public ItemAdapter(ArrayList<String> data) { this.mData = data; } // public void updateData(ArrayList<String> data) { this.mData = data; notifyDataSetChanged(); } // @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // 实例化展示的view View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false); // 实例化viewholder ViewHolder viewHolder = new ViewHolder(v); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { // 绑定screenName数据 holder.userName.setText(mData.get(position)); } @Override public int getItemCount() { // 获取item的数量 return mData == null ? 0 : mData.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { TextView userName; TextView bodyText; public ViewHolder(View itemView) { super(itemView); // 获取组件 bodyText =itemView.findViewById(R.id.body_text); userName=itemView.findViewById(R.id.user_name); } } }
实例
7新浪微博数据传入:
MAinActivity.java
package com.scnu.sihao.sinaweibodemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.DividerItemDecoration;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.util.Log;import android.widget.VideoView;import java.util.ArrayList;public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private RecyclerView.Adapter mAdapter; private RecyclerView.LayoutManager mLayoutManager; private String[] userName = new String[RetrofitUtil.COUNT]; private static RetrofitUtil retrofitUtil2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //requestWindowFeature(Window.FEATURE_NO_TITLE);// 不显示程序的标题栏 继承Activity才可以生效 setContentView(R.layout.activity_main); mRecyclerView = findViewById(R.id.recyclerView); initData(); initView(); } // 获取对象 public static void getObject(RetrofitUtil retrofitUtil) { retrofitUtil2 = retrofitUtil; } private void initData() { mAdapter = new ItemAdapter( getScreenName(), getCreatAt(), getSource(), getRepostsCount(), getCommentsCount(), getAttitudesCount(), getText(), getProfileImageUrl(),getPicUrls()); } private void initView() { mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); //设置布局管理器 mRecyclerView.setLayoutManager(mLayoutManager); //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能 mRecyclerView.setHasFixedSize(true); //设置adapter mRecyclerView.setAdapter(mAdapter); //添加分割线 mRecyclerView.addItemDecoration(new MyDividerItemDecoration( this, DividerItemDecoration.VERTICAL)); } private ArrayList<String> getScreenName() { ArrayList<String> screenName = new ArrayList<>(); for (int i = 0; i < RetrofitUtil.COUNT; i++) { userName[i] = retrofitUtil2.screen_name[i]; screenName.add(userName[i]); Log.i("123123123", userName[i]); } return screenName; } private ArrayList<String> getCreatAt() { ArrayList<String> CreatAt = new ArrayList<>(); for (int i = 0; i < RetrofitUtil.COUNT; i++) { CreatAt.add(retrofitUtil2.created_at[i]); Log.i("123123123", retrofitUtil2.created_at[i]); } return CreatAt; } private ArrayList<String> getSource() { ArrayList<String> Source = new ArrayList<>(); for (int i = 0; i < RetrofitUtil.COUNT; i++) { Source.add(retrofitUtil2.source[i]); Log.i("123123123", retrofitUtil2.source[i]); } return Source; } private ArrayList<String> getRepostsCount() { ArrayList<String> RepostsCount = new ArrayList<>(); for (int i = 0; i < RetrofitUtil.COUNT; i++) { RepostsCount.add(retrofitUtil2.reposts_count[i]); Log.i("123123123", retrofitUtil2.reposts_count[i]); } return RepostsCount; } private ArrayList<String> getCommentsCount() { ArrayList<String> CommentsCount = new ArrayList<>(); for (int i = 0; i < RetrofitUtil.COUNT; i++) { CommentsCount.add(retrofitUtil2.comments_count[i]); Log.i("123123123", retrofitUtil2.comments_count[i]); } return CommentsCount; } private ArrayList<String> getAttitudesCount() { ArrayList<String> AttitudesCount = new ArrayList<>(); for (int i = 0; i < RetrofitUtil.COUNT; i++) { AttitudesCount.add(retrofitUtil2.attitudes_count[i]); Log.i("123123123", retrofitUtil2.attitudes_count[i]); } return AttitudesCount; } private ArrayList<String> getText() { ArrayList<String> Text = new ArrayList<>(); for (int i = 0; i < RetrofitUtil.COUNT; i++) { Text.add(retrofitUtil2.text[i]); Log.i("123123123", retrofitUtil2.text[i]); } return Text; } private ArrayList<String> getProfileImageUrl() { ArrayList<String> ProfileImageUrl = new ArrayList<>(); for (int i = 0; i < RetrofitUtil.COUNT; i++) { ProfileImageUrl.add(retrofitUtil2.profile_image_url[i]); Log.i("123123123", retrofitUtil2.profile_image_url[i]); } return ProfileImageUrl; } private String[][] getPicUrls() { String[][] PicUrls = new String[RetrofitUtil.COUNT][9]; for (int i = 0; i < RetrofitUtil.COUNT; i++) { for (int j = 0; j < 9; j++) { if(retrofitUtil2.pic_urls[i][j]!=null) { PicUrls[i][j] = retrofitUtil2.pic_urls[i][j]; Log.i("123123123", retrofitUtil2.pic_urls[i][j]); } } } return PicUrls; }}
ItemAdapter.java
package com.scnu.sihao.sinaweibodemo;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.net.Uri;import android.os.Message;import android.support.v7.widget.RecyclerView;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.ImageView;import android.widget.TextView;import android.widget.VideoView;import java.net.URL;import java.util.ArrayList;// 创建ItemAdapterpublic class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder>{ private ArrayList<String> mScreenName; private ArrayList<String> mCreatAt; private ArrayList<String> mSource; private ArrayList<String> mRepostsCount; private ArrayList<String> mCommentsCount; private ArrayList<String> mAttitudesCount; private ArrayList<String> mText; private ArrayList<String> mProfileImageUrl; private String[][] mPicUrls= new String[RetrofitUtil.COUNT][9]; private boolean flag=false; // 构造方法 传入数组 public ItemAdapter(ArrayList<String> screenName,ArrayList<String> creatAt,ArrayList<String> source, ArrayList<String> repostsCount,ArrayList<String> commentsCount, ArrayList<String> attitudesCount, ArrayList<String> text, ArrayList<String> profileImageUrl,String[][] PicUrls) { this.mScreenName = screenName; this.mCreatAt = creatAt; this.mSource = source; this.mRepostsCount = repostsCount; this.mCommentsCount = commentsCount; this.mAttitudesCount = attitudesCount; this.mText = text; this.mProfileImageUrl = profileImageUrl; this.mPicUrls=PicUrls; } /*public void updateData(ArrayList<String> screenName) { this.mScreenName = screenName; notifyDataSetChanged(); }*/ @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // 实例化展示的view 非Activity与XML连接 View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false); // 实例化viewholder ViewHolder viewHolder = new ViewHolder(v); return viewHolder; } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { Log.i("position", String.valueOf(position)); // 传过来的ArrayList 根据position绑定值 position为当前界面显示的item条目 从0开始 若有多个则调用多个 但是也是一个个按先后顺序的 holder.userName.setText(mScreenName.get(position)); holder.Time.setText(mCreatAt.get(position)); holder.From.setText(mSource.get(position)); holder.Transmit.setText(mRepostsCount.get(position)); holder.Comment.setText(mCommentsCount.get(position)); holder.Good.setText(mAttitudesCount.get(position)); holder.bodyText.setText(mText.get(position)); // 图片加载要用子线程!!! new Thread(new Runnable() { @Override public void run() { try { URL url = new URL(mProfileImageUrl.get(position)); Log.i("url", String.valueOf(url)); holder.UserImage.setImageBitmap(BitmapFactory.decodeStream(url.openStream())); } catch (Exception e) { e.printStackTrace(); } } }).start(); // 图片加载要用子线程!!! for (int i = 0; i < 9; i++) { if (mPicUrls[position][i] != null) { flag = true; //提前结束了 break; } } if (flag) { new Thread(new Runnable() { @Override public void run() { try { for(int j = 0; j < 9; j++) { URL url = new URL(mPicUrls[position][j]); Log.i("url111222", String.valueOf(url)); holder.image[j].setImageBitmap(BitmapFactory.decodeStream(url.openStream())); } //flag为true之后 记得将他设置回false!!! flag=false; } catch (Exception e) { e.printStackTrace(); } } }).start(); } } // 重写该方法 可以实现设置item显示数量 不用调用 重写了就自动执行 @Override public int getItemCount() { // 获取item的数量 return mScreenName == null ? 0 : mScreenName.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { TextView userName; TextView Time,From; Button Transmit,Comment,Good; TextView bodyText; ImageView UserImage; //图片数组 ImageView []image = new ImageView[9]; public ViewHolder(View itemView) { super(itemView); // 获取组件 userName=itemView.findViewById(R.id.user_name); Time=itemView.findViewById(R.id.time); From=itemView.findViewById(R.id.from); Transmit=itemView.findViewById(R.id.transmit); Comment=itemView.findViewById(R.id.comment); Good=itemView.findViewById(R.id.good); bodyText =itemView.findViewById(R.id.body_text); UserImage=itemView.findViewById(R.id.user_image); //图片 image[0] = itemView.findViewById(R.id.image_1); image[1] = itemView.findViewById(R.id.image_2); image[2] = itemView.findViewById(R.id.image_3); image[3] = itemView.findViewById(R.id.image_4); image[4] = itemView.findViewById(R.id.image_5); image[5] = itemView.findViewById(R.id.image_6); image[6] = itemView.findViewById(R.id.image_7); image[7] = itemView.findViewById(R.id.image_8); image[8] = itemView.findViewById(R.id.image_9); } }}
RecyclerView会根据item的真实呈现,去调用onBindViewHolder() 方法进行数据的绑定
若一个界面有多个item呈现, 则按顺序调用每个item的onBindViewHolder 根据onBindViewHolder(position)里的参数position (下标从0开始)去绑定数据
问题1
这个是界面显示就自动加载数据,加载界面,这样recyclerView就会有adpater 可以加载
但是若加载界面时先不加载数据,点击了某个按钮再加载数据,加载recyclerView的界面,但是这样初始化界面recyclerView没有adapter会skipping
解决:可以先在加载的时候让他View.GONE 等要用了再让他visible
问题2
RecyclerView中的item图片要刷到item可见变为不可见,才能把图片加载出来
使用Glide框架进行图片加载
参考:
http://blog.csdn.net/weixin_37577039/article/details/78698865
- RecyclerView使用(一)(仿微博首页UI设置)
- RecyclerView使用(一)
- RecyclerView使用详解(一)
- RecyclerView使用详解(一)
- RecyclerView使用详解(一)
- RecyclerView使用详解(一)
- RecyclerView使用详解(一)
- RecyclerView使用进阶(一)
- RecyclerView使用详解(一)
- RecyclerView使用详解(一)
- RecyclerView的使用(一)
- RecyclerView使用详解(一)
- Recyclerview使用体验(一)
- RecyclerView的使用(一)
- android UI开发之RecyclerView(一)简单实现
- Android RecyclerView使用(一) 基本使用
- RecyclerView中ItemDecoration的简单使用(一)--设置item的padding
- jboss-as-7.1.1.Final:(一)首页设置
- 计算机视觉学习笔记:梯度下降(gradient Descent)
- iOS Swift 入门
- 介绍Collection框架的结构
- vue 学习笔记
- 第二章kNN分类算法sorted函数
- RecyclerView使用(一)(仿微博首页UI设置)
- 【数字图像处理】HSV颜色分量
- angularjs项目的知识点
- MacOS 剪切文件
- iOS调研——Masonry与SDAutoLayout相比较
- forEach循环es6语法
- Vue.js 2.0 中#$on与$emit如何使用之实例讲解
- MySQL数据库入门(二)
- *傅里叶变换