Android — 使用recyclerview+FlexboxLayoutManager实现Tag标签

如图实现下面流式的tag标签。我们用recyclerview+flexboxLayoutManager来实现。

重点:

FlexboxLayoutManager layoutManager =new FlexboxLayoutManager(this);

rv.setLayoutManager(layoutManager);

 1.首先我们引入依赖。在build.gradle文件中。

  implementation 'com.google.android.flexbox:flexbox:3.0.0'

 2.写布局。使用Recyclerview.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:itemCount="10"
      />

</androidx.constraintlayout.widget.ConstraintLayout>

3.我们写一个简单的adapter,给recyclerview设置adapter. 由于item的布局很简单。里面只有一个textview。这里就省略。。。

public class FlexboxAdapter extends RecyclerView.Adapter<FlexboxAdapter.FlexboxAdapterHolder> {
    Context mContext;
    private List<String> mStringArrayList;
    public FlexboxAdapter(Context context,List<String> list) {
        this.mContext = context;
        this.mStringArrayList= list;
    }
    @Override
    public FlexboxAdapterHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false);
        return new FlexboxAdapterHolder(view);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @SuppressLint("ResourceAsColor")
    @Override
    public void onBindViewHolder(@NonNull FlexboxAdapterHolder holder, final int position) {
        holder.tvTitle.setText(mStringArrayList.get(position));

    }

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

    public class FlexboxAdapterHolder extends RecyclerView.ViewHolder {
        private final TextView tvTitle;

        public FlexboxAdapterHolder(View itemView) {
            super(itemView);
            tvTitle = itemView.findViewById(R.id.tvTitle);
        }
    }
}

4.在我们的MainActivity中,找到recyclerview。然后给recyclerview设置LayoutManager是FlexboxLayoutManager(重点),然后设置相应的adapter. 代码如下。

public class MainActivity extends AppCompatActivity {

    private ArrayList<String> dataList =new ArrayList();
    private ArrayList<Integer> colorList = new ArrayList();
    private RecyclerView rv;
    private String[] arr= {"aaaaaaaa.jpg","巴拉巴.jpg","我的下朋友企业.jpg","新中.jpg","我的好朋友是不同的风格类型哦哦哦哦哦","开心","测试tag标签"};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rv = findViewById(R.id.rv);
        //将正常的manager替换为FlexboxLayoutManager
        FlexboxLayoutManager layoutManager =new FlexboxLayoutManager(this);
        layoutManager.setFlexDirection(FlexDirection.ROW);//设置水平方向。也可以设置垂直方向
        // layoutManager.setJustifyContent(JustifyContent.FLEX_END);
        // layoutManager.setAlignItems(AlignItems.CENTER);
        rv.setLayoutManager(layoutManager);

        ArrayList<String> list = new ArrayList<>();
        for(int i=0;i<arr.length;i++){
            list.add(arr[i]);
        }
        FlexboxAdapter adapter =new FlexboxAdapter(this,list);
        rv.setAdapter(adapter);

    }
}

补充:layoutManager.setFlexDirection(FlexDirection.ROW) ;//设置水平方向。从左到右
FlexDirection.COLUMN //垂直方向,从上到下
FlexDirection.ROW_REVERSE //水平方向,从右到左
FlexDirection.COLUMN_REVERSE //垂直方向,从下到上

layoutManager.setFlexWrap(FlexWrap.WRAP); //是否换行FlexWrap.NOWRAP不换行 FlexWrap.WRAP换行
layoutManager.setJustifyContent(JustifyContent.FLEX_END); //项目在主轴上对齐方式,例如上面定义水平方向,就是水平方向对齐方式
layoutManager.setAlignItems(AlignItems.CENTER);//项目在交叉口对齐方式,因为上面定义水平方向,则为在垂直方向对齐方式
想了解更多属性含义可以参考以下文章

flex布局总结_棒怡情的专栏-CSDN博客

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是完整的实现代码: 1. 在布局文件中添加 RecyclerView 和字母索引条: ```xml <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.example.indexbar.IndexBar android:id="@+id/index_bar" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentEnd="true" android:layout_marginEnd="10dp" android:background="@android:color/transparent" app:indexBarTextColor="@color/colorPrimary" app:indexBarTextSize="12sp" /> ``` 2. 在 Activity 或 Fragment 中,初始化 RecyclerView 和 IndexBar: ```java import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import me.yokeyword.indexablerv.IndexableAdapter; import me.yokeyword.indexablerv.IndexableLayout; import me.yokeyword.indexablerv.SimpleHeaderAdapter; import me.yokeyword.indexablerv.SimpleIndexableAdapter; import me.yokeyword.indexablerv.SimpleLayoutManager; public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private IndexBar mIndexBar; private List<AppInfo> mDatas = new ArrayList<>(); private List<IndexableEntity<AppInfo>> mIndexDatas = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecyclerView = findViewById(R.id.recycler_view); mIndexBar = findViewById(R.id.index_bar); // 初始化 RecyclerView 的布局管理器、适配器和数据源 mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mDatas = getData(); mIndexDatas = getIndexDatas(mDatas); mRecyclerView.setAdapter(new SimpleAdapter(this, R.layout.item_app, mDatas)); mRecyclerView.addItemDecoration(new SimpleItemDecoration(this)); mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // 根据 RecyclerView 的滚动位置更新字母索引条的选中状态 int position = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); mIndexBar.setSelectedIndex(mIndexDatas.indexOf(mDatas.get(position))); } }); // 初始化字母索引条的监听器 mIndexBar.setOnTouchLetterChangeListenner(new IndexBar.OnTouchLetterChangeListenner() { @Override public void onTouchLetterChange(String letter) { // 根据字母索引条的触摸事件,滚动 RecyclerView 到相应位置 for (int i = 0; i < mDatas.size(); i++) { if (TextUtils.equals(letter, mDatas.get(i).getSortLetters())) { ((LinearLayoutManager) mRecyclerView.getLayoutManager()) .scrollToPositionWithOffset(i, 0); return; } } } }); // 初始化字母索引条的数据源,并设置到 IndexBar 中 List<String> indexList = getIndexList(mIndexDatas); mIndexBar.setIndexList(indexList); } // 获取应用列表数据源 private List<AppInfo> getData() { List<AppInfo> list = new ArrayList<>(); PackageManager pm = getPackageManager(); List<ApplicationInfo> apps = pm.getInstalledApplications(0); for (ApplicationInfo app : apps) { if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { String name = app.loadLabel(pm).toString(); String packageName = app.packageName; list.add(new AppInfo(name, packageName)); } } Collections.sort(list, new Comparator<AppInfo>() { @Override public int compare(AppInfo o1, AppInfo o2) { return o1.getSortLetters().compareTo(o2.getSortLetters()); } }); return list; } // 将应用列表数据源转换成 IndexableEntity 数据源 private List<IndexableEntity<AppInfo>> getIndexDatas(List<AppInfo> list) { List<IndexableEntity<AppInfo>> indexList = new ArrayList<>(); for (AppInfo app : list) { String pinyin = HanziToPinyin.getPinYin(app.getName()); if (!TextUtils.isEmpty(pinyin)) { app.setPinyin(pinyin); String sortLetters = pinyin.substring(0, 1).toUpperCase(); if (sortLetters.matches("[A-Z]")) { app.setSortLetters(sortLetters); indexList.add(new IndexEntity<>(app)); } else { app.setSortLetters("#"); indexList.add(new IndexEntity<>(app)); } } else { app.setSortLetters("#"); indexList.add(new IndexEntity<>(app)); } } return indexList; } // 获取字母索引条的数据源 private List<String> getIndexList(List<IndexableEntity<AppInfo>> list) { List<String> indexList = new ArrayList<>(); for (IndexableEntity<AppInfo> entity : list) { indexList.add(entity.getFieldIndexBy()); } return indexList; } // IndexableAdapter 适配器 public static class SimpleAdapter extends IndexableAdapter<AppInfo> { private int mLayoutRes; private LayoutInflater mInflater; public SimpleAdapter(Context context, int layoutRes, List<AppInfo> datas) { super(datas); mLayoutRes = layoutRes; mInflater = LayoutInflater.from(context); } @Override public RecyclerView.ViewHolder onCreateTitleViewHolder(ViewGroup parent) { View view = mInflater.inflate(R.layout.item_index_title, parent, false); return new TitleViewHolder(view); } @Override public RecyclerView.ViewHolder onCreateContentViewHolder(ViewGroup parent) { View view = mInflater.inflate(mLayoutRes, parent, false); return new ContentViewHolder(view); } @Override public void onBindTitleViewHolder(RecyclerView.ViewHolder holder, String indexTitle) { TitleViewHolder viewHolder = (TitleViewHolder) holder; viewHolder.tvTitle.setText(indexTitle); } @Override public void onBindContentViewHolder(RecyclerView.ViewHolder holder, AppInfo item) { ContentViewHolder viewHolder = (ContentViewHolder) holder; viewHolder.tvName.setText(item.getName()); viewHolder.tvPackageName.setText(item.getPackageName()); } private static class TitleViewHolder extends RecyclerView.ViewHolder { TextView tvTitle; TitleViewHolder(View itemView) { super(itemView); tvTitle = itemView.findViewById(R.id.tv_title); } } private static class ContentViewHolder extends RecyclerView.ViewHolder { TextView tvName; TextView tvPackageName; ContentViewHolder(View itemView) { super(itemView); tvName = itemView.findViewById(R.id.tv_name); tvPackageName = itemView.findViewById(R.id.tv_package_name); } } } // IndexableEntity 实体类 public static class IndexEntity<T> implements IndexableEntity { private T data; public IndexEntity(T data) { this.data = data; } @Override public String getFieldIndexBy() { return ((AppInfo) data).getSortLetters(); } @Override public void setFieldIndexBy(String indexField) { ((AppInfo) data).setSortLetters(indexField); } @Override public void setFieldPinyinIndexBy(String pinyin) { ((AppInfo) data).setPinyin(pinyin); } public T getData() { return data; } } // AppInfo 实体类 public static class AppInfo { private String name; private String packageName; private String pinyin; private String sortLetters; public AppInfo(String name, String packageName) { this.name = name; this.packageName = packageName; } public String getName() { return name; } public String getPackageName() { return packageName; } public String getPinyin() { return pinyin; } public void setPinyin(String pinyin) { this.pinyin = pinyin; } public String getSortLetters() { return sortLetters; } public void setSortLetters(String sortLetters) { this.sortLetters = sortLetters; } } // HanziToPinyin 汉字转拼音工具类 public static class HanziToPinyin { private static final String TAG = "HanziToPinyin"; public static String getPinYin(String input) { StringBuilder sb = new StringBuilder(); char[] inputArray = input.toCharArray(); for (char c : inputArray) { String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c); if (pinyinArray != null && pinyinArray.length > 0) { sb.append(pinyinArray[0]); } } return sb.toString(); } } } ``` 其中,IndexBar 和 SimpleItemDecoration 可以在 Github 上的 IndexBar 项目中找到。具体使用方式可以参考该项目的 README.md 文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值