Custom ListView con la fecha como SectionHeader (Custom SimpleCursorAdapter utilizado)
Quiero mostrar ListView con la fecha como SectionHeader.
Lo que tengo: Estoy mostrando ListView desde la base de datos sqlite usando SimpleCursorAdapter personalizado.
- ¿Cuál es el tamaño máximo de la base de datos SQLite en Android?
- SQLite Android asignación de la ventana de cursor de 2048 kb falló
- SQLiteConstraintException: código de error 19: falla de restricción
- Base de datos SQLite para aplicaciones de Android con múltiples usuarios potenciales
- ¿Por qué Androidite SQLite puede almacenar doble valor (java 8 bytes) en la columna de flotación
Mi Custom SimpleCursorAdapter es:
public class DomainAdapter extends SimpleCursorAdapter{ private Cursor dataCursor; private LayoutInflater mInflater; public DomainAdapter(Context context, int layout, Cursor dataCursor, String[] from, int[] to) { super(context, layout, dataCursor, from, to); this.dataCursor = dataCursor; mInflater = LayoutInflater.from(context); } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.todo_row, null); holder = new ViewHolder(); holder.text1 = (TextView) convertView.findViewById(R.id.label);//Task Title holder.text2 = (TextView) convertView.findViewById(R.id.label2);//Task Date holder.img = (ImageView) convertView.findViewById(R.id.task_icon); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } dataCursor.moveToPosition(position); int title = dataCursor.getColumnIndex("title"); String task_title = dataCursor.getString(title); int title_date = dataCursor.getColumnIndex("day"); String task_day = dataCursor.getString(title_date); int description_index = dataCursor.getColumnIndex("priority"); int priority = dataCursor.getInt(description_index); holder.text1.setText(task_title); holder.text2.setText(task_day); if(priority==1) holder.img.setImageResource(R.drawable.redbutton); else if(priority==2) holder.img.setImageResource(R.drawable.bluebutton); else if(priority==3)holder.img.setImageResource(R.drawable.greenbutton); else holder.img.setImageResource(R.drawable.redbuttonchecked); return convertView; } static class ViewHolder { TextView text1; TextView text2; ImageView img; } }
Resultados de Google hasta el momento:
MergeAdapter
Jeff Sharkey
Amazing ListView
Entonces pregunta
Problema: Quiero mostrar listview con Date como encabezados de sección. Los valores Ofcourse Date provienen de la base de datos sqlite.
¿Puede alguien por favor me guía cómo puedo lograr esta tarea.
O Proporcionarme un Código de Muestra o Código Exacto (como) relacionado con el mismo.
Editado De acuerdo con la respuesta de Graham Borald (Esto funciona bien, pero fue una solución rápida.)
public class DomainAdapter extends SimpleCursorAdapter{ private Cursor dataCursor; private LayoutInflater mInflater; public DomainAdapter(Context context, int layout, Cursor dataCursor, String[] from, int[] to) { super(context, layout, dataCursor, from, to); this.dataCursor = dataCursor; mInflater = LayoutInflater.from(context); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.tasks_row, null); holder = new ViewHolder(); holder.text1 = (TextView) convertView.findViewById(R.id.label);//Task Title holder.text2 = (TextView) convertView.findViewById(R.id.label2);//Task Date holder.img = (ImageView) convertView.findViewById(R.id.taskImage); holder.sec_hr=(TextView) convertView.findViewById(R.id.sec_header); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } dataCursor.moveToPosition(position); int title = dataCursor.getColumnIndex("title"); String task_title = dataCursor.getString(title); int title_date = dataCursor.getColumnIndex("due_date"); String task_day = dataCursor.getString(title_date); int description_index = dataCursor.getColumnIndex("priority"); int priority = dataCursor.getInt(description_index); String prevDate = null; if (dataCursor.getPosition() > 0 && dataCursor.moveToPrevious()) { prevDate = dataCursor.getString(title_date); dataCursor.moveToNext(); } if(task_day.equals(prevDate)) { holder.sec_hr.setVisibility(View.GONE); } else { holder.sec_hr.setText(task_day); holder.sec_hr.setVisibility(View.VISIBLE); } holder.text1.setText(task_title); holder.text2.setText(task_day); if(priority==1) holder.img.setImageResource(R.drawable.redbutton); else if(priority==2) holder.img.setImageResource(R.drawable.bluebutton); else if(priority==3)holder.img.setImageResource(R.drawable.greenbutton); else holder.img.setImageResource(R.drawable.redbuttonchecked); return convertView; } static class ViewHolder { TextView text1; TextView text2; TextView sec_hr; ImageView img; } }
Editado según la respuesta de CommonsWare
public class DomainAdapter extends SimpleCursorAdapter{ private Cursor dataCursor; private TodoDbAdapter adapter; private LayoutInflater mInflater; boolean header; String last_day; public DomainAdapter(Context context, int layout, Cursor dataCursor, String[] from, int[] to) { super(context, layout, dataCursor, from, to); this.dataCursor = dataCursor; mInflater = LayoutInflater.from(context); header=true; adapter=new TodoDbAdapter(context); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; TitleHolder title_holder = null; if(getItemViewType(position)==1) { //convertView= mInflater.inflate(R.layout.todo_row, parent, false); if (convertView == null) { convertView = mInflater.inflate(R.layout.todo_row, null); holder = new ViewHolder(); holder.text1 = (TextView) convertView.findViewById(R.id.label);//Task Title holder.text2 = (TextView) convertView.findViewById(R.id.label2);//Task Date holder.img = (ImageView) convertView.findViewById(R.id.task_icon); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } dataCursor.moveToPosition(position); int title = dataCursor.getColumnIndex("title"); String task_title = dataCursor.getString(title); int title_date = dataCursor.getColumnIndex("day"); String task_day = dataCursor.getString(title_date); int description_index = dataCursor.getColumnIndex("priority"); int priority = dataCursor.getInt(description_index); holder.text1.setText(task_title); holder.text2.setText(task_day); if(priority==1) holder.img.setImageResource(R.drawable.redbutton); else if(priority==2) holder.img.setImageResource(R.drawable.bluebutton); else if(priority==3)holder.img.setImageResource(R.drawable.greenbutton); else holder.img.setImageResource(R.drawable.redbuttonchecked); } else { if (convertView == null) { convertView = mInflater.inflate(R.layout.section_header, null); title_holder = new TitleHolder(); title_holder.datee = (TextView) convertView.findViewById(R.id.sec_header);//Task Title convertView.setTag(title_holder); } else { title_holder = (TitleHolder) convertView.getTag(); } dataCursor.moveToPosition(position); int title_date = dataCursor.getColumnIndex("day"); String task_day = dataCursor.getString(title_date); title_holder.datee.setText(task_day); } return convertView; } static class ViewHolder { TextView text1; TextView text2; ImageView img; } static class TitleHolder{ TextView datee; } @Override public int getCount() { return dataCursor.getCount()+1; //just for testing i took no. of headers=1 } @Override public int getViewTypeCount() { return 2; } @Override public int getItemViewType(int position) { dataCursor.moveToPosition(position); **Long id=dataCursor.getLong(position);** Cursor date=adapter.fetchTodo(id); int title_date = date.getColumnIndex("day"); String task_day = date.getString(title_date); Log.i("tag",task_day); if(last_day.equals(task_day)) return 1;//Display Actual Row else { last_day=task_day;//Displaying Header return 0; } } /* @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { final View view; if(getItemViewType(cursor.getPosition())==1) view= mInflater.inflate(R.layout.todo_row, parent, false); else view=mInflater.inflate(R.layout.section_header,parent, false); return view; } @Override public void bindView(View convertView, Context context, Cursor cursor) { long id = cursor.getPosition(); }*/ }
Estoy recibiendo la excepción de puntero nulo en la línea: Cursor date=adapter.fetchTodo(id);
Parece que Cursor no está recibiendo ningún dato.
- ¿El depurador de Android trunca mensajes de depuración?
- Android: ListView con CheckBox, poblado desde la base de datos SQLite no funciona
- Android SQLite - selecciónArgs que no sean cadenas
- ¿Cómo crear un widget de Android con opciones?
- Android: la base de datos está bloqueada
- Android: Cómo cargar imagen dinámicamente desde el servidor por su nombre de SQlite
- Empaquetado DB de SQLite con mi aplicación
- Datos de exportación de Android a csv
De lejos, la forma más sencilla de hacerlo es incrustar la vista de encabezado de fecha en cada elemento . Entonces, todo lo que necesitas hacer en bindView
es comparar la fecha de la fila anterior con la fecha de esta fila y ocultar la fecha si es la misma. Algo como esto:
String thisDate = cursor.getString(dateIndex); String prevDate = null; // get previous item's date, for comparison if (cursor.getPosition() > 0 && cursor.moveToPrevious()) { prevDate = cursor.getString(dateIndex); cursor.moveToNext(); } // enable section heading if it's the first one, or // different from the previous one if (prevDate == null || !prevDate.equals(thisDate)) { dateSectionHeaderView.setVisibility(View.VISIBLE); } else { dateSectionHeaderView.setVisibility(View.GONE); }
¿Puede alguien por favor me guía cómo puedo lograr esta tarea.
Con dolor considerable.
Necesitará crear su propia subclase de CursorAdapter
(o posiblemente SimpleCursorAdapter
). En esa subclase, tendrá que calcular el número de filas de encabezado y ajustar getCount()
para que coincida. Usted necesitará tener getViewTypeCount()
devolver el número correcto. Necesitará identificar las posiciones de esas filas de encabezado y ajustar getItemViewType()
, newView()
y bindView()
para hacer frente a las filas de encabezado, ajustando el valor de position
de las filas de detalle para tener en cuenta el número de cabeceras que están por delante De esa fila, para que obtenga la posición correcta del Cursor
para trabajar. Puede que tenga que haber otros ajustes también, pero estos son bastante seguros.
Si nadie me golpea, probablemente escribiré uno de estos en el próximo año, una vez que sea necesario para un proyecto mío.
Es muy simple para la implementación:
public class ChatAdapter extends NoteBaseAdapter { private Cursor mCursor; /** * List of notes to showToast */ public int getCount() { int count = 0; if (mCursor != null) count = mCursor.getCount(); return count; } public Comment getItem(int position) { mCursor.moveToPosition(position); Comment comment = Comment.fromCursor(mCursor); return comment; } public long getItemId(int position) { return 0; } public View getView(final int position, View convertView, ViewGroup parent) { final Comment comment = getItem(position); CommentCell cellView = null; if (convertView == null) { cellView = new CommentCell(parent.getContext()); cellView.setup(elementsColor, backgroundColor); } else cellView = (CommentCell) convertView; cellView.setComment(comment); boolean showHeader = false; String currentDate = null; if (position > 0 && position < getCount()) { int previousPosition = position - 1; Comment previousComment = getItem(previousPosition); currentDate = comment.headerDate(); String previousDate = previousComment.headerDate(); showHeader = !currentDate.equalsIgnoreCase(previousDate); } else { showHeader = true; currentDate = comment.headerDate(); } cellView.showHeader(showHeader, currentDate); return cellView; } public void update(long itemUniqueId) { mCursor = Comment.fetchResultCursor(itemUniqueId); notifyDataSetChanged(); }
Y mostrar / ocultar el encabezado en la vista personalizada de CommentCell:
public void showHeader(boolean show, String currentDate) { if (show) { headerTextview.setVisibility(VISIBLE); headerTextview.setText(currentDate); } else { headerTextview.setVisibility(GONE); } }
Create string date:
public String headerDate() { String createDateStr = null; if (createDate != Consts.NONE_LONG) createDateStr = TimeUtil.dateToString("dd MMMM", new Date(createDate)); return createDateStr; } public static String dateToString(String format, Date date) { DateFormat dateFormat = new SimpleDateFormat(format, Locale.getDefault()); String text = dateFormat.format(date); return text; }
- Cómo centrar un ImageView en un LinearLayout?
- Receptor de difusión no funciona después de reiniciar el dispositivo en Android