当前位置: 首页 > 知识库问答 >
问题:

Recyclerview和处理不同类型的行膨胀

廉鸿运
2023-03-14

我应该像“老”方式那样做吗,还是应该用layoutmanager做些什么?我在想是否有人能给我指明正确的方向。因为我只能找到一种类型的例子。

我想要一张略有不同的牌的清单。或者我应该只使用ScrollViewCardViews...不使用适配器和RecyclerView

共有1个答案

杨乐意
2023-03-14

处理类似于iOS的UITableView的行/节逻辑,在Android中不像在iOS中那么简单,但是,当您使用RecolyerView时,您所能做的灵活性要大得多。

最后,这都是关于如何确定在适配器中显示的视图类型的问题。一旦你弄明白了,它应该是很容易的航行(不是真的,但至少你会把它整理好)。

适配器公开了您应该重写的两个方法:

getItemViewType(int position)
createViewHolder(ViewGroup parent, int viewType)

如果您计划使用默认的LayoutManager,如LinearLayoutManager,那么您应该可以继续使用。如果您打算制作自己的LayoutManager实现,则需要更加努力地工作。您真正需要使用的唯一API是findViewByPosition(int position),它在某个位置提供给定的视图。由于您可能希望根据视图的类型对其进行不同的布局,因此有以下几个选项:

>

  • 通常在使用ViewHolder模式时,使用视图持有者设置视图的标记。在运行时,您可以在布局管理器中使用此功能,通过在视图保持器中添加一个字段来表示此功能,从而找出视图的类型。

    由于您需要一个函数来确定哪个位置与哪个视图类型相关,因此您不妨以某种方式使这个方法全局可访问(也许是一个管理数据的单例类?),然后您就可以根据位置查询相同的方法了。

    下面是一个代码示例:

    // in this sample, I use an object array to simulate the data of the list. 
    // I assume that if the object is a String, it means I should display a header with a basic title.
    // If not, I assume it's a custom model object I created which I will use to bind my normal rows.
    private Object[] myData;
    
    public static final int ITEM_TYPE_NORMAL = 0;
    public static final int ITEM_TYPE_HEADER = 1;
    
    public class MyAdapter extends Adapter<ViewHolder> {
    
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    
            if (viewType == ITEM_TYPE_NORMAL) {
                View normalView = LayoutInflater.from(getContext()).inflate(R.layout.my_normal_row, null);
                return new MyNormalViewHolder(normalView); // view holder for normal items
            } else if (viewType == ITEM_TYPE_HEADER) {
                View headerRow = LayoutInflater.from(getContext()).inflate(R.layout.my_header_row, null);
                return new MyHeaderViewHolder(headerRow); // view holder for header items
            }
        }
    
    
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
    
            final int itemType = getItemViewType(position);
    
            if (itemType == ITEM_TYPE_NORMAL) {
                ((MyNormalViewHolder)holder).bindData((MyModel)myData[position]);
            } else if (itemType == ITEM_TYPE_HEADER) {
                ((MyHeaderViewHolder)holder).setHeaderText((String)myData[position]);
            }
        }
    
        @Override
        public int getItemViewType(int position) {
            if (myData[position] instanceof String) {
                return ITEM_TYPE_HEADER;
            } else {
                return ITEM_TYPE_NORMAL;
            }
        }
    
        @Override
        public int getItemCount() {
            return myData.length;
        }
    }
    

    下面是这些视图持有者的示例:

    public MyHeaderViewHolder extends ViewHolder {
    
        private TextView headerLabel;    
    
        public MyHeaderViewHolder(View view) {
            super(view);
    
            headerLabel = (TextView)view.findViewById(R.id.headerLabel);
        }
    
        public void setHeaderText(String text) {
            headerLabel.setText(text);
        }    
    }
    
    
    public MyNormalViewHolder extends ViewHolder {
    
        private TextView titleLabel;
        private TextView descriptionLabel;    
    
        public MyNormalViewHolder(View view) {
            super(view);
    
            titleLabel = (TextView)view.findViewById(R.id.titleLabel);
            descriptionLabel = (TextView)view.findViewById(R.id.descriptionLabel);
        }
    
        public void bindData(MyModel model) {
            titleLabel.setText(model.getTitle());
            descriptionLabel.setText(model.getDescription());
        }    
    }
    

    当然,本示例假设您构造了数据源(myData),这样就可以很容易地实现适配器。作为一个示例,我将向您展示如何构造一个数据源,该数据源显示一个姓名列表,并在姓名的第一个字母发生变化时显示一个标题(假设列表是按字母顺序排列的)--类似于联系人列表的外观:

    // Assume names & descriptions are non-null and have the same length.
    // Assume names are alphabetized
    private void processDataSource(String[] names, String[] descriptions) {
        String nextFirstLetter = "";
        String currentFirstLetter;
    
        List<Object> data = new ArrayList<Object>();
    
        for (int i = 0; i < names.length; i++) {
            currentFirstLetter = names[i].substring(0, 1); // get the 1st letter of the name
    
            // if the first letter of this name is different from the last one, add a header row
            if (!currentFirstLetter.equals(nextFirstLetter)) {
                nextFirstLetter = currentFirstLetter;
                data.add(nextFirstLetter);
            }
    
            data.add(new MyModel(names[i], descriptions[i]));
        }
    
        myData = data.toArray();
    }
    

  •  类似资料:
    • 我使用的是改型2.0.1。我想处理所有类型的网络错误和异常(如没有网络连接,超时错误,服务器找不到等)我已经找到这个链接。但是其中一些方法在V1.8.0中被否决了。在2.0.1中如何做到这一点?

    • 本文向大家介绍处理执行中的并行性类型,包括了处理执行中的并行性类型的使用技巧和注意事项,需要的朋友参考一下 数据并行 数据并行意味着在每个多个计算核心上并发执行同一任务。 让我们举个例子,对大小为N的数组的内容求和。对于单核系统,一个线程将简单地对元素[0]求和。。。[N-1]。但是,对于双核系统,在核0上运行的线程A可以对元素[0]求和。。。[N / 2-1],而在核心1上运行的线程B可以求和元

    • 以下是GSON的例外: 改型实例是使用GsonConverterFactory创建的

    • 假设我正在为Akka(类型化)执行元定义一个行为,该行为将执行并发计算,将其结果报告给生成它的执行元,然后停止。 如果我用计算的所有输入初始化这个actor,加上对它的“父级”的引用,那么它将永远不需要接收任何类型的传入消息。 我将使用创建此行为,向它传递一个执行计算的函数,然后返回。 Akka(Typed)要求我为将返回此行为的函数提供某种的结果类型。虽然我可以为分配行为将发送的结果消息的类型,

    • 我正在解码一个响应体,我得到了错误: 我在Udemy上学习颤振教程时,正在尝试使用API。教程说要使用https://javiercbk.github.io/json_to_dart/将JSON转换为Dart。我把JSON从https://www.openbrewerydb.org/并将其转换为Dart,但我遇到的问题是,当我尝试解码API时,我得到了未处理的错误异常:“List”类型不是“Map