android - CursorAdapter 中基于下一项的多行布局

标签 android cursor android-recyclerview android-adapter

我需要在 RecyclerView 中显示某种访问者日志,要显示的数据来自 SQLiteDatabase DESC - 按日期时间排序(enter_time 列,UNIX 值)。我已经实现了一个简单的 CursorAdapter,并且能够在 RecyclerView 中显示数据。

下一步是制作不同的 View ,以便每天的第一个条目使用带有带有日期的附加标题的布局:

enter image description here

CursorAdapter 中,我实现了 getItemViewType(int) 方法,我需要在其中添加选择正确项目类型的逻辑。

逻辑很简单:

  • 如果光标中的下一项与当前日期相同,则选择简单布局
  • 如果光标中的下一项与当前日期不同,则选择带标题的布局

问题来了:我需要检查CursorAdapterCursor中的下一项,但显示的结果是错误的,我可以不说为什么。代码对我来说看起来是正确的,但布局是随机分配给项目的。

public static class VisitorsRecyclerAdapter extends RecyclerView.Adapter<VisitorsRecyclerAdapter.VisitorViewHolder> {

    CustomCursorAdapter mCursorAdapter;
    Context mContext;
    private static final int NO_HEADER_LAYOUT = 1;
    private static final int HEADER_LAYOUT = 0;

    public VisitorsRecyclerAdapter(Context context, Cursor c) {
        mContext = context;
        mCursorAdapter = new CustomCursorAdapter(mContext, c, 0);
    }

    public static class VisitorViewHolder extends RecyclerView.ViewHolder {

        public TextView textName;
        public TextView textCats;

        public VisitorViewHolder(View v) {
            super(v);
            textName = (TextView) v.findViewById(R.id.item_visitor_name);
            textCats = (TextView) v.findViewById(R.id.item_visitor_category);
        }
    }

    public static class HeaderViewHolder extends RecyclerView.ViewHolder {

        public TextView textName;
        public TextView textCats;

        public HeaderViewHolder(View v) {
            super(v);
            textName = (TextView) v.findViewById(R.id.item_visitor_name);
            textCats = (TextView) v.findViewById(R.id.item_visitor_category);
        }
    }

    private class CustomCursorAdapter extends CursorAdapter {


        public CustomCursorAdapter(Context context, Cursor c, int flags) {
            super(context, c, flags);
        }

        @Override
        public int getViewTypeCount() {
            return 2;
        }

        @Override
        public int getItemViewType(int position) {

            Cursor cursor = (Cursor) mCursorAdapter.getItem(position);
            cursor.moveToNext();

            // date of current item
            Date date0 = new Date(Long.parseLong(cursor.getString(cursor.getColumnIndex(DatabaseConst.VisitorEntry.COLUMN_NAME_ENTER))) * 1000);

            if(position == -1) return HEADER_LAYOUT;
            cursor = (Cursor) mCursorAdapter.getItem(position - 1);
            cursor.moveToNext();

            // date of item that temporary comes after
            Date date1 = new Date(Long.parseLong(cursor.getString(cursor.getColumnIndex(DatabaseConst.VisitorEntry.COLUMN_NAME_ENTER))) * 1000);

            SimpleDateFormat format = new SimpleDateFormat("ddMMyyyy", Locale.ENGLISH);

            return format.format(date0).equals(format.format(date1)) ? NO_HEADER_LAYOUT : HEADER_LAYOUT;
        }

        @Override
        public View newView(final Context context, Cursor cursor, ViewGroup parent) {
            View v = null;
            int position = cursor.getPosition();
            int type = getItemViewType(position);
            RecyclerView.ViewHolder viewHolder = null;

            switch (type) {
                case HEADER_LAYOUT:
                    v = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.item_day, parent, false);
                    viewHolder = new HeaderViewHolder(v);
                    break;
                case NO_HEADER_LAYOUT:
                    v = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.item_visitor, parent, false);
                    viewHolder = new VisitorViewHolder(v);
                    break;
            }
            assert v != null;
            v.setTag(viewHolder);
            return v;
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            final int viewType = getItemViewType(cursor.getPosition());

            switch (viewType) {
                case HEADER_LAYOUT:
                    HeaderViewHolder holder = (HeaderViewHolder) view.getTag();
                    holder.textName.setText(DateFormat.getDateTimeInstance().format(new Date(Long.parseLong(cursor.getString(cursor.getColumnIndex(DatabaseConst.VisitorEntry.COLUMN_NAME_ENTER))) * 1000)));
                    holder.textCats.setText(cursor.getString(cursor.getColumnIndex(DatabaseConst.VisitorEntry.COLUMN_NAME_FIRST_NAME)));
                    break;
                case NO_HEADER_LAYOUT:
                    VisitorViewHolder holder0 = (VisitorViewHolder) view.getTag();
                    holder0.textName.setText(DateFormat.getDateTimeInstance().format(new Date(Long.parseLong(cursor.getString(cursor.getColumnIndex(DatabaseConst.VisitorEntry.COLUMN_NAME_ENTER))) * 1000)));
                    holder0.textCats.setText(cursor.getString(cursor.getColumnIndex(DatabaseConst.VisitorEntry.COLUMN_NAME_FIRST_NAME)));
                    break;
            }

        }

    }

    @Override
    public int getItemCount() {
        if(mCursorAdapter == null) return 0;

        return mCursorAdapter.getCount();
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        mCursorAdapter.getCursor().moveToPosition(position);
        mCursorAdapter.bindView(holder.itemView, mContext, mCursorAdapter.getCursor());
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
        RecyclerView.ViewHolder viewHolder = null;
        switch (viewType){
            case HEADER_LAYOUT:
                viewHolder = new HeaderViewHolder(v);
                break;
            case NO_HEADER_LAYOUT:
                viewHolder = new VisitorViewHolder(v);
                break;
        }

        return viewHolder;
    }
}

这是实际的错误结果:

enter image description here

我查看了SO,但我找不到需要从相邻项目恢复数据的类似场景(我不确定这是否是问题所在)。您建议如何解决此问题?

最佳答案

在您从 getItemViewType 返回值之前,这似乎是正确的。您仅创建了一个 ViewHolder,即 VisitorViewHolder。 但还有另一种更好的方法来实现这一点,创建多个 ViewHolder 类并在 onCreateViewHolder 中切换它们。

这样修改,

@Override
    public VisitorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    switch (viewType){
       case HEADER_LAYOUT:
        View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
        final VisitorViewHolder holder = new VisitorViewHolder(v);    
        return holder;

       case NO_HEADER_LAYOUT:
              //Return you another viewholder which contains view with no header
      }
 }

参见here获取更多引用,这将使您的任务更加轻松。

关于android - CursorAdapter 中基于下一项的多行布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36750390/

相关文章:

c# - 如何使用 C# 将 Cursor 转换为可以保存到 .resx 文件中的图像?

android - 如何在 recyclerview 中保存复选框位置?

android - 条目 : otherfileoutputs=null 中的空值

java - 从 apk 恢复原始源

android - 如何在 Android 中合并两个 SimpleCursorAdapters?

mysql - 存储过程、函数或游标 mysql 将多行合并为一行而不使用 group_concat

java - 如何将这个嵌套的复杂 JSON 解析为 POJO

java - 使用 Recycler View 类的待办事项列表

android - 将动态 View 添加到 android tabhost

android - Phonegap 表单验证错误,使用后退按钮隐藏