android - RecyclerView 与 StaggeredGridLayoutManager : variable number of columns and vertically scrollable

标签 android android-recyclerview staggeredgridlayoutmanager

我想显示一个字符串列表,这个列表必须是垂直可滚动的,并且对于每一行都有可变数量的列,这个列将取决于字符串。所以它将是一个可垂直滚动的网格。
所以图形上我想实现这一点:
enter image description here

结果我得到的是一个可水平滚动的列表,有 3 行和许多列,而我想要的是相反的方式:不能水平滚动(很多列,取决于团队名称)但可以垂直滚动。

为了实现这一点,我在回收站 View 中添加了一个 StaggeredGridLayoutManager,其中包含 3 个跨度计数(这可能是错误的),并且 StaggeredGridLayoutManager.GAP_HANDLING_NONE 尽可能多地拥有列。

第一个问题是是否可以使用 StaggeredGridLayoutManager 实现这一目标?如果是,我该如何解决我的问题?欢迎任何建议或想法。

请注意,xml 中的项目具有最大宽度,然后省略

我所拥有的是以下内容:
item_team.xml

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

<data>

    <variable
        name="title"
        type="String" />

</data>

<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/margin_small"
    android:background="@drawable/club_background"
    android:padding="@dimen/margin_general">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:ellipsize="end"
        android:maxWidth="184dp"
        android:gravity="center"
        android:lines="1"
        android:text="@{title}"
        tools:text="Arsenal" />

</RelativeLayout>

团队适配器.java:
public class TeamAdapter extends ListAdapter<TeamItem, RecyclerView.ViewHolder> {
private LayoutInflater inflater;
private List<TeamItem> items = new ArrayList<>();

private static final DiffUtil.ItemCallback<TeamItem> ITEM_CALLBACK = new DiffUtil.ItemCallback<TeamItem>() {
    @Override
    public boolean areItemsTheSame(@NonNull TeamItem item1, @NonNull TeamItem item2) {
        return item1.hashCode() == item2.hashCode();
    }

    @Override
    public boolean areContentsTheSame(@NonNull TeamItem item1, @NonNull TeamItem item2) {
        return item1.id.equalsIgnoreCase(item2.id);
    }
};

private static final int VIEW_TYPE_TEAM = 0;

public TeamAdapter(Context context) {
    super(ITEM_CALLBACK);
    inflater = LayoutInflater.from(context);
}

public void setTeams(List<TeamItem> teams) {
    items = teams;
    notifyDataSetChanged();
}

public class TeamViewHolder extends RecyclerView.ViewHolder {

    private final ItemTeamBinding binding;

    TeamViewHolder(ItemTeamBinding binding) {
        super(binding.getRoot());
        this.binding = binding;
    }

    public void bind(TeamItem team) {
        binding.setTitle(team.name);
        binding.executePendingBindings();
    }
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    switch (viewType) {
        case VIEW_TYPE_TEAM:
            ItemTeamBinding itemTeamBinding = DataBindingUtil.inflate(inflater, R.layout.item_team, parent, false);
            return new TeamItemViewHolder(itemTeamBinding);
    }

    throw new RuntimeException("There are invalid view types in TeamAdapter!");
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, final int position) {
    switch (viewHolder.getItemViewType()) {
        case VIEW_TYPE_TEAM:
            ((TeamItemViewHolder) viewHolder).bind(items.get(position));
            break;
    }
}

@Override
public int getItemCount() {
    if (items != null && !items.isEmpty()) {
        return items.size();
    }

    return super.getItemCount();
}

@Override
public int getItemViewType(int position) {
    if (items != null && !items.isEmpty()) {
        return VIEW_TYPE_TEAM;
    }

    return super.getItemViewType(position);
  }
}

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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">

<data>

    <variable
        name="activity"
        type="com.ziniestro.base.activity.MainActivity" />

</data>

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/tlbMain"
            android:layout_width="match_parent"
            android:layout_height="?android:actionBarSize"
            app:contentInsetLeft="0dp"
            app:contentInsetStart="0dp"
            app:navigationIcon="@null">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/margin_large"
                android:paddingTop="@dimen/margin_large"
                android:paddingBottom="@dimen/margin_large"
                android:text="@string/main_title" />

        </androidx.appcompat.widget.Toolbar>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/margin_medium"
            android:layout_marginTop="@dimen/margin_small"
            android:layout_marginEnd="@dimen/margin_medium"
            android:layout_marginBottom="@dimen/margin_xlarge"
            android:background="@drawable/round_border_station_preference"
            android:orientation="vertical">

            <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <ImageView
                    android:id="@+id/imgMain"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentStart="true"
                    android:layout_alignParentTop="true"
                    android:layout_marginStart="@dimen/margin_medium"
                    android:layout_marginTop="@dimen/margin_medium"
                    android:layout_marginBottom="@dimen/margin_xlarge"
                    android:src="@drawable/ic_title" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentTop="true"
                    android:layout_marginStart="@dimen/margin_large"
                    android:layout_marginTop="@dimen/margin_xlarge"
                    android:layout_toEndOf="@+id/imgMain"
                    android:gravity="center|start"
                    android:text="@string/main_title" />

            </RelativeLayout>

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rcyMain"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layoutAnimation="@anim/layout_anim_scale"
                tools:listitem="@layout/item_team" />

        </LinearLayout>

    </LinearLayout>

</androidx.core.widget.NestedScrollView>

MainActivity.java
public class MainActivity extends AppCompatActivity {

private ActivityMainBinding binding;
public TeamAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.setActivity(this);
    binding.tlbMain.setTitle(Constants.EMPTY_STRING);

    final Drawable backIcon = ContextCompat.getDrawable(this, R.drawable.ic_arrow_back);
    backIcon.setColorFilter(ContextCompat.getColor(this, R.color.secondary) + 0xFF000000, PorterDuff.Mode.SRC_ATOP);
    binding.tlbMain.setNavigationIcon(backIcon);

    setSupportActionBar(binding.tlbMain);

    adapter = new TeamAdapter(this);

    if(MainApplication.getInstance().teamFeed.items !=null && !MainApplication.getInstance().teamFeed.items.isEmpty()) {
        adapter.setTeams(MainApplication.getInstance().teamFeed.items);
        StaggeredGridLayoutManager gridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.GAP_HANDLING_NONE);
        binding.rcyMain.setLayoutManager(gridLayoutManager);

        binding.rcyMain.setHasFixedSize(true);
        binding.rcyMain.setAdapter(adapter);
        binding.rcyMain.setNestedScrollingEnabled(false);
    }
}
}

最佳答案

我想你想要的是FlexboxLayoutManager https://github.com/google/flexbox-layout#flexboxlayoutmanager-within-recyclerviewWrap Vertical Recyclerview 中的选项。

包含您想要的字符串的“单元格”的大小可能会有所不同,如果它不能将单元格放入该行,它会将其包装到下一行。

关于android - RecyclerView 与 StaggeredGridLayoutManager : variable number of columns and vertically scrollable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59998188/

相关文章:

android - 以编程方式将 fragment 添加到 LinearLayout

android - RecyclerView notifyItemInserted 复制了之前条目的数据

Android 交错 Grdiv 全屏查看最后一个元素(如果独立)

android - 如何使用 StaggeredGridLayoutManager 确定 RecyclerView 中的 viewholder 是向左还是向右

java - AlarmManager setInexactRepeating、setWindow、setRepeating 方法在一周内从循环内调用时不会触发警报

java - 切换条件在 Android 中不起作用

java - Android 中的自定义进度条首选项问题

android - CardView 中的 ImageView 占满整个屏幕

android - 在 recyclerview 上/外部/顶部添加一个按钮

java - 根据项目位置动态更改 StaggeredGridLayout 的列跨度计数