经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Android RecycleView多种布局实现(工厂模式)
来源:cnblogs  作者:浮云Cloud  时间:2018/10/20 15:25:39  对本文有异议

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

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

 

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

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

 

2.然后是类图:

 

3.Adapter类:

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

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

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

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

4.ItemHolder抽象类:

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

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

5.LargeItemHolder类:

另外两个类似

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

6.Item接口:

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

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

另外两个类似

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

8.工厂类ItemHolderFactory:

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

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

9.ListActivity类:

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

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

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

  1. 1 <?xml version="1.0" encoding="utf-8"?>
  2. 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. 3 xmlns:tools="http://schemas.android.com/tools"
  4. 4 android:orientation="vertical"
  5. 5 android:layout_width="match_parent"
  6. 6 android:layout_height="wrap_content"
  7. 7 android:layout_margin="4dp"
  8. 8 android:background="#ffffff"
  9. 9 android:elevation="2dp">
  10. 10
  11. 11 <ImageView
  12. 12 android:contentDescription="@id/item_title"
  13. 13 android:id="@+id/item_image"
  14. 14 android:layout_width="match_parent"
  15. 15 android:layout_height="170dp"
  16. 16 android:scaleType="centerCrop"
  17. 17 tools:src="@drawable/img_7" />
  18. 18
  19. 19 <TextView
  20. 20 android:id="@+id/item_title"
  21. 21 android:layout_width="match_parent"
  22. 22 android:layout_height="wrap_content"
  23. 23 android:layout_marginTop="8dp"
  24. 24 android:paddingStart="8dp"
  25. 25 android:paddingEnd="8dp"
  26. 26 android:lines="1"
  27. 27 android:ellipsize="end"
  28. 28 android:textColor="#000000"
  29. 29 android:textSize="18sp"
  30. 30 tools:text="Item Title" />
  31. 31
  32. 32 <TextView
  33. 33 android:id="@+id/item_sub_title"
  34. 34 android:layout_width="match_parent"
  35. 35 android:layout_height="wrap_content"
  36. 36 android:layout_marginBottom="8dp"
  37. 37 android:paddingStart="8dp"
  38. 38 android:paddingEnd="8dp"
  39. 39 android:lines="1"
  40. 40 android:ellipsize="end"
  41. 41 android:textSize="14sp"
  42. 42 tools:text="Sub Title" />
  43. 43
  44. 44 </LinearLayout>

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号