Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/204.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RecyclerView动态标头_Android_Listview_Android Recyclerview_Recyclerview Layout - Fatal编程技术网

Android RecyclerView动态标头

Android RecyclerView动态标头,android,listview,android-recyclerview,recyclerview-layout,Android,Listview,Android Recyclerview,Recyclerview Layout,我一直在使用RecyclerView添加动态标题。我已经提供了一个样本图像如下我想要的 在上面的图像中,孩子们是有限的,这在我的例子中是不存在的。头球后我有了不确定的孩子 基本上不是header0而是像MAR这样的月份名称,而在MAR月份发生的事情将会发生。数据来自API,即Web服务,其中的日期也即将到来,但我正在努力为上面解释的内容创建一个逻辑 我试过的如下。下面是我创建的一个示例项目,因为原始代码是机密的,并且它有类似于原始代码的逻辑问题 MainActivity.java pu

我一直在使用RecyclerView添加动态标题。我已经提供了一个样本图像如下我想要的

在上面的图像中,孩子们是有限的,这在我的例子中是不存在的。头球后我有了不确定的孩子

基本上不是header0而是像MAR这样的月份名称,而在MAR月份发生的事情将会发生。数据来自API,即Web服务,其中的日期也即将到来,但我正在努力为上面解释的内容创建一个逻辑

我试过的如下。下面是我创建的一个示例项目,因为原始代码是机密的,并且它有类似于原始代码的逻辑问题

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);
        }
    }
}
    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);
        }
    }
}
    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;
    }
}
获得如下输出:

    <LinearLayout

    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >

     <!--Header -->
    <LinearLayout
        android:id="@+id/header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:visibility="gone">
         .................
         ................
     </LinearLayout>

     .......................
     .......................
    </LinearLayout>
public boolean displayHeader(int position) {

   if(position == 0) return true;
   //.....
  // check month difference to previous position if any then return true; 
  // else return false;  
}


提前谢谢

您可以通过以下方式解决:

  • 为每行项目中的标题使用额外视图
  • 检查两个连续行的日期(在您的情况下为月份)差异,如果发现差异,则显示后面的行标题。假设位置3和位置4行的显示头和位置4行的显示头有月差
  • 默认情况下,所有行标题都将隐藏
  • 您的数据应该按日期排序
  • row.xml:

        <LinearLayout
    
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >
    
         <!--Header -->
        <LinearLayout
            android:id="@+id/header"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:visibility="gone">
             .................
             ................
         </LinearLayout>
    
         .......................
         .......................
        </LinearLayout>
    
    public boolean displayHeader(int position) {
    
       if(position == 0) return true;
       //.....
      // check month difference to previous position if any then return true; 
      // else return false;  
    }
    
    onBindViewHolder中

    if(displayHeader(position)){
       // set to visiable 
    }else{
       // set visibility to gone
    }
    

    问题是您有一个
    Bean
    列表,并且您希望在新月份添加一个标题。因此,当月份发生变化时,您需要在
    beanArrayListToPopulate
    中添加
    Bean
    标题。因此,您需要创建一个额外的
    Bean
    来添加标题

    因此for循环应该是这样的(在
    MainActivity
    中)

    编辑:您也可以尝试这种方法

    但是我认为我最好使用一个专用的对象,不要用仅用于显示它们的信息来污染您检索的数据(
    Bean

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

    在活动中

    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));
    }
    

    注意:可能代码需要一些调整,因为我还没有测试过它。

    那么到底是什么问题呢?我添加了一个我得到的输出图像。请查收it@EselfarLet让我试试,我会给你回复的。Thanks@AbuYousufLet让我查一查,然后回去you@EselfarI“我更新了我的答案,做了一些改进。如果原始答案有效,您可以尝试它们:)据我所知,如果数据以正确的顺序(如升序或降序)来自Web服务,这将有效。如果没有任何命令,它不会出现怎么办?@EselfarIf not ordered,您将多次使用相同的标题。如果您只想拥有一个相同类型的标题(例如“2018年3月”),则需要先在请求中(如果来自数据库)或通过排序结果(来自Web服务)对列表进行排序,然后再显示它们。谢谢lot@Eselfar
    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;
        }
    }