欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android RecyclerView线性布局详解(1)

程序员文章站 2023-12-18 09:33:34
recyclerview是android 5.0新增的控件,在android-support-v7下面。官方文档对recycleview介绍很简洁到位,如下: a fle...

recyclerview是android 5.0新增的控件,在android-support-v7下面。官方文档对recycleview介绍很简洁到位,如下:

a flexible view for providing a limited window into a large data set.
大概意思就是说:在有限大小的窗口里显示大量数据的一个灵活的view。

下面是reccleview继承图:

Android RecyclerView线性布局详解(1)

看到这里我们自然想到了与之类似的控件listview,recyclerview和listview都是在有限的屏幕区域里维护少量的view来进行显示大量的数据,其实recyclerview是listview的升级版,功能更加强大,更加灵活,扩展性更强,google建议使用recycleview替代listview。

下面是recycleview结构图:

Android RecyclerView线性布局详解(1)

recycleview主要包括以下几个部件:

1. recyclerview.adapter

数据和视图的分离设计是程序解耦和可维护的重要指标,recycleview作为展示大量数据的view肯定是遵循这个设计的,listview也不例外。通过继承recycleview.adapter即可轻松实现自己的adapter,主要重写recycleview.adapter的下面三个方法即可实现:

public myrecycleviewadapter.myviewholder oncreateviewholder(viewgroup parent, int viewtype) 
public void onbindviewholder(myrecycleviewadapter.myviewholder holder, int position)
public int getitemcount() 

上面myrecycleviewadapter是我自己定义的viewholder

2. viewholder

viewholder用来保存列表中item view引用的类,这样做的目的是重用item视图,从而提高性能。
在listview中,viewholder不是listview自带的,是需要自己定义的,当然你也可以不使用viewholder,这样的后果就是listview每次调用getview()方法的时候都会调用findviewbyid()方法,要知道findviewbyid()性能很差,它通过递归的方式去从view树中找特定的子view的,最终往往带来很差的性能体验,所以使用viewholder也成了优化listview最重要的手段。
在recyclerview中,android内置了recyclerview.viewholder,这意味着viewholder使用成了必须。

3. 分割线 recycleview.itemdecoration

listview添加分割线很简单,只需在listview的xml中配置”divider”属性即可,如:

android:dividerheight="2dp"
android:divider="@color/red"

但recycleview添加分割线是比较麻烦的,并且默认是不带分割线的。但实际开发中一般都需要分割线,使用recycleview.itemdecoration为recycleview添加分割线

4. 布局管理器 layoutmanager

recycleview支持多种布局模式:

1、linearlayoutmanager
线性布局管理器,支持水平布局和垂直布局两种
2、gridlayoutmanager
网格布局管理器
3、staggerdgridlayoutmanager
错列的网格布局管理器,可以实现瀑布流列表

recycleview使用时和listview很类似,直接看一个简单的例子,分别展示一个垂直方向和水平方向上的列表,并且都支持使用颜色和图片做分割线,效果图如下:

Android RecyclerView线性布局详解(1)

Android RecyclerView线性布局详解(1)

1. mainactivity

package com.cjl.recycleviewtest;
...
public class mainactivity extends appcompatactivity {

 private verticalfragment mverticalfragment;
 private horizontalfragment mhorizontalfragment;

 @override
 protected void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_main);
 //垂直
 mverticalfragment = new verticalfragment();
 //水平
 mhorizontalfragment = new horizontalfragment();
 //默认为设置垂直
 getfragmentmanager().begintransaction().replace(r.id.activity_main, mverticalfragment).commit();
 }

 @override
 public boolean oncreateoptionsmenu(menu menu) {
 menuinflater inflater = getmenuinflater();
 inflater.inflate(r.menu.menu_recycleview, menu);
 return super.oncreateoptionsmenu(menu);
 }

 @override
 public boolean onoptionsitemselected(menuitem item) {
 int id = item.getitemid();
 switch (id) {
  //垂直方向
  case r.id.vertical:
  verticalfragment mverticalfragment = new verticalfragment();
  getfragmentmanager().begintransaction().replace(r.id.activity_main, mverticalfragment).commit();
  break;
  //水平方向
  case r.id.horizontal:
 getfragmentmanager().begintransaction().replace(r.id.activity_main, mhorizontalfragment).commit();
  break;
 }
 return super.onoptionsitemselected(item);
 }
}

mainactivity布局文件 r.layout.activity_main

<?xml version="1.0" encoding="utf-8"?>
<framelayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
</framelayout>

2. 垂直方向上 verticalfragment

public class verticalfragment extends fragment implements view.onclicklistener{

 private recyclerview mrecycleviewdrawable;
 private recyclerview mrecycleviewcolor;
 private linearlayoutmanager mmanagercolor;
 private linearlayoutmanager mmanagerdrawable;
 private list<string> mdata;
 private button mdrawable;
 private button mcolor;
 private myrecycleviewadapter mrecycleviewadapter;

 @nullable
 @override
 public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) {
 view view = inflater.inflate(r.layout.fragment_vertical_layout, container, false);
 mrecycleviewdrawable = (recyclerview) view.findviewbyid(r.id.recycleview_drawable);
 mrecycleviewcolor = (recyclerview) view.findviewbyid(r.id.recycleview_color);

 mdrawable = (button) view.findviewbyid(r.id.btn_drawable);
 mdrawable.setonclicklistener(this);
 mcolor = (button) view.findviewbyid(r.id.btn_color);
 mcolor.setonclicklistener(this);
 //1. 颜色分割线
 mmanagercolor = new linearlayoutmanager(getactivity());
 mmanagercolor.setorientation(linearlayoutmanager.vertical);
 mrecycleviewcolor.setlayoutmanager(mmanagercolor);
 //设置颜色分割线
 mrecycleviewcolor.additemdecoration(new lineardivider(getactivity(), linearlayoutmanager.vertical, 10, this.getresources().getcolor(r.color.coloraccent)));

 //2. 图片分割线
 mmanagerdrawable = new linearlayoutmanager(getactivity());
 mmanagerdrawable.setorientation(linearlayoutmanager.vertical);
 mrecycleviewdrawable.setlayoutmanager(mmanagerdrawable);
 //设置图片分割线
 drawable drawable = contextcompat.getdrawable(getactivity(), r.mipmap.divider);
 mrecycleviewdrawable.additemdecoration(new lineardivider(getactivity(), linearlayoutmanager.vertical, 20, drawable));

 mdata = new arraylist<string>();
 initdata(mdata);
 //自定义adapter
 mrecycleviewadapter = new myrecycleviewadapter(getactivity(), r.layout.item_vertical_recycleview, mdata);
 //设置adapter
 mrecycleviewcolor.setadapter(mrecycleviewadapter);
 mrecycleviewdrawable.setadapter(mrecycleviewadapter);
 return view;
 }

 private void initdata(list<string> datalist) {
 for (int i = 0; i < 30; i++) {
  datalist.add("item" + i);
 }
 }

 @override
 public void onclick(view view) {
 int id = view.getid();
 switch (id){
  case r.id.btn_drawable:
  mrecycleviewcolor.setvisibility(view.invisible);
  mrecycleviewdrawable.setvisibility(view.visible);
  break;

  case r.id.btn_color:
  mrecycleviewcolor.setvisibility(view.visible);
  mrecycleviewdrawable.setvisibility(view.invisible);
  break;
 }
 }
}

verticalfragment 的布局文件 r.layout.fragment_vertical_layout

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <android.support.v7.widget.recyclerview
 android:id="@+id/recycleview_drawable"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_marginbottom="60dp"/>

 <android.support.v7.widget.recyclerview
 android:id="@+id/recycleview_color"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_marginbottom="60dp"
 android:visibility="invisible"/>

 <linearlayout
 android:id="@+id/lilayout"
 android:orientation="horizontal"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:weightsum="2"
 android:layout_alignparentbottom="true">

 <button
  android:id="@+id/btn_drawable"
  android:layout_width="wrap_content"
  android:layout_height="50dp"
  android:text="图片分割线"
  android:gravity="center"
  android:layout_weight="1"
  android:background="@color/colorprimary"/>

 <button
  android:id="@+id/btn_color"
  android:layout_width="wrap_content"
  android:layout_height="50dp"
  android:text="颜色分割线"
  android:gravity="center"
  android:layout_weight="1"
  android:background="@color/mytv"/>
 </linearlayout>
</relativelayout>

3. 直接继承recyclerview.adapter

public class myrecycleviewadapter extends recyclerview.adapter<myrecycleviewadapter.myviewholder> {

 private layoutinflater mlayoutinflater;
 private list<string> mdatalist;
 private int mitemlayout;

 public myrecycleviewadapter(context context, int itemlayout, list<string> datalist) {
 mlayoutinflater = layoutinflater.from(context);
 mitemlayout = itemlayout;
 mdatalist = datalist;
 }

 @override
 public myrecycleviewadapter.myviewholder oncreateviewholder(viewgroup parent, int viewtype) {
 return new myviewholder(mlayoutinflater.inflate(mitemlayout, parent, false));
 }

 @override
 public void onbindviewholder(myrecycleviewadapter.myviewholder holder, int position) {
 holder.mtextview.settext(mdatalist.get(position));
 }

 @override
 public int getitemcount() {
 return mdatalist.size();
 }

 class myviewholder extends recyclerview.viewholder {

 private textview mtextview;
 public myviewholder(view itemview) {
  super(itemview);
  mtextview = (textview) itemview.findviewbyid(r.id.tv);
 }
 }
}

item布局文件 item_vertical_recycleview.xml

<?xml version="1.0" encoding="utf-8"?>
<framelayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">

 <textview
 android:id="@+id/tv"
 android:gravity="center"
 android:layout_width="match_parent"
 android:layout_height="60dp"/>

</framelayout>

4. 分割线 recyclerview.itemdecoration

public class lineardivider extends recyclerview.itemdecoration {

 private drawable mdividerdarwable;
 private int morientation;
 private int mdividerhight = 1;
 private paint mcolorpaint;

 public final int[] atrrs = new int[]{
  android.r.attr.listdivider
 };

 /*
 orientation 方向
 */
 public lineardivider(context context, int orientation) {
 final typedarray ta = context.obtainstyledattributes(atrrs);
 this.mdividerdarwable = ta.getdrawable(0);
 ta.recycle();
 setorientation(orientation);
 }

 /*
 int orientation 方向
 int dividerhight 分割线的线宽
 drawable dividerdrawable 充当分割线的图片
 */
 public lineardivider(context context, int orientation, int dividerhight, drawable dividerdrawable) {
 this(context, orientation);
 mdividerhight = dividerhight;
 mdividerdarwable = dividerdrawable;
 }

 /*
 int orientation 方向
 int dividerhight 分割线的线宽
 int dividercolor 分割线的颜色
 */
 public lineardivider(context context, int orientation, int dividerhight, int dividercolor) {
 this(context, orientation);
 mdividerhight = dividerhight;
 mcolorpaint = new paint();
 mcolorpaint.setcolor(dividercolor);
 }

 public void setorientation(int orientation) {
 if (orientation != linearlayoutmanager.horizontal && orientation != linearlayoutmanager.vertical) {
  throw new illegalargumentexception("方向参数错误!");
 }
 morientation = orientation;
 }

 @override
 public void ondraw(canvas c, recyclerview parent, recyclerview.state state) {
 super.ondraw(c, parent, state);
 if (morientation == linearlayoutmanager.horizontal) {
  drawhorizontaldivider(c, parent);
 } else {
  drawvirticaldivider(c, parent);
 }
 }

 //画垂直分割线
 public void drawvirticaldivider(canvas c, recyclerview parent) {
 int left = parent.getpaddingleft();
 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;
  final int bottom = top + mdividerhight;
  if (mdividerdarwable != null) {
  mdividerdarwable.setbounds(left, top, right, bottom);
  mdividerdarwable.draw(c);
  }
  if (mcolorpaint != null) {
  c.drawrect(left, top, right, bottom, mcolorpaint);
  }
 }
 }

 //画水平分割线
 public void drawhorizontaldivider(canvas c, recyclerview parent) {
 int top = parent.getpaddingtop();
 int bottom = parent.getheight() - parent.getpaddingbottom();
 final int childcount = parent.getchildcount();
 for (int i = 0; i < childcount; i++) {
  final view child = parent.getchildat(i);
  recyclerview.layoutparams params = (recyclerview.layoutparams) child.getlayoutparams();
  final int left = child.getright() + params.rightmargin;
  final int right = left + mdividerhight;
  if (mdividerdarwable != null) {
  mdividerdarwable.setbounds(left, top, right, bottom);
  mdividerdarwable.draw(c);
  }
  if (mcolorpaint != null) {
  c.drawrect(left, top, right, bottom, mcolorpaint);
  }
 }
 }

 @override
 public void getitemoffsets(rect outrect, view view, recyclerview parent, recyclerview.state state) {
 super.getitemoffsets(outrect, view, parent, state);
 if (morientation == linearlayoutmanager.horizontal) {
  outrect.set(0, 0, 0, mdividerhight);
 } else {
  outrect.set(0, 0, mdividerhight, 0);
 }
 }
}


未完待续……

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: