2011-06-07 31 views
25

Quiero mostrar ListView con Date como SectionHeader.ListView personalizado con fecha como SectionHeader (Usado CustomCursorAdapter personalizado)

Lo que tengo: Estoy mostrando ListView de la base de datos sqlite usando SimpleCursorAdapter personalizado.

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

Google Resultados hasta la fecha:

MergeAdapter

Jeff Sharkey

Amazing ListView

SO Question

Problema: Quiero mostrar listview con la fecha como encabezados de sección. Los valores de la fecha del curso provienen de la base de datos sqlite.

¿Puede alguien por favor guía cómo puedo lograr esta tarea.

O proporcióneme un código de ejemplo o un código exacto (como) relacionado con el mismo.

Editado Según la respuesta de Graham Borald (esto funciona bien. Sin embargo, 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 Excepción del puntero nulo en la línea: Cursor date=adapter.fetchTodo(id); Parece que el Cursor no está obteniendo un ny datos.

+0

https://github.com/emilsjolander/StickyListHea Gracias 0rs. – Mertuarez

Respuesta

51

La forma más simple de hacerlo es insertar la vista de encabezado de fecha en cada elemento. Luego, todo lo que necesita 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); 
    } 
+0

Gracias por una solución rápida. Esto está funcionando. Pero quiero ir según la respuesta de CommonsWare. ¿Puedes ayudarme a implementar eso? –

+2

No considero que esto sea una solución rápida. Creo que es una solución muy clara, compacta y eficiente para el problema. He usado exactamente este enfoque en el código de producción, y da muy buenos resultados. ¿Con qué aspecto estás descontento? –

+0

Problema: cuando hago clic largo en el primer elemento (que también contiene el encabezado) toda la vista de ese elemento se pone de color amarillo. No quiero eso. –

4

¿Puede alguien por favor guía cómo puedo lograr esta tarea.

Con mucho dolor.

Deberá crear su propia subclase de CursorAdapter (o posiblemente SimpleCursorAdapter). En esa subclase, deberá calcular el número de filas de encabezado y ajustar getCount() para que coincida. Necesitará tener getViewTypeCount() devolver el número correcto. Deberá identificar las posiciones de esas filas de encabezado y ajustar getItemViewType(), newView() y bindView() para tratar las filas de encabezado, ajustando el valor position para las filas de detalles para tener en cuenta el número de encabezados que están delante de esa fila, por lo que obtener la posición correcta Cursor para trabajar. También puede ser necesario hacer otros ajustes, pero eso es bastante cierto.

Si nadie me gana, probablemente escriba uno de estos en el próximo año, una vez que sea necesario para un proyecto mío.

+0

Gracias por su magnífica respuesta. Realmente aprecio tu respuesta y esfuerzo. Pero quiero confirmar lo que he entendido. –

+0

1. getCount() debe devolver el número de elementos (filas) o el número total de elementos (filas + encabezado)? –

+0

@Kartik: filas + encabezados. Más exactamente, 'getCount()' devuelve el número de filas que deberían estar en 'ListView', que tiene cierta semejanza con el número de" filas "en su' Cursor', pero en su caso también debe tener en cuenta cualquier encabezados u otras filas que está agregando a la mezcla. – CommonsWare

1

es muy sencilla para la aplicació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 espectáculo de cabecera/ocultar en la costumbre CommentCell vista:

public void showHeader(boolean show, String currentDate) { 
    if (show) { 
     headerTextview.setVisibility(VISIBLE); 
     headerTextview.setText(currentDate); 
    } else { 
     headerTextview.setVisibility(GONE); 
    } 
} 

fecha de creación cadena:

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; 
} 
+0

¿Puede explicar su solución? Es un montón de código. –

Cuestiones relacionadas