RecyclerView的不同position加载不同View实现

在android开发中,有很多页面,可能一个页面上面需要2种不同的recyclerView,一般的,我们会使用一个scrollview,然后嵌套2个recyclerView,但是嵌套总会有点问题,除非你重写方法,listView是重写listview的onMeasure方法,RecyclerView重写LayoutManager方法,具体可以参考之前的一篇博客
http://blog.csdn.net/picasso_l/article/details/50324863

但是,这么做可能还是会有这样那样的限制。

下面介绍一种新的方法,全部用一个RecyclerView或者listview显示,用getItemViewType方法中不同的position,设置不同的ViewType

核心思想:
1.重写RecyclerView.Adapter的getItemViewType(int position),在此方法中根据不同的position,设置不同的ViewType
2.编写具体的RecyclerView.ViewHolder子类(不同子类对应不同View或Layout)
3.重写RecyclerView.Adapter的onCreateViewHolder(ViewGroup parent,int viewType) 在此方法中根据我们之前设置的ViewType来返回不同的RecyclerView.ViewHolder的子类

直接上代码

public class FunItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<FunItemModel.ImageUrlEntity> mImgList;
    private List<CommentsEntity> mCommentList;
    private Context mContext;
    private String author, time, msg, authorUrl, location;
    private static final int TYPE_INFO = 0;
    private static final int TYPE_IMGS = 1;
    private static final int TYPE_MSG = 2;
    private static final int TYPE_CT = 3;
    private static final int TYPE_COMS = 4;


    public FunItemAdapter(List<FunItemModel.ImageUrlEntity> imageUrlList, List<CommentsEntity> commentsList, String author, String authorUrl, String time, String location, String msg, Activity context) {
        LogCat.i("FunItemAdapter");
        mImgList = imageUrlList;
        mCommentList = commentsList;
        this.author = author;
        this.time = time;
        this.msg = msg;
        this.authorUrl = authorUrl;
        this.location = location;
        mContext = context;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

        RecyclerView.ViewHolder holder = getViewHolderByViewType(viewType);

        return holder;

    }

    private RecyclerView.ViewHolder getViewHolderByViewType(int viewType) {

        View view_info = View.inflate(mContext, R.layout.fun_item_info, null);
        View view_imgs = View.inflate(mContext, R.layout.fun_detail_pic_item_view, null);
        RecyclerView.ViewHolder holder = null;
        switch (viewType) {
            case TYPE_INFO:
                holder = new ViewHolder_Info(view_info);
                break;
            case TYPE_IMGS:
                holder = new ViewHolder_Imgs(view_imgs);
                break;
        }
//        if(i==(mImgList.size()+1)){//msg
//
//        }
//
//        if(i>(mImgList.size()+1)){//pinglun
//
//        }
        return holder;
    }

    @Override
    public int getItemViewType(int position) {

        if (position == 0) {
            return TYPE_INFO;
        }
        if (position > 0 && position <= mImgList.size()) {//mImgList){
            return TYPE_IMGS;
        }
        return 0;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
        if (i == 0) {
            Picasso
                    .with(mContext)
                    .load(authorUrl)
                    .into(((ViewHolder_Info)viewHolder).detail_author_img);
            ((ViewHolder_Info)viewHolder).detail_author_text.setText(author);
            ((ViewHolder_Info)viewHolder).detail_location.setText(location);
            ((ViewHolder_Info)viewHolder).detail_time.setText(time);
//            mMsgText.setText(msg);

        }
        if (i > 0) {
            String url = mImgList.get(i - 1).getValue();
            LogCat.i("帖子详情图片地址url=" + url);

            Transformation transformation = new PicassoTransformation(((ViewHolder_Imgs)viewHolder).detail_pic_item);

            if (url != null && !url.equals("")) {
                url = Constant.QINIU_YUN + url;
                Picasso
                        .with(mContext)
                        .load(url)
                        .placeholder(R.mipmap.zhanwei)
                        .error(R.mipmap.zhanwei)
                        .transform(transformation)
                        .into(((ViewHolder_Imgs)viewHolder).detail_pic_item);
            }
        }

    }


    @Override
    public int getItemCount() {
        return 1 + mImgList.size()/*+1+1+mCommentList.size()*/;
    }

    class ViewHolder_Info extends RecyclerView.ViewHolder {
        public ImageView detail_author_img;
        public TextView detail_author_text,detail_time,detail_location;

        public ViewHolder_Info(View itemView) {
            super(itemView);
            detail_author_img = (ImageView)itemView.findViewById(R.id.detail_author_img);
            detail_author_text = (TextView)itemView.findViewById(R.id.detail_author_text);
            detail_time = (TextView)itemView.findViewById(R.id.detail_time);
            detail_location = (TextView)itemView.findViewById(R.id.detail_location);
        }
    }

    class ViewHolder_Imgs extends RecyclerView.ViewHolder {
        public ImageView detail_pic_item;

        public ViewHolder_Imgs(View itemView) {
            super(itemView);
            detail_pic_item = (ImageView)itemView.findViewById(R.id.detail_pic_item);
        }
    }
}

效果可以是这样的
这里写图片描述
这里写图片描述

如上面2张图,从用户信息,到图片列表,到评论列表都是可以写在一个RecyclerView里面的

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
通过封装BaseAdapterRecyclerView.Adapter得到的通用的,简易的Adapter。项目地址:https://github.com/tianzhijiexian/CommonAdapter 效果图:已解决的问题 提升item的独立性,完美支持item被多处复用 item会根据type来做自动复用 支持多种类型的item 一个item仅会调用一次setViews(),避免重复建立监听器 一个item仅会触发一次绑定视图的操作,提示效率 支持dataBinding和其他第三方注入框架 提供了getView()方法来简化findViewById 支持通过item的构造方法来传入Activity对象 支持通过item的构造方法来传入item中事件的回调 提供了getConvertedData(data, type)方法来对item传入的数据做转换,方便拆包和提升item的复用性 支持viewpager的正常加载模式和懒加载 支持快速将listview的适配器切换为recyclerView的适配器 viewpager的notifyDataSetChanged可以正常更新界面 支持recyclerView的添加头部和底部 支持适配器的数据自动绑定,只用操作数据便可,adapter会自动notify界面零、重要接口adapteritem必须实现此接口,接口源码如下:public interface AdapterItem<T> {     /**      * @return item布局文件的layoutId      */     @LayoutRes     int getLayoutResId();     /**      * 初始化views      */     void bindViews(final View root);     /**      * 设置view的参数      */     void setViews();     /**      * 根据数据来设置item的内部views      *      * @param model    数据list内部的model      * @param position 当前adapter调用item的位置      */     void handleData(T model, int position); }例子:public class TextItem implements AdapterItem<DemoModel> {     @Override     public int getLayoutResId() {         return R.layout.demo_item_text;     }     TextView textView;     @Override     public void bindViews(View root) {         textView = (TextView) root.findViewById(R.id.textView);     }     @Override     public void setViews() { }     @Override     public void handleData(DemoModel model, int position) {         textView.setText(model.content);     } }一、ListView GridView的通用适配器——CommonAdapter只需继承CommonAdapter便可实现适配器:listView.setAdapter(new CommonAdapter<DemoModel>(data, 1) {     public AdapterItem<DemoModel> createItem(Object type) {         return new TextItem();     } });二、RecyclerView的通用适配器——CommonRcvAdapter通过继承CommonRcvAdapter实现适配器:mAdapter = new CommonRcvAdapter<DemoModel>(data) {  public AdapterItem createItem(Object type) {         return new TextItem();   } };三、ViewPager的通用适配器——CommonPagerAdapter通过继承CommonPagerAdapter实现适配器:viewPager.setAdapter(new CommonPagerAdapter<DemoModel>() {     public AdapterItem createItem(Object type) {         return new TextItem();     } });设计思路1. Adapter如果用adapter常规写法,你会发现代码量很大,可读性低。如果adapter中有多个类型的Item,我们还得在getView()中写很多if-else语句,很乱。 而现在我让adapter的代码量减少到一个8行的内部类,如果你需要更换item只需要动一行代码,真正实现了可插拔化。最关键的是item现在作为了一个独立的对象,可以方便的进行复用。2. AdapterItem和原来方式最为不同的一点就是我把adapteritem作为了一个实体,这种方式借鉴了RecyclerViewViewHolder的设计。把item作为实体的好处有很多,比如复用啊,封装啊,其余的就不细说了。3. 分层在使用过程中,我发现如果adapter放在view层,那就会影响到view层的独立性。此外adapter中经常有很多数据处理的操作,比如通过type选择item,数据的拆包、转换等操作。于是我还是推荐把adapter放在mvp的p层,或者是mvvm的m层。通过在实际的项目中使用来看,放在m或p层的效果较好,view的复用也比较好做。
介绍:一个实现了下拉刷新,滚动到底部加载更多以及添加header功能的的RecyclerView。使用方式和RecyclerView完全一致,不需要额外的layout,不需要写特殊的adater。 加载效果内置了AVLoadingIndicatorView上的所有效果,可以根据需要指定。项目地址:https://github.com/jianghejie/XRecyclerView 效果:使用:xml<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context=".MainActivity">       <com.jcodecraeer.xrecyclerview.XRecyclerView         android:id="@ id/recyclerview"         android:layout_width="fill_parent"         android:layout_height="fill_parent" />   </RelativeLayout>2.MainActivitypackage com.example.xrecyclerview;   import android.os.Bundle; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup;   import com.jcodecraeer.xrecyclerview.ProgressStyle; import com.jcodecraeer.xrecyclerview.XRecyclerView;   import java.util.ArrayList;   public class MainActivity extends AppCompatActivity {     private XRecyclerView mRecyclerView;     private MyAdapter mAdapter;     private ArrayList<String> listData;     private int refreshTime = 0;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         mRecyclerView = (XRecyclerView)this.findViewById(R.id.recyclerview);         LinearLayoutManager layoutManager = new LinearLayoutManager(this);         layoutManager.setOrientation(LinearLayoutManager.VERTICAL);         mRecyclerView.setLayoutManager(layoutManager);           mRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader);         mRecyclerView.setLaodingMoreProgressStyle(ProgressStyle.Pacman);         mRecyclerView.setArrowImageView(R.drawable.iconfont_downgrey);           View header =   LayoutInflater.from(this).inflate(R.layout.recyclerview_header, (ViewGroup)findViewById(android.R.id.content),false);         mRecyclerView.addHeaderView(header);             mRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() {             @Override             public void onRefresh() {                 refreshTime  ;                 new Handler().postDelayed(new Runnable(){                     public void run() {                         listData.clear();                         for(int i = 0; i < 15 ;i ){                             listData.add("item"   i   "after "   refreshTime   " times of refresh");                         }                         mAdapter.notifyDataSetChanged();                         mRecyclerView.refreshComplete();                     }                   }, 3000);            //refresh data here             }               @Override             public void onLoadMore() {                 new Handler().postDelayed(new Runnable(){                     public void run() {                         for(int i = 0; i < 15 ;i ){                             listData.add("item"   (i   listData.size()) );                         }                         mAdapter.notifyDataSetChanged();                         mRecyclerView.loadMoreComplete();                     }                 }, 3000);               }         });           listData = new  ArrayList<String>();         mAdapter = new MyAdapter(listData);         for(int i = 0; i < 15 ;i ){             listData.add("item"   i);         }         mRecyclerView.setAdapter(mAdapter);     }       @Override     public boolean onCreateOptionsMenu(Menu menu) {         // Inflate the menu; this adds items to the action bar if it is present.         getMenuInflater().inflate(R.menu.menu_main, menu);         return true;     }       @Override     public boolean onOptionsItemSelected(MenuItem item) {         // Handle action bar item clicks here. The action bar will         // automatically handle clicks on the Home/Up button, so long         // as you specify a parent activity in AndroidManifest.xml.         int id = item.getItemId();           //noinspection SimplifiableIfStatement         if (id == R.id.action_settings) {             return true;         }           return super.onOptionsItemSelected(item);     }     }3. adapterpackage com.example.xrecyclerview;   import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView;   import java.util.ArrayList;   /**  * Created by jianghejie on 15/11/26.  */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {     public ArrayList<String> datas = null;     public MyAdapter(ArrayList<String> datas) {         this.datas = datas;     }     //创建新View,被LayoutManager所调用     @Override     public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {         View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item,viewGroup,false);         ViewHolder vh = new ViewHolder(view);         return vh;     }     //将数据与界面进行绑定的操作     @Override     public void onBindViewHolder(ViewHolder viewHolder, int position) {         viewHolder.mTextView.setText(datas.get(position));     }     //获取数据的数量     @Override     public int getItemCount() {         return datas.size();     }     //自定义的ViewHolder,持有每个Item的的所有界面元素     public static class ViewHolder extends RecyclerView.ViewHolder {         public TextView mTextView;         public ViewHolder(View view){             super(view);             mTextView = (TextViewview.findViewById(R.id.text);         }     } }
使用 RecyclerView 实现分页加载的一般流程如下: 1. 在布局文件中定义 RecyclerView 和一个加载更多时显示的进度条。 2. 创建一个 Adapter,继承自 RecyclerView.Adapter实现数据的展示。 3. 在 Activity 或 Fragment 中初始化 RecyclerViewAdapter,并设置 LayoutManager。 4. 加载第一页数据。 5. 当用户滑动到列表底部时,触发加载更多数据的操作。 6. 在 Adapter 中添加一个方法,用于添加新的数据。 7. 在加载更多数据时,显示进度条,同时请求网络数据。 8. 当数据请求成功后,隐藏进度条,将新的数据添加到 Adapter 中,并通知 RecyclerView 刷新列表。 以下是一个简单的示例代码: ```java public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> { private List<MyData> mDataList = new ArrayList<>(); // 添加新的数据 public void addData(List<MyData> dataList) { mDataList.addAll(dataList); notifyDataSetChanged(); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // 创建 ViewHolder ... } @Override public void onBindViewHolder(MyViewHolder holder, int position) { // 绑定数据 ... } @Override public int getItemCount() { return mDataList.size(); } } public class MyActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private MyAdapter mAdapter; private ProgressBar mProgressBar; private int mCurrentPage = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化 RecyclerViewAdapter mRecyclerView = findViewById(R.id.recycler_view); mAdapter = new MyAdapter(); mRecyclerView.setAdapter(mAdapter); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); // 初始化进度条 mProgressBar = findViewById(R.id.progress_bar); // 加载第一页数据 loadMoreData(); } private void loadMoreData() { // 显示进度条 mProgressBar.setVisibility(View.VISIBLE); // 请求网络数据 MyApi.getData(mCurrentPage, new MyCallback<List<MyData>>() { @Override public void onSuccess(List<MyData> dataList) { // 隐藏进度条 mProgressBar.setVisibility(View.GONE); // 添加新的数据 mAdapter.addData(dataList); // 更新当前页数 mCurrentPage++; } @Override public void onFailure(Throwable t) { // 处理错误 } }); } // 监听 RecyclerView 的滑动事件 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // 判断是否已经滑动到列表底部 if (!recyclerView.canScrollVertically(1)) { // 加载更多数据 loadMoreData(); } } }); } ``` 在这个示例中,我们使用了一个 mCurrentPage 变量来记录当前加载的页数。每次加载更多数据时,都会将当前页数加一,并将新的数据添加到 Adapter 中。 当用户滑动到列表底部时,我们会触发 loadMoreData() 方法来请求新的数据。在这个方法中,我们显示进度条,请求网络数据,并在成功后隐藏进度条,并将新的数据添加到 Adapter 中。 注意,在这个示例中,我们使用了一个 MyCallback 接口来处理网络请求的回调。你需要根据实际情况自己实现这个接口,并在 onSuccess() 方法中处理返回的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值