zoukankan      html  css  js  c++  java
  • Android RecycleView多种布局实现(工厂模式)

    RecycleView是个很常用的控件,很多APP中都可以看到它的身影,同时它也是个很难用的控件,主要就难在多种布局的实现。

    在《第一行代码—Android》这本书里边有个RecycleView实现的聊天界面布局,左右两种布局写在了同一个文件中,如果是发送来的消息,就隐藏右侧布局,反之隐藏左侧布局,这种方式对于比较简单的、只有两种Item的界面是可行的,假如我们的Item有多种布局,那么这种方式就显得很笨重。对于多种布局,我们可以使用工厂模式来实现。

    Github:https://github.com/imcloudfloating/DesignApp

    1.首先看看效果(GIF一直上传失败,只好传JPG了):

    这里的LayoutManager使用GridLayoutManager,设置为6列,然后在Adapter类中根据不同的类型来设置所占列数,具体见Adapter类的setSpanCount方法。

    2.然后是类图:

    3.Adapter类:

    适配器的代码很短,设置数据和绑定View的代码都写在了ItemHolder的子类里面;

    List<Item>储存三种类型的Item数据,如果需要增加新的类型,只要实现Item接口就可以了;

    在onBindViewHolder方法中调用ItemHolder的setData()方法来设置数据;

     1 public class MultiListAdapter extends RecyclerView.Adapter<ItemHolder> {
     2 
     3     private List<Item> mDataList;
     4 
     5     public MultiListAdapter(List<Item> dataList) {
     6         mDataList = dataList;
     7     }
     8 
     9     @NonNull
    10     @Override
    11     public ItemHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) {
    12         return ItemHolderFactory.getItemHolder(viewGroup, type);
    13     }
    14 
    15     @Override
    16     public void onBindViewHolder(@NonNull ItemHolder viewHolder, int i) {
    17         //设置 Holder 数据
    18         viewHolder.setData(mDataList.get(i));
    19     }
    20 
    21     @Override
    22     public int getItemViewType(int position) {
    23         return mDataList.get(position).getType();
    24     }
    25 
    26     @Override
    27     public int getItemCount() {
    28         return mDataList.size();
    29     }
    30 
    31     public void setSpanCount(GridLayoutManager layoutManager) {
    32         layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    33             @Override
    34             public int getSpanSize(int i) {
    35                 int type = getItemViewType(i);
    36                 switch (type) {
    37                     default:
    38                     case ItemHolderFactory.ITEM_LARGE:
    39                         return 3;
    40                     case ItemHolderFactory.ITEM_SMALL:
    41                         return 2;
    42                     case ItemHolderFactory.ITEM_TITLE_BAR:
    43                         return 6;
    44                 }
    45             }
    46         });
    47     }
    48 }

    4.ItemHolder抽象类:

    setData方法用来设置Item布局的数据

    1 public abstract class ItemHolder extends RecyclerView.ViewHolder {
    2     public ItemHolder(View item) {
    3         super(item);
    4     }
    5 
    6     public abstract void setData(Item itemData);
    7 }

    5.LargeItemHolder类:

    另外两个类似

     1 public class LargeItemHolder extends ItemHolder {
     2 
     3     private ImageView mItemImage;
     4     private TextView mTitle;
     5     private TextView mSubTitle;
     6 
     7     public LargeItemHolder(View item) {
     8         super(item);
     9         mItemImage = item.findViewById(R.id.item_image);
    10         mTitle = item.findViewById(R.id.item_title);
    11         mSubTitle = item.findViewById(R.id.item_sub_title);
    12     }
    13 
    14     @Override
    15     public void setData(Item itemData) {
    16         ItemLarge item = (ItemLarge) itemData;
    17         mItemImage.setImageBitmap(item.getImage());
    18         mTitle.setText(item.getTitle());
    19         mSubTitle.setText(item.getSubTitle());
    20     }
    21 }

    6.Item接口:

    1 public interface Item {
    2     int getType();
    3 }

    7.ItemLarge类(一个图片、一个标题和一个副标题):

    另外两个类似

     1 public class ItemLarge implements Item {
     2 
     3     private Bitmap mImage;
     4     private String mTitle;
     5     private String mSubTitle;
     6 
     7     public ItemLarge(Bitmap bitmap, String title, String subTitle) {
     8         mImage = bitmap;
     9         mTitle = title;
    10         mSubTitle = subTitle;
    11     }
    12 
    13     public Bitmap getImage() {
    14         return mImage;
    15     }
    16 
    17     public String getTitle() {
    18         return mTitle;
    19     }
    20 
    21     public String getSubTitle() {
    22         return mSubTitle;
    23     }
    24 
    25     @Override
    26     public int getType() {
    27         return ItemHolderFactory.ITEM_LARGE;
    28     }
    29 }

    8.工厂类ItemHolderFactory:

    三个常量表示不同的布局类型,通过getItemHolder来创建ViewHolder。

     1 public class ItemHolderFactory {
     2 
     3     public static final int ITEM_LARGE = 0;
     4     public static final int ITEM_SMALL = 1;
     5     public static final int ITEM_TITLE_BAR = 2;
     6 
     7     @IntDef({
     8             ITEM_LARGE,
     9             ITEM_SMALL,
    10             ITEM_TITLE_BAR
    11     })
    12     @interface ItemType {}
    13 
    14     static ItemHolder getItemHolder(ViewGroup parent, @ItemType int type) {
    15         switch (type) {
    16             default:
    17             case ITEM_LARGE:
    18                 return new LargeItemHolder(LayoutInflater
    19                         .from(parent.getContext()).inflate(R.layout.item_large, parent, false));
    20             case ITEM_SMALL:
    21                 return new SmallItemHolder(LayoutInflater
    22                         .from(parent.getContext()).inflate(R.layout.item_small, parent, false));
    23             case ITEM_TITLE_BAR:
    24                 return new TitleBarItemHolder(LayoutInflater
    25                         .from(parent.getContext()).inflate(R.layout.item_title_bar, parent, false));
    26         }
    27     }
    28 }

    9.ListActivity类:

     1 public class ListActivity extends AppCompatActivity {
     2 
     3     List<Item> itemList = new ArrayList<>();
     4 
     5     @Override
     6     protected void onCreate(Bundle savedInstanceState) {
     7         super.onCreate(savedInstanceState);
     8         setContentView(R.layout.activity_list);
     9 
    10         initData();
    11 
    12         GridLayoutManager layoutManager = new GridLayoutManager(this, 6);
    13         MultiListAdapter adapter = new MultiListAdapter(itemList);
    14         adapter.setSpanCount(layoutManager);
    15 
    16         RecyclerView recyclerView = findViewById(R.id.recycle_view);
    17         recyclerView.setLayoutManager(layoutManager);
    18         recyclerView.setAdapter(adapter);
    19     }
    20 
    21     private void initData() {
    22         //添加数据
    23         itemList.add(new ItemTitleBar("Hot New", null));
    24         itemList.add(new ItemLarge(
    25                 BitmapFactory.decodeResource(getResources(), R.drawable.img_1),
    26                 "One More Light",
    27                 "Linkin Park"));
    28         itemList.add(new ItemLarge(
    29                 BitmapFactory.decodeResource(getResources(), R.drawable.img_2),
    30                 "Let Go ",
    31                 "Avril Lavigne"));
    32         itemList.add(new ItemTitleBar("Recommended", null));
    33         itemList.add(new ItemSmall(
    34                 BitmapFactory.decodeResource(getResources(), R.drawable.img_3),
    35                 "Bridge to Terabithia"));
    36         itemList.add(new ItemSmall(
    37                 BitmapFactory.decodeResource(getResources(), R.drawable.img_4),
    38                 "Life Is Beautiful"));
    39         itemList.add(new ItemSmall(
    40                 BitmapFactory.decodeResource(getResources(), R.drawable.img_5),
    41                 "A Violent Flame"));
    42         itemList.add(new ItemTitleBar("Top Rated", null));
    43         itemList.add(new ItemLarge(
    44                 BitmapFactory.decodeResource(getResources(), R.drawable.img_6),
    45                 "Furious 7: Original Motion Picture Soundtrack",
    46                 "Various Artists"));
    47         itemList.add(new ItemLarge(
    48                 BitmapFactory.decodeResource(getResources(), R.drawable.img_7),
    49                 "Halo 5: Guardians (Original Soundtrack)",
    50                 "Kazuma Jinnouchi"));
    51     }
    52 }

    10.布局文件(item_large.xml):

    layout_width用match_parent是为了Item在网格中居中,此处match_parent相当于宽度为Item所占的列数。

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     xmlns:tools="http://schemas.android.com/tools"
     4     android:orientation="vertical"
     5     android:layout_width="match_parent"
     6     android:layout_height="wrap_content"
     7     android:layout_margin="4dp"
     8     android:background="#ffffff"
     9     android:elevation="2dp">
    10 
    11     <ImageView
    12         android:contentDescription="@id/item_title"
    13         android:id="@+id/item_image"
    14         android:layout_width="match_parent"
    15         android:layout_height="170dp"
    16         android:scaleType="centerCrop"
    17         tools:src="@drawable/img_7" />
    18 
    19     <TextView
    20         android:id="@+id/item_title"
    21         android:layout_width="match_parent"
    22         android:layout_height="wrap_content"
    23         android:layout_marginTop="8dp"
    24         android:paddingStart="8dp"
    25         android:paddingEnd="8dp"
    26         android:lines="1"
    27         android:ellipsize="end"
    28         android:textColor="#000000"
    29         android:textSize="18sp"
    30         tools:text="Item Title" />
    31 
    32     <TextView
    33         android:id="@+id/item_sub_title"
    34         android:layout_width="match_parent"
    35         android:layout_height="wrap_content"
    36         android:layout_marginBottom="8dp"
    37         android:paddingStart="8dp"
    38         android:paddingEnd="8dp"
    39         android:lines="1"
    40         android:ellipsize="end"
    41         android:textSize="14sp"
    42         tools:text="Sub Title" />
    43 
    44 </LinearLayout>
  • 相关阅读:
    小G的城堡
    最大公约数与扩展欧几里得算法
    阶乘的逆元
    素数的判断
    快速幂
    重载高精度运算符
    Hello World!
    【JavaScript】7-13 日K蜡烛图 (15分)
    【JavaScript】7-12 两个数的简单计算器 (10分)
    【JavaScript】7-11 分段计算居民水费 (10分)
  • 原文地址:https://www.cnblogs.com/cloudfloating/p/9817251.html
Copyright © 2011-2022 走看看