1. Nimm jetzt an unserem Uhans - 3. ADVENT - Gewinnspiel teil - Alle Informationen findest Du hier!

Custom SimpleCursorAdapter - Sections Problem

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von MetBo, 03.09.2011.

  1. MetBo, 03.09.2011 #1
    MetBo

    MetBo Threadstarter Fortgeschrittenes Mitglied

    Beiträge:
    264
    Erhaltene Danke:
    4
    Registriert seit:
    14.05.2010
    Hallo,

    Ich versuche gerade in meiner ListView Sections einzublenden.

    Beispiel:
    Um dies zu realisieren, habe ich eine eigene SimpleCursorAdapter Klasse (NewsAdapter_new) angelegt.

    In einer LinkedHashMap<Integer, String> speichere ich mit <Position (Cursor Position), Sectionname> die Sections. Diese Funktion funktioniert soweit sehr gut.

    In getView() rufe ich die Methode getItemViewType() auf, um zu entscheiden, ob die aktuelle Cursor Position ein normaler Eintrag oder eine Section ist.


    Das Ganze klappt auch soweit ganz gut - es werden Sections und normale Einträge angezeigt. Mein Problem ist nun, dass die Einträge, die normalerweise auf der Section Position wären, verschwinden bzw. nicht angezeigt werden.


    Hier meine Custom SimpleCursorAdapter Klasse:
    Code:
    public class NewsAdapter_new extends SimpleCursorAdapter {
    	protected static final String TAG = "NewsAdapter";
    	
    	protected static final int TYPE_HEADER = 0x00;
    	protected static final int TYPE_NORMAL = 0x01;
    	protected static final int TYPE_COUNT = 0x02;
    	
    	protected final LayoutInflater mInflater;
    	protected final LinkedHashMap<Integer, String> mSections;
    	
    	protected int mCurrentSectionMapSize = 0;
    
    	public NewsAdapter_new(Context context, int layout, Cursor c,
    			String[] from, int[] to, int flags) {
    		super(context, layout, c, from, to, flags);
    		
    		mInflater = LayoutInflater.from(mContext);
    		mSections = getSeparators();
    		mCursor.moveToFirst();
    	}
    	
    	@Override
    	public View getView(int position, View convertView, ViewGroup parent) {
    		int viewType = getItemViewType(position);
    		
    		mCursor.moveToPosition(position);
    			
    			switch (viewType) {
    				case TYPE_NORMAL: {
    					// Normale Einträge werden hier initialisiert
    				
    					break;
    				}
    				case TYPE_HEADER: {
    					// Header-View wird hier initialisiert
    					break;
    				}
    			}
    		
    		return convertView;
    	}
    	
    	@Override
    	public int getCount() {
    		if (mCursor.getCount() != 0) {
    			return super.getCount() + mSections.keySet().size();
    		}
    		
    		return 0;
    	}
    	
    	@Override
        public int getItemViewType(int position) {
    		if (mSections == null) {
    			return TYPE_NORMAL;
    		} else {
    			if (mSections.containsKey(position)) {
    				return TYPE_HEADER;
    			} else {
    				return TYPE_NORMAL;
    			}
    		}
        }
    	
    	@Override
    	public boolean areAllItemsEnabled() {
    		return false;
    	}
    	
    	@Override
    	public boolean isEnabled(int position) {
    		if (mSections == null) {
    			return true;
    		}
    		
    		return !mSections.containsKey(position);
    	}
    
        @Override
        public int getViewTypeCount() {
            return TYPE_COUNT;
        }
    	
        protected LinkedHashMap<Integer, String> getSeparators() {
        	LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>();
        	String newDate = "";
    		String oldDate = "";
    		
    		mCursor.moveToFirst();
    		
    		if (!mCursor.isAfterLast()) {
    			do {
    				String currentString = mCursor.getString(mCursor.getColumnIndex(ArticleCol.DATE));
    				newDate = currentString.substring(0, 10);
    				
    				if (!newDate.contentEquals(oldDate)) {
    					map.put(mCursor.getPosition(), Util.formatBackToRealDate(newDate));
    				}
    				
    				oldDate = newDate;
    			} while (mCursor.moveToNext());
    		}
    		
        	return map;
        }
    }
    
    Hat jemand mein Problem verstanden und könnte mir eventuell helfen eine Lösung zu finden?

    Vielen Dank,
    Grüße Metti
     
  2. sixi, 03.09.2011 #2
    sixi

    sixi Erfahrener Benutzer

    Beiträge:
    237
    Erhaltene Danke:
    64
    Registriert seit:
    20.01.2009
    Du musst deine "Header" aus der position von "getView" rausrechnen.

    Im Konkreten:

    getView(0) -> Header 0
    getView(1) -> getItem(1-1 = 0)
    getView(2) -> getItem(2-1 = 1);
    getView(3) -> getItem(3-1 = 2);
    getView(4) -> getItem(4-1 = 3);
    getView(5) -> Header 1
    getView(6) -> getItem(6-2 = 4);
    etc.
    (für dein Beispiel)
     
  3. MetBo, 03.09.2011 #3
    MetBo

    MetBo Threadstarter Fortgeschrittenes Mitglied

    Beiträge:
    264
    Erhaltene Danke:
    4
    Registriert seit:
    14.05.2010
    Also muss ich für jeden Header getView() extra aufrufen?
     
  4. sixi, 03.09.2011 #4
    sixi

    sixi Erfahrener Benutzer

    Beiträge:
    237
    Erhaltene Danke:
    64
    Registriert seit:
    20.01.2009
    Nein - getView wird automatisch aufgerufen.
    Es kommen quasi für jede position (von 0 bis anzahlElemente die du per getCount() zurückgibst) Anfragen. DU musst nur in dem getView schauen, dass du für jede position den richtigen View zurückgibst.
    Und dazu gehört halt der richtige Typ (was du schon tust), aber auch das richtige Element aus deinen Listen (das meinte ich mit der getView(x) -> ... zuweisung da oben ;))
     
  5. MetBo, 04.09.2011 #5
    MetBo

    MetBo Threadstarter Fortgeschrittenes Mitglied

    Beiträge:
    264
    Erhaltene Danke:
    4
    Registriert seit:
    14.05.2010
    In deinem Beispiel sollte also die Berechnung der korrekten Positionen in getItem() stattfinden. Nun habe ich mal ein bisschen debuggt und mir ist aufgefallen, dass der Adapter gar nicht in die getItem() Funktion springt?!
     
  6. sixi, 04.09.2011 #6
    sixi

    sixi Erfahrener Benutzer

    Beiträge:
    237
    Erhaltene Danke:
    64
    Registriert seit:
    20.01.2009
    Tut er auch nicht von alleine, du musst es wenn dann explizit aufrufen.
    GetItem() musst du wenn dann explizit aufrufen. MUSST du aber NICHT!

    Du musst einfach nur sicherstellen, dass für jede Position der richtige Typ zurückgegeben wird (das was du mit der SWITCH-Anweisung machst!) UND je nach Typ das Richtige Element aus einer deiner Liste...

    Also - wenn
    getView(0, convertView, parent) aufgerufen wird:
    gehst du in deinem Switch in "case TYPE_HEADER:" und gibst den View, passend zu deinem ersten Header aus == deineHeader[0]

    getView(1, convertView, parent) aufgerufen wird:
    gehst du in deinem Switch in "case TYPE_NORMAL:" und gibst den View, passend zu deinem ersten Element aus deinen Elementen == deineElemente[0] == deineElemente(position-1)

    getView(2, convertView, parent) aufgerufen wird:
    gehst du in deinem Switch in "case TYPE_NORMAL:" und gibst den View, passend zu deinem zweitem Element aus deinen Elementen == deineElemente[1] == deineElemente(position-1)

    ...

    getView(5, convertView, parent) aufgerufen wird:
    gehst du in deinem Switch in "case TYPE_HEADER:" und gibst den View, passend zu deinem zweiten Header aus == deineHeader[1]

    getView(6, convertView, parent) aufgerufen wird:
    gehst du in deinem Switch in "case TYPE_NORMAL:" und gibst den View, passend zu deinem FÜNFTEN Ersten aus deinen Elementen == deineElemente[5] genau HIER ist die Variable position NICHTMEHR gleich dem X. Element aus deineElemente, sondern deineElemente(position-2)

    An dieser Stelle ist es dann nichtmehr das SECHSTE Element, sondern eben das FÜNFTE, weil der View zur position FÜNF ein header ist, und genau dein Problem ja ist, dass du jeweils die Elemente aus deinen Elementen nicht angezeigt kriegst, wo ein header ist...


    Die Beispiele sind kein Copy&Paste-Code sondern sollen dir dein Problem aufzeigen ;-) Debugg doch deine Variante einfach mal durch, dann siehst du das getView() mit den Werten Position 0 bis xx aufgerufen wird - und du aber NIE auf die "normalen Elemente" zugreifst, für die Positionen, wo ein Header angezeigt wird.
     
    Zuletzt bearbeitet: 04.09.2011
    MetBo bedankt sich.
  7. MetBo, 04.09.2011 #7
    MetBo

    MetBo Threadstarter Fortgeschrittenes Mitglied

    Beiträge:
    264
    Erhaltene Danke:
    4
    Registriert seit:
    14.05.2010
    Ich habe das Prinzip jetzt verstanden. Ich habe jetzt auch folgendes verändert bzw. eingebunden:

    Es werden immer noch nicht alle Einträge angezeigt ... ich verzweifel -.-
     

Diese Seite empfehlen