RecyclerView动态标题 [英] RecyclerView Dynamic Header

查看:88
本文介绍了RecyclerView动态标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用RecyclerView添加动态标头.我提供了一个示例图像,如下所示.

I have been working with RecyclerView to add dynamic headers. I have provided a sample Image like below what I wants.

在上图中,孩子是有限的,在我看来,这是有限的.标头后面有不确定的孩子.

In above image the children are finite which is not in my case. I'm having uncertain children after the header.

基本上,它会代替 header0 ,而是类似于 MAR 的月份名称,并且下面会出现 MAR 月份中发生的事情.数据来自API,即Web服务,该日期也即将到来,但是我正在努力为上面解释的内容创建逻辑.

Basically instead of header0 it will be Month name like MAR and below that things which have occurred in MAR month will come. The data is coming from API i.e Web Service in which date is also coming but I'm struggling to create a logic for what I have explained above.

我尝试过的方法如下.以下是我创建的一个示例项目,因为原始代码是机密的,并且具有与原始代码类似的逻辑问题.

What I have tried is like below. Below is a sample project I created as original code is confidential and It has similar logic issue like original one.

MainActivity.java

    public class MainActivity extends AppCompatActivity {

    private RecyclerView rv;
    private ArrayList<Bean> beanArrayList = new ArrayList<>();
    private ArrayList<Bean> beanArrayListToPopulate = new ArrayList<>();

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

        addDataToBean();

        rv = findViewById(R.id.rv);
        rv.setLayoutManager(new LinearLayoutManager(this));

        String prevMonth = null;

        for (int i = 0; i < beanArrayList.size(); i++) {

            Bean bean = new Bean();
            bean.setFirstName(beanArrayList.get(i).getFirstName());

            String newMonth;
            String createdDate = beanArrayList.get(i).getCreatedDate();

            if (createdDate != null) {
                newMonth = createdDate.split(" ")[1].trim();
                if (!newMonth.equalsIgnoreCase(prevMonth)) {
                    bean.setViewType(Adapter.VIEW_TYPE_ITEM);
                } else if (newMonth.equalsIgnoreCase(prevMonth)) {
                    bean.setViewType(Adapter.VIEW_TYPE_HEADER);
                    bean.setHeaderString(newMonth);
                }
                prevMonth = newMonth;
            }
            beanArrayListToPopulate.add(bean);
        }
        rv.setAdapter(new Adapter(beanArrayListToPopulate));
    }

    private void addDataToBean() {

        SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy");

        Date currentDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);

        for (int i = 0; i < 50; i++) {
            Bean bean = new Bean();
            calendar.add(Calendar.DATE, 10);
            Date newDate = calendar.getTime();
            bean.setCreatedDate(sdf.format(newDate));
            bean.setFirstName("Maulik - " + i);
            beanArrayList.add(bean);
        }
    }
}

Adapter.java

    public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    public static final int VIEW_TYPE_ITEM = 0;
    public static final int VIEW_TYPE_HEADER = 1;

    private ArrayList<Bean> mBeanList;

    public Adapter(ArrayList<Bean> beanList) {
        this.mBeanList = beanList;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        if (viewType == VIEW_TYPE_HEADER) {
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header, parent, false);
            return new VHHeader(view);
        } else if (viewType == VIEW_TYPE_ITEM) {
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
            return new VHItem(view);
        }
        throw new RuntimeException("There is no type that matches the type " + viewType + ". Make sure you are using view types correctly!");
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof VHHeader) {
            ((VHHeader) holder).tvHeader.setText(mBeanList.get(position).getHeaderString());
        } else if (holder instanceof VHItem) {
            ((VHItem) holder).tvItem.setText(mBeanList.get(position).getFirstName());
        }
    }

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

    @Override
    public int getItemViewType(int position) {
        return mBeanList.get(position).getViewType();
    }

    class VHItem extends RecyclerView.ViewHolder {
        private TextView tvItem;

        public VHItem(View itemView) {
            super(itemView);
            tvItem = itemView.findViewById(R.id.tv_item);
        }
    }

    class VHHeader extends RecyclerView.ViewHolder {
        private TextView tvHeader;

        public VHHeader(View itemView) {
            super(itemView);
            tvHeader = itemView.findViewById(R.id.tv_header);
        }
    }
}

Bean.java

    public class Bean {

    private String createdDate;
    private String firstName;
    private int viewType;
    private String headerString;

    public String getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(String createdDate) {
        this.createdDate = createdDate;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public int getViewType() {
        return viewType;
    }

    public void setViewType(int viewType) {
        this.viewType = viewType;
    }

    public String getHeaderString() {
        return headerString;
    }

    public void setHeaderString(String headerString) {
        this.headerString = headerString;
    }
}

获得类似的输出

谢谢.!

推荐答案

问题是您有一个Bean列表,并且想在新的月份添加标题.因此,当月份更改时,在beanArrayListToPopulate中,您需要添加Bean 标头.因此,您需要创建一个额外的Bean来添加标题.

The problem is that you have have a list of Bean and you want to add a header when this is a new month. So when the month changes, in beanArrayListToPopulate you need to add the Bean and the header. So you need to create an extra Bean to add the header.

所以for循环应该像这样(在MainActivity中)

So the for loop should be like that (in MainActivity)

String prevMonth = null;
String newMonth;
String createdDate;
for (Bean bean : beanArrayList) {
    createdDate = bean.getCreatedDate();
    // Create header Bean if necessary
    if (createdDate != null) {
        newMonth = createdDate.split(" ")[1].trim();
        if (!newMonth.equalsIgnoreCase(prevMonth)) {
            Bean headerBean = new Bean();
            headerBean.setViewType(Adapter.VIEW_TYPE_HEADER);
            headerBean.setHeaderString(newMonth);
            beanArrayListToPopulate.add(headerBean);
            prevMonth = newMonth;
        }
    }
    // Update data Bean
    bean.setViewType(Adapter.VIEW_TYPE_ITEM);
    beanArrayListToPopulate.add(bean);
}

您也可以尝试这种方法

但是我想我最好还是使用专用的对象,而不用仅用于显示它们的信息来污染您检索的数据(Bean).

But I think I'd even be better to use a dedicated object to not pollute the data you retrieve (Bean) with information only used to display them.

所以您可以做的是创建一个ListItem对象,并在您的适配器中使用它,而不是Bean本身.

So what you can do is to create a ListItem object and use it in your Adapter instead of the Bean itself.

在活动中

private ArrayList<Bean> beanArrayList = new ArrayList<>();
private ArrayList<ListItem> mListItems = new ArrayList<>();

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

    addDataToBean();

    rv = findViewById(R.id.rv);
    rv.setLayoutManager(new LinearLayoutManager(this));

    String prevMonth = null;
    String newMonth;
    String createdDate;
    for (Bean bean : beanArrayList) {
        createdDate = bean.getCreatedDate();
        // Create a header if necessary
        if (createdDate != null) {
            newMonth = createdDate.split(" ")[1].trim();
            if (!newMonth.equalsIgnoreCase(prevMonth)) {
                ListItem headerItem = new ListItem(newMonth, Adapter.VIEW_TYPE_HEADER);
                mListItems.add(headerItem);
                prevMonth = newMonth;
            }
        }
        // Create a new item with the Bean data
        ListItem item = new ListItem(bean.getFirstName(), Adapter.VIEW_TYPE_ITEM);
        mListItems.add(item);
    }

    rv.setAdapter(new Adapter(mListItems));
}

在适配器中(我只输入了更改的内容)

In the Adapter (I've put only what I've changed)

private final ArrayList<ListItem> mItems;

public Adapter(ArrayList<ListItem> items) {
    this.mItems = items;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view;
    final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    if (viewType == VIEW_TYPE_HEADER) {
        view = inflater.inflate(R.layout.header, parent, false);
        return new VHHeader(view);
    } else if (viewType == VIEW_TYPE_ITEM) {
        view = inflater.inflate(R.layout.item, parent, false);
        return new VHItem(view);
    }
    throw new RuntimeException("There is no type that matches the type " + viewType + ". Make sure you are using view types correctly!");
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    ListItem item = mItems.get(position);
    // Note: You have the type information directly inside the ViewHolder so you don't need
    // to check the ViewHolder's instance type
    switch (holder.getItemViewType()) {
        case VIEW_TYPE_HEADER:
            ((VHHeader) holder).tvHeader.setText(item.getData());
            break;
        case VIEW_TYPE_ITEM:
            ((VHItem) holder).tvItem.setText(item.getData());
            break;
    }
}

ListItem

public class ListItem {
    private String mData;
    private int mType;

    public ListItem(String data, int type) {
        mData = data;
        mType = type;
    }

    public String getData() {
        return mData;
    }

    public void setData(String data) {
        mData = data;
    }

    public int getType() {
        return mType;
    }
}

注意:也许代码可能需要做一些调整,因为我尚未对其进行测试.

Note: Maybe the code will required some adjustments as I haven't tested it.

这篇关于RecyclerView动态标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆