2012-08-19 9 views
5

ich einen benutzerdefinierten Adapter:Android benutzerdefinierte Listview wiederholt Auswahl Hintergrund

public class PhraseCustomAdapter extends BaseAdapter 
{ 
public String original[]; 
public String translation[]; 
public String transcription[]; 

public Activity context; 
public LayoutInflater inflater; 

public PhraseCustomAdapter(Activity context,String[] original, String[] translation, String[] transcription) { 
    super(); 

    this.context = context; 
    this.original = original; 
    this.translation = translation; 
    this.transcription = transcription; 

    inflater = LayoutInflater.from(context); 
    this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

@Override 
public int getCount() { 
    // TODO Auto-generated method stub 
    return original.length; 
} 

@Override 
public Object getItem(int position) { 
    // TODO Auto-generated method stub 
    return position; 
} 

public String getItemTranlation(int position) { 

    return translation[position]; 
} 

public String getItemTranscription(int position) { 
    // TODO Auto-generated method stub 
    return transcription[position]; 
} 

public String getItemOriginal(int position) { 
    // TODO Auto-generated method stub 
    return original[position]; 
} 


@Override 
public long getItemId(int position) { 
    // TODO Auto-generated method stub 
    return position; 
} 

static class ViewHolder 
{ 
    ImageView imgViewLogo; 
    TextView txtViewOriginal; 
    TextView txtViewTranslation; 
    TextView txtViewTranscription; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 

    ViewHolder holder; 
    if (convertView == null) { 
     holder = new ViewHolder(); 
     convertView = inflater.inflate(R.layout.phrase_row, null); 

     holder.imgViewLogo = (ImageView) convertView.findViewById(R.id.imgViewLogo); 
     holder.txtViewOriginal = (TextView) convertView.findViewById(R.id.txtViewOriginal); 
     holder.txtViewTranslation = (TextView) convertView.findViewById(R.id.txtViewTranslation); 
     holder.txtViewTranscription = (TextView) convertView.findViewById(R.id.txtViewTranscription); 

     convertView.setTag(holder); 
    } 
    else 
     holder=(ViewHolder)convertView.getTag(); 


    holder.txtViewOriginal.setText(original[position]); 
    holder.txtViewTranslation.setText(translation[position]); 
    holder.txtViewTranscription.setText(transcription[position]); 

    return convertView; 
} 

}

Und ich brauche Android4-Stil Multi-Auswahl zu implementieren (lang drücken, dann auf Punkt wählen). Also:

lview1 = (ListView) findViewById(R.id.listViewPhrase); 
    adapter = new PhraseCustomAdapter(this, original, translation, transcription); 
    lview1.setAdapter(adapter); 
    lview1.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 
    lview1.setMultiChoiceModeListener(new MultiChoiceModeListener() { 

     @Override 
     public void onItemCheckedStateChanged(ActionMode mode, int position, 
               long id, boolean checked) { 
      View view; 
      if (checked){ 
       Log.v ("checked?", "YES"); 
       Log.v ("Position", Integer.toString(position)); 

       view = lview1.getChildAt(position); 
       view.setBackgroundColor(Color.LTGRAY); 


       original_list.add (adapter.getItemOriginal(position)); 
       translation_list.add (adapter.getItemTranlation(position)); 
       transcription_list.add (adapter.getItemTranscription(position)); 

       countSelected += 1; 
      } 
      if (!checked){ 
       Log.v ("checked?", "NO"); 
       Log.v ("Position", Integer.toString(position)); 


       for (int i = 0; i < original_list.size(); i++) 
       { 
        if (original_list.get(i) == adapter.getItemOriginal(position)){ 
         original_list.remove (i); 
         translation_list.remove (i); 
         transcription_list.remove (i); 
        } 
       } 
       countSelected -= 1; 
      } 


      mode.setTitle(Integer.toString(countSelected) + " " + getString(R.string.selectItem)); 
     } 

Das Problem ist: Wenn ich lang drückt das Element (zum Beispiel erster Punkt), der siebte Artikel zu markiert ist (durch Hintergrund ändern). Wenn ich versuche, das 7. Objekt zu "heben", stürzt die App ab. Wenn ich versuche, auf den neuesten Artikel zu klicken, stürzt die App ab. Ich habe einige Artikel lesen, wie Ansicht gerendert wird und Gegenstände recyceln, aber ich weiß nicht, jede mögliche Lösung für mein Problem

UPD: LogCat ausgegeben, wenn die 7. Position „unhighlighting“:

V/checked?(24966): YES 
V/Position(24966): 7 
Shutting down VM 
threadid=1: thread exiting with uncaught exception (group=0x2b542210) 
AndroidRuntime(24966): FATAL EXCEPTION: main 
java.lang.NullPointerException 
at com.alextee.phrases.PhraseActivity$1.onItemCheckedStateChanged(PhraseActivity.java:145) 
at android.widget.AbsListView$MultiChoiceModeWrapper.onItemCheckedStateChanged(AbsListView.java:5688) 
at android.widget.AbsListView.performItemClick(AbsListView.java:1040) 
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2522) 
at android.widget.AbsListView$1.run(AbsListView.java:3183) 
at android.os.Handler.handleCallback(Handler.java:605) 
at android.os.Handler.dispatchMessage(Handler.java:92) 
at android.os.Looper.loop(Looper.java:137) 
android.app.ActivityThread.main(ActivityThread.java:4441) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:511) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
at dalvik.system.NativeStart.main(Native Method) 
+0

Können Sie die LogCat Stacktrace bei Post Ihre App stürzt ab, wenn Sie den siebten Eintrag entfernen? – tolgap

+0

Hinzugefügt am Ende des Posts. –

Antwort

10

Listenansicht ist selbst komplex und es ist auch Recycling. Wenn Sie sich die Android-Entwicklervideos für die Listenansicht ansehen, werden Sie mehr über das Listenansichts-Recycling und dessen Probleme erfahren.
Das Problem in Ihrer App ist auf das Recycling der Listenansicht zurückzuführen.
Wenn Sie den Hintergrund eines Listenelements bei Klick oder langem Klick ändern, ändert sich der Hintergrund und wenn dieses Element aus dem sichtbaren Bereich Ihres Geräts gescrollt wird, wird die mit diesem Element verknüpfte Ansicht wiederverwendet und einem anderen Listenelement zugewiesen welches momentan sichtbar ist. Jetzt wird dieser Gegenstand ebenfalls hervorgehoben.
Dieses Bild beschreibt die Listenansicht Recycling:

enter image description here


für ein Element in einer Listenansicht markieren Sie Folgendes tun sollten:

  • auf der Listenansicht Set onItemClickListener.
  • Ändern Sie in der onItemClick() - Methode den Hintergrund der Ansicht und speichern Sie die aktuell markierte Position in der Listenansicht und rufen Sie notifyDataSetChanged() auf dem Listenadapter auf. Der Aufruf von notifyDataSetChanged() ist wichtig, da die aktuellen sichtbaren Elemente neu gezeichnet werden.

-Code für Liste onItemClick sollte wie folgt sein:

grid[pos].setOnItemClickListener(new OnItemClickListener() { 
      @Override 
      public void onItemClick (AdapterView<?> parent, 
        View v, int position, long Id) 
      { 
        highlighted = position; //highlighted is a global variable 
        //container is the root view of the list row layout 
        LinearLayout container = (LinearLayout)v.findViewById(R.id.container); 
        container.setBackgroundResource(R.drawable.highlighted_backg); 
        mListAdapter.notifyDataSetChanged(); 

      } 
    }); 

Die getView() -Methode wie dies umgesetzt werden soll:

public View getView (int position, View convertView, ViewGroup parent) 
{ 
    ViewHolder holder; 

    if(convertView == null) { 
     convertView = inflater.inflate(R.layout.row_item, null); 
     holder = new ViewHolder(); 
     holder.itemName1 = (TextView)convertView.findViewById(R.id.text1); 
     ... 
     holder.container = (LineaLayout)convertView.findViewById(R.id.container); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    if(MainActivity.highlighted == position) { 
     holder.container.setBackgroundResource(R.drawable.highlighted_backg); 
    }else { 
     holder.foodItemCol1.setBackgroundResource(R.drawable.normal_back); 
    } 

    return convertView; 
} 
+0

Hat mir sehr geholfen. Vielen Dank. –

+0

Ausgezeichnet! Beste sehr nette Antwort! – Kay

+0

trotzdem den ful lcode zu posten? Ich versuche zu sehen, wie das zu meiner derzeitigen Situation passt, bin aber ein wenig verloren –

1

Set die Hintergrundfarbe des Artikels in getView() gemäß seinem Status überprüft. Ich weiß nicht, ob du das direkt vom ListView bekommen kannst, sonst könntest du z.B. a Set und halten Sie die aktuell überprüften Positionen dort. Dann in getView() nachsehen, ob die übergebene Position in diesem Set ist, was bedeuten würde, dass es überprüft wird und den Hintergrund entsprechend setzt. Wenn nicht, setzen Sie den Hintergrund auf die ungeprüfte Farbe. Der spätere ist wichtig, da Sie eine recycelte Ansicht erhalten haben könnten, deren Hintergrund auf die Farbe "checked" gesetzt ist.

Ein Beispiel für die Verfolgung von überprüften Artikeln finden Sie here.

Verwandte Themen