【问题标题】:Multiple row of chips in chipgroup芯片组多排芯片
【发布时间】:2020-08-25 12:48:03
【问题描述】:

我正在从我的 API 中获取例如 25 个国家标签的列表,例如德国、英国、法国、意大利等... 我想要 2 行,每行 10 个 chips,如果我下次获取 30 个标签,我想要 3 行,每行 10 个 chips 等等...

到目前为止,我还没有找到任何可以让我这样做的东西。我快速浏览了Flexbox-Layout,但它似乎不符合我的需求,我目前有下面的代码,但我正在考虑用Recyclerview 做这样的逻辑

片段

viewModel.videoSelected.observe(viewLifecycleOwner, object : Observer<VideoPage> {
            override fun onChanged(videoPage: VideoPage?) {
                videoPage?.tags ?: return
                val chipGroup = binding.chipGroup
                val chipGroupInflater = LayoutInflater.from(chipGroup.context)
                val children = videoPage.tags.map { tagName ->
                    val chip = chipGroupInflater.inflate(R.layout.chip_video_tag, chipGroup, false) as Chip
                    chip.text = tagName
                    chip.tag = tagName
                    chip.setOnClickListener {
                        Toast.makeText(context, tagName, Toast.LENGTH_SHORT).show()
                    }

                    chip
                }

                for (chip in children) {
                    chipGroup.addView(chip)
                }
            }
        })

结果是一行中的 25 个筹码。我怎样才能使它在多行上分开?

【问题讨论】:

  • 不知道为什么您认为 Flexbox LayoutManager 不能满足您的需求,因为它可以让您精确控制何时开始新行。你有没有想过在芯片 11,21 等上使用layout_wrapBefore 标志
  • 这确实是我需要的,我一定是过得太快了。不使用库是否可以在本地做同样的事情?
  • 是的,可以不使用库,因为库使用标准的东西,您只需要实现自己的布局管理器或扩展现有的布局管理器,但使用 flexbox 会更容易

标签: android android-chips


【解决方案1】:

如评论所述,您可以在芯片 11、21 等上使用带有 layout_wrapBefore 标志的 Flexbox LayoutManager

或者,如果您重新格式化数据,也可以使用标准的 recyclerview。

要使用标准的 recyclerview,您需要将数据排列在 2D 数据结构中,这可以是 ArrayList 的 ArrayList 或带有 Arrays 或一组 POJO 类

在外部 Arraylist 中将是行,而在内部 Arraylist 中,您将拥有要在行中显示的项目。

所以 RecyclerView 项目只是一个水平线性布局来产生行,你从内部 ArrayList 添加你的芯片

使用生成的二维结构的示例

主活动

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private RAdapter adapter;
    private ArrayList<ArrayList<String>> rowsArrayList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = (RecyclerView) findViewById(R.id.recycler);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);

        rowsArrayList = new ArrayList<>();
        for (int i = 1; i <= 3; i++) {
            ArrayList<String> row = new ArrayList<>();
            for (int j = 1; j <= 10; j++) {
                row.add(String.valueOf(j));
            }
            rowsArrayList.add(row);
        }

        adapter = new RAdapter(this, rowsArrayList);
        recyclerView.setAdapter(adapter);
    }
}

R适配器

public class RAdapter extends RecyclerView.Adapter<RAdapter.RHolder>{

    class RHolder extends RecyclerView.ViewHolder {
        private LinearLayout line;

        public RHolder(View itemView) {
            super(itemView);
            line = itemView.findViewById(R.id.line);
        }
    }

    private Context context;
    private ArrayList<ArrayList<String>> rowsArrayList;

    public RAdapter(Context context, ArrayList<ArrayList<String>> rowsArrayList) {
        this.context = context;
        this.rowsArrayList = rowsArrayList;
    }

    @Override
    public RHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout, parent, false);
        return new RHolder(view);
    }

    @Override
    public void onBindViewHolder(RHolder holder, int position) {
        // Because we might be recycling the LinearLayout that might have had chips added to it already
        holder.line.removeAllViews();
        ArrayList<String> row = rowsArrayList.get(position);
        for (String text: row) {
            Chip chip = new Chip(context);
            chip.setText(text);
            holder.line.addView(chip);
        }
    }

    @Override
    public int getItemCount() {
        return rowsArrayList.size();
    }

}

row_layout.xml

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

</LinearLayout>

这会产生

更新:
再多一点数学就可以做到,而无需重新排列数据

显示 25 个项目以涵盖不完整的行用例

主活动

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private RAdapter adapter;
    private ArrayList<String> itemsArrayList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recyclerView = (RecyclerView) findViewById(R.id.recycler);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);

        itemsArrayList = new ArrayList<>();
        for (int i = 1; i <= 25; i++) {
            itemsArrayList.add(String.valueOf(i));
        }

        adapter = new RAdapter(this, itemsArrayList);
        recyclerView.setAdapter(adapter);
    }
}

R适配器

public class RAdapter extends RecyclerView.Adapter<RAdapter.RHolder>{

    class RHolder extends RecyclerView.ViewHolder {
        private LinearLayout line;

        public RHolder(View itemView) {
            super(itemView);
            line = itemView.findViewById(R.id.line);
        }
    }

    private Context context;
    private ArrayList<String> itemsArrayList;
    private int itemsPerRow = 10;

    public RAdapter(Context context, ArrayList<String> itemsArrayList) {
        this.context = context;
        this.itemsArrayList = itemsArrayList;
    }

    @Override
    public RHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout, parent, false);
        return new RHolder(view);
    }

    @Override
    public void onBindViewHolder(RHolder holder, int position) {
        // Because we might be recycling the LinearLayout that might have had chips added to it already
        holder.line.removeAllViews();
        int adjustedPosition = position + 1;
        int rangeEnd = Math.min(itemsArrayList.size(), adjustedPosition * itemsPerRow);
        int rangeStart = Math.max((position * itemsPerRow) + 1, rangeEnd - itemsPerRow);
        for (int i = rangeStart; i <= rangeEnd; i++) {
            int arrayPositionAdjusted = i - 1;
            Chip chip = new Chip(context);
            chip.setText(itemsArrayList.get(arrayPositionAdjusted));
            holder.line.addView(chip);
        }
    }

    @Override
    public int getItemCount() {
        return return (int) Math.ceil(itemsArrayList.size()/ (double) itemsPerRow);
    }

}

制作

【讨论】:

    【解决方案2】:

    我还设法通过BindingAdapter 以更简单的方式做到这一点:

     <androidx.recyclerview.widget.RecyclerView
                        app:listVideoTagChip="@{viewModel.videoSelected.tags}"
                        android:id="@+id/rv_video_chips"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
                        android:orientation="horizontal"
                        tools:listitem="@layout/chip_video_tag"/>
    
    private const val TAG_PER_ROW = 10
    
    @BindingAdapter("listVideoTagChip")
    fun RecyclerView.bindRecyclerView(data: List<String>?) {
        val adapter: VideoTagAdapter = this.adapter as VideoTagAdapter
        (layoutManager as StaggeredGridLayoutManager).spanCount =
            data?.size?.let {
                ceil(it.toDouble().div(TAG_PER_ROW)).toInt()
            } ?: 1
        adapter.submitList(data)
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-02
      • 2019-09-11
      • 1970-01-01
      • 1970-01-01
      • 2018-12-14
      • 2019-05-23
      • 1970-01-01
      • 1970-01-01
      • 2020-11-01
      相关资源
      最近更新 更多