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