RecyclerView是Google在API 21下support.V7包里的控件,用来替代ListView。
一、使用RecycleView的前提条件
想使用RecycleView,一定要在build.gradle中引入compile 'com.android.support:recyclerview-v7:24.0.0'依赖。就是必须导入v7包。
首先它的使用几乎和listview相差不大,看它的xml,直接生成一个Recycleview然后,设置宽高id即可。二、使用RecycleView的优缺点
RecyclerView提供了三种布局管理器:
- LinerLayoutManager 以垂直或者水平列表方式展示Item
- GridLayoutManager 以网格方式展示Item
- StaggeredGridLayoutManager 以瀑布流方式展示Item
优点:
- RecycleView强制封装ViewHolder
- 相当轻松的设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式
- 可设置Item操作的动画,删除或者添加等
- 通过ItemDecoration,控制Item间的间隔,可自己绘制
缺点:
- 需要自己实现OnItemClickListener点击事件(这么实用的需求,Google竟然让我们自己实现...),相当无语阿。。。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/Retorytext4" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="" /> <!--<ListView--> <!--android:id="@+id/listview"--> <!--android:layout_width="match_parent"--> <!--android:layout_height="match_parent" />-->二、activty界面分析<android.support.v7.widget.RecyclerView android:id="@+id/Retorylistview" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
1.//首先要找到该控件
mrycleview=view.findViewById(R.id.Retorylistview); RecyclerView.LayoutManager line= new LinearLayoutManager(context);//设置一个布局管理器,默认为垂直的line.setOrientation(OrientationHelper.HORIZONTAL);
mrycleview.setLayoutManager(line);
2.绑定adapter//这个activty代码rec=new recycleadapter();mrycleview.setAdapter(rec);
public class fram_0 extends Fragment { public View view; public ListView list; public ListAdapter listAdapter; private RecyclerView mrycleview; recycleadapter rec; private PlayerActivity activty; private int a; private Bundle bundle; ArrayList<josntop.ShowapiResBodyBean.PagebeanBean.SonglistBean> list1; PlayerActivity Play; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.layout_0, container, false); list=view.findViewById(R.id.listview); // mrycleview=view.findViewById(R.id.Retorylistview); // mrycleview.setItemAnimator(new DefaultItemAnimator()); rec=new recycleadapter(); activty= (PlayerActivity) getActivity(); Log.e("msg","44444444444444444444444"); rec.SetOnItemclick(new recycleadapter.Onitemlisten() { @Override public void onitemclick(View view, int position) { Toast.makeText(view.getContext(), list1.get(position).getUrl()+"", Toast.LENGTH_SHORT).show(); activty.setpaly(); } }); mrycleview.setAdapter(rec); // rec.notifyDataSetChanged() query(); click(); return view; } public void set(int a) { this.a=a; } @Override public void onAttach(Context context) { Log.e("msg","Fragment:onAttach"); super.onAttach(context); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { Log.e("msg","Fragment:onCreate"); super.onCreate(savedInstanceState); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { Log.e("msg","Fragment:onActivityCreated"); super.onActivityCreated(savedInstanceState); } @Override public void onStart() { Log.e("msg","Fragment:onStart"); super.onStart(); } @Override public void onResume() { Log.e("msg","Fragment:onResume"); super.onResume(); } @Override public void onPause() { Log.e("msg","Fragment:onPause"); super.onPause(); } @Override public void onStop() { Log.e("msg","Fragment:onStop"); super.onStop(); } @Override public void onDestroyView() { Log.e("msg","Fragment:onDestroyView"); super.onDestroyView(); } @Override public void onDestroy() { Log.e("msg","Fragment:onDestroy"); super.onDestroy(); } @Override public void onDetach() { Log.e("msg","Fragment:onDetach"); super.onDetach(); } private void query() { // http://route.showapi.com/213-4?showapi_appid=48962&topid=5&showapi_sign=9ad486a2461e47f4b3391171911f5b4b //1.创建Retrofit对象 Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create())//解析方法 .baseUrl("http://route.showapi.com/")//主机地址 .build(); PlayerActivity.retrofitinter retrofitinter=retrofit.create(PlayerActivity.retrofitinter.class); Call<josntop> call=retrofitinter.getResult("48962","5","9ad486a2461e47f4b3391171911f5b4b"); call.enqueue(new Callback<josntop>() { @Override public void onResponse(Call<josntop> call, Response<josntop> response) { list1= (ArrayList<josntop.ShowapiResBodyBean.PagebeanBean.SonglistBean>) response.body().getShowapi_res_body().getPagebean().getSonglist(); TextView TV=view.findViewById(R.id.Retorytext4); // for(int i=0;i<list1.size();i++) // { // list1.get(i).getSingername(); Log.e("msg", list.get(i).getSingername()+""); // TV.append(list1.get(i).getSingername()); // listAdapter.get(list,context); // } final Context context=view.getContext(); mrycleview=view.findViewById(R.id.Retorylistview); RecyclerView.LayoutManager line= new LinearLayoutManager(context); mrycleview.setLayoutManager(line);
//默认就是垂直发的 // line.setOrientation(OrientationHelper.HORIZONTAL); rec.setdata(list1); // list.setAdapter(listAdapter); } @Override public void onFailure(Call<josntop> call, Throwable t) { } }); } public interface retrofitinter { @GET("/213-4/") Call<josntop> getResult(@Query("showapi_appid") String showapi_appid, @Query("topid") String topid, @Query("showapi_sign") String showapi_sign); }
三、可以看到对RecylerView的设置过程,比ListView要复杂一些,虽然代码抒写上有点复杂,但它的扩展性是极高的。在了解了RecyclerView的一些控制之后,紧接着来看看它的Adapter的写法,RecyclerView的Adapter与ListView的Adapter还是有点区别的,RecyclerView.Adapter,需要实现3个方法:
1.onCreateViewHolder()
这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
第一个方法中主要进行了
1.实例化一个view。
context=parent.getContext();
View view=inflater.from(parent.getContext()).inflate(R.layout.listitem,null);
2.实例化了一个viewhoider
ViewHolder holder= new ViewHolder(view);
3.获取了一个媒体播放的对象,主要是因为我需要在获得子条目时在这里面就进行播放,放在这个方法最
manager= Playmanager.getinstance();
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Log.e("msg","11111111111111111"); context=parent.getContext(); View view=inflater.from(parent.getContext()).inflate(R.layout.listitem,null); ViewHolder holder= new ViewHolder(view); manager= Playmanager.getinstance(); return holder; }2. onBindViewHolder()
这个方法主要用于适配渲染数据到View中。方法提供给你了一viewHolder而不是原来的convertView。
1.将要加载数据都放入到
holder.tv1.setText(list.get(position).getSongname()); holder.tv2.setText(list.get(position).getSingername()); Picasso.with(context) .load(list.get(position).getAlbumpic_big()) .error(R.mipmap.ic_launcher) .placeholder(R.drawable.dibu8) .into(holder.IV);
2.获取每一个子条目并设置监听View view=holder.itemView;
view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context,list.get(position).getSongname(),Toast.LENGTH_LONG).show(); manager.cutmusic(list.get(position).getUrl()); if(listen!=null) { listen.onitemclick(v, position); } } }); }
@Override public void onBindViewHolder(ViewHolder holder, final int position) { Log.e("msg","22222222222222222222"); holder.tv1.setText(list.get(position).getSongname()); holder.tv2.setText(list.get(position).getSingername()); Picasso.with(context) .load(list.get(position).getAlbumpic_big()) .error(R.mipmap.ic_launcher) .placeholder(R.drawable.dibu8) .into(holder.IV); View view=holder.itemView; view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context,list.get(position).getSongname(),Toast.LENGTH_LONG).show(); manager.cutmusic(list.get(position).getUrl()); if(listen!=null) { listen.onitemclick(v, position); } } }); }3. getItemCount()
这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。接下来通过几个小的实例帮助大家更深入的了解RecyclerView的用法。
@Override public int getItemCount() { Log.e("msg","3333333333333333333333"); return list.size(); }4. // 定义内部类继承ViewHolder
class ViewHolder extends RecyclerView.ViewHolder { TextView tv1,tv2; private ImageView IV; public ViewHolder(View itemView) { super(itemView); // tv = (TextView)itemView.findViewById(R.id.recycleitem); // IV=(ImageView)itemView.findViewById(R.id.imageView10); tv1=itemView.findViewById(R.id.textView4song); tv2=itemView.findViewById(R.id.textViewname); IV=itemView.findViewById(R.id.imageView5); } }
5.定义一个接口与activty进行通信。
view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context,list.get(position).getSongname(),Toast.LENGTH_LONG).show(); manager.cutmusic(list.get(position).getUrl()); if(listen!=null) { listen.onitemclick(v, position); } } });
public interface Onitemlisten { void onitemclick(View view, int position); } Onitemlisten listen; public void SetOnItemclick(Onitemlisten listen) { this.listen=listen; }这是在fragment中进行回调接口的核心代码,1.获取一个自己fragmnet绑定的actvity,然后调用了一个setplay方法,这是为了使播放键能跟上activty= (PlayerActivity) getActivity();
Log.e("msg","44444444444444444444444"); rec.SetOnItemclick(new recycleadapter.Onitemlisten() { @Override public void onitemclick(View view, int position) { Toast.makeText(view.getContext(), list1.get(position).getUrl()+"", Toast.LENGTH_SHORT).show(); activty.setpaly(); } });6.定义一个方法传递数据public void setdata(ArrayList<josntop.ShowapiResBodyBean.PagebeanBean.SonglistBean> list) { this.list=list; notifyDataSetChanged(); }
//这个是适配器的代码
public class recycleadapter extends RecyclerView.Adapter<recycleadapter.ViewHolder>{ private ArrayList<josntop.ShowapiResBodyBean.PagebeanBean.SonglistBean> list=new ArrayList<josntop.ShowapiResBodyBean.PagebeanBean.SonglistBean>(); private LayoutInflater inflater; private Context context; int a; private Playmanager manager; public void setdata(ArrayList<josntop.ShowapiResBodyBean.PagebeanBean.SonglistBean> list) { this.list=list; notifyDataSetChanged(); } public recycleadapter(int a) { this.a=a; } public recycleadapter() { } public void delete(int position) { list.remove(position); notifyItemRemoved(position); } @Override public int getItemViewType(int position) { return super.getItemViewType(position); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Log.e("msg","11111111111111111"); context=parent.getContext(); View view=inflater.from(parent.getContext()).inflate(R.layout.listitem,null); ViewHolder holder= new ViewHolder(view); manager= Playmanager.getinstance(); return holder; } @Override public void onBindViewHolder(ViewHolder holder, final int position) { Log.e("msg","22222222222222222222"); holder.tv1.setText(list.get(position).getSongname()); holder.tv2.setText(list.get(position).getSingername()); Picasso.with(context) .load(list.get(position).getAlbumpic_big()) .error(R.mipmap.ic_launcher) .placeholder(R.drawable.dibu8) .into(holder.IV); View view=holder.itemView; view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context,list.get(position).getSongname(),Toast.LENGTH_LONG).show(); manager.cutmusic(list.get(position).getUrl()); if(listen!=null) { listen.onitemclick(v, position); } } }); } @Override public int getItemCount() { Log.e("msg","3333333333333333333333"); return list.size(); } class ViewHolder extends RecyclerView.ViewHolder { TextView tv1,tv2; private ImageView IV; public ViewHolder(View itemView) { super(itemView); // tv = (TextView)itemView.findViewById(R.id.recycleitem); // IV=(ImageView)itemView.findViewById(R.id.imageView10); tv1=itemView.findViewById(R.id.textView4song); tv2=itemView.findViewById(R.id.textViewname); IV=itemView.findViewById(R.id.imageView5); } } public interface Onitemlisten { void onitemclick(View view, int position); } Onitemlisten listen; public void SetOnItemclick(Onitemlisten listen) { this.listen=listen; } }