我可以为 ViewHolder 创建一个没有 xml 布局的 recyclerview 吗?

Can I make a recyclerview without an xml layout for the ViewHolder?

我要在我的 android 应用程序中添加一个 RecyclerView。因此,就像我在回收站视图中看到的所有文档一样,我有一个 Adapter class,其中定义了一个 ViewHolder class。该代码如下所示(在 PointChangeAdapter.java 中)。

但是,我的代码和我见过的大多数教程之间有一处不同; 我没有为 ViewHolder 定义布局的 xml 文件。至少那是我正在努力工作的。

看来我不需要定义自定义布局,因为我的 RecyclerView 的元素只是 TextView。这可能可以通过 ListView 来完成,但我喜欢 RecyclerView 的灵​​活性,并且也只是想了解是否有可能让我在这里工作。也就是说, 回收站,没有 xml 布局。

为了弥补 xml 布局的不足,我修改了 Adapter 的 onCreateViewHolder 方法。 一个典型的例子会使用布局充气器,例如

    @Override
    public PointChangeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final TextView textView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.my_viewholder_xml_layout, parent, false);
        return new PointChangeViewHolder(textView);
    }

我有

    @Override
    public PointChangeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final TextView textView = new TextView(parent.getContext());
        parent.addView(textView);
        return new PointChangeViewHolder(textView);
    }

也就是说,不是在 xml 布局上调用 inflate 并指定 RecyclerView 父级, 我创建了一个新的 TextView 并通过 addView.

将其直接添加到 RecyclerView 父级

唯一的问题是这不起作用。

它给我一个“ViewHolder views must not be attached when created”错误:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.mherzl.pointcounter, PID: 5253 java.lang.IllegalStateException: ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot) at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7080)

...

我也试过完全删除 parent.addView(textView); 行, 使我的示例几乎与 this 示例相同, 就像我正在尝试做的那样,它没有指定 xml 布局。 当我 运行 我的代码没有 addView 行时,我没有得到错误, 但在那种情况下,文本仍然不会出现在回收站视图中。 所以也出现了错误。 另外,我觉得应该需要 addView 行; 由于充气器似乎将 TextView 附加到 RecyclerView 父项, 看来我更换充气器的东西也应该附在上面。

是否可以使用 TextView 作为元素制作 RecyclerView 而不是由自定义 xml 布局定义的元素?

这是我的代码:

PointChangeAdapter.java:

package com.mherzl.pointcounter;

import android.view.ViewGroup;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class PointChangeAdapter extends RecyclerView.Adapter<PointChangeAdapter.PointChangeViewHolder> {

    private List<Integer> recentChanges;

    public PointChangeAdapter(List<Integer> recentChanges) {
        this.recentChanges = recentChanges;
    }

    @Override
    public int getItemCount() {
        if (recentChanges == null) {
            return 0;
        }
        return recentChanges.size();
    }

    @Override
    public PointChangeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final TextView textView = new TextView(parent.getContext());
        parent.addView(textView);
        return new PointChangeViewHolder(textView);
    }

    @Override
    public void onBindViewHolder(PointChangeViewHolder holder, int position) {
        final int pointChange = recentChanges.get(position);
        String text = Integer.toString(pointChange);
        holder.setText(text);
    }

    public static class PointChangeViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;

        public PointChangeViewHolder(TextView textView) {
            super(textView);
            this.textView = textView;
        }

        public void setText(String text) {
            textView.setText(text);
        }
    }
}

这就是 运行 的内容 -- 在片段的 onCreateView 中使用 RecyclerView:

RecyclerView pointChangeRecycler =
        (RecyclerView) view.findViewById(R.id.point_changes_recycler);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
pointChangeRecycler.setLayoutManager(layoutManager);
List<Integer> myList = new ArrayList<>();
myList.add(1); myList.add(2); myList.add(3);
PointChangeAdapter pointChangeAdapter = new PointChangeAdapter(myList);
pointChangeRecycler.setAdapter(pointChangeAdapter);

是的。 onCreateViewHolder 只是 returns 一个带有 ViewGroup(甚至可能只是一个视图)作为根视图的 ViewHolder。

您的问题是您将其添加到了父级。你不想那样做。 RecyclerView 最终将成为它的父级。您应该只是创建它并返回一个以该视图作为根视图的持有者。

是的,即使传入的父级可能(尽管不一定)也是 RecyclerView。回收器视图的布局管理器进行添加。这就是为什么您的 inflate() 调用的最后一个参数是 false- 以防止 inflate 将其添加到父级。