Ich muß in einem RecyclerView
und die Daten, die eine Art von Besuchern Protokollen anzeigen zu Anzeige von einem von Datetime (Spalte enter_time
, UNIX-Wert) -ordered DESC
SQLiteDatabase
kommt. Ich habe bereits eine einfache CursorAdapter
implementiert und kann Daten in der RecyclerView
anzeigen.Mehrere Zeilenlayouts in Cursor basierend auf nächstem Punkt
Im nächsten Schritt verschiedene Ansichten zu machen, so dass der erste Eintrag eines jeden Tages ein Layout mit einem zusätzlichen Header mit dem Datum verwendet:
Im Innern der CursorAdapter
implementiert I getItemViewType(int)
Methode, wo ich brauche füge meine Logik hinzu und wähle den richtigen Gegenstandstyp aus.
Die Logik ist einfach:
- Wenn nächster Punkt in
Cursor
selben Tag wie die aktuelle hat, dann wählen Sie das einfache Layout - Wenn nächster Punkt in
Cursor
anderes Datum als das aktuelle hat, wählen Sie dann die Layout mit Kopf
Hier kommt das Problem: ich muß nächstes Element in den Cursor
der CursorAdapter
überprüfen, aber die Das angezeigte Ergebnis ist falsch und ich kann nicht sagen warum. Der Code sieht für mich korrekt aus, aber das Layout wird nach dem Zufallsprinzip zugewiesen.
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;
}
}
Dies ist die eigentliche falsche Ergebnis:
ich SO sah über, aber ich kann ähnliches Szenario nicht finden, wo es Daten von benachbarten Elemente benötigt erholen (Ich bin nicht Event sicher ist das das Problem). Was würden Sie vorschlagen, um dieses Problem zu beheben?
statt iterieren den Cursor über und immer wieder würde ich 'SparseBooleanArray' verwenden, um die Positionen von" Header "Ansichten zu halten – pskink
@pskink netter Vorschlag, ich werde es implementieren, nachdem ich aus diesem – fillobotto