2016-07-14 9 views
1

Ich benutze eine listview, die einige Elemente binden und beim Klicken ich wollte Ansicht von listview aktualisieren, aber wenn ich es scrollen, wird dieser Effekt auf andere Ansichten angewendet, die zufällig Position ändert, wenn mehr Zeit blättern.Listview view update zufällig auf scroll

Dies ist mein Code.

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:orientation="vertical"> 
<ListView 
    android:id="@+id/twvTest" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"></ListView> 
</LinearLayout> 

MainActivity.java

public class MainActivity extends Activity { 
ListView twvTest; 
ArrayList<DataModel> dataModels; 
NameListAdapter adapter; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    twvTest = (ListView) findViewById(R.id.twvTest); 

    dataModels = new ArrayList<>(); 
    adapter = new NameListAdapter(MainActivity.this, dataModels); 
    twvTest.setAdapter(adapter); 
    twvTest.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
      for (int i = 0; i < twvTest.getCount(); i++) { 
       TextView txtName = (TextView) view.findViewById(R.id.txtName); 
       if (i == position) { 
        txtName.setTextColor(Color.GREEN); 
        txtName.setBackgroundColor(Color.YELLOW); 
       } else { 
        txtName.setTextColor(Color.YELLOW); 
        txtName.setBackgroundColor(Color.GREEN); 
       } 
      } 
     } 
    }); 
    fillList(); 
} 

private void fillList() { 
    for (int i = 0; i < 30; i++) { 
     DataModel dataModel = new DataModel(); 
     dataModel.setName("Name : " + i); 
     dataModels.add(dataModel); 
    } 
    adapter.notifyDataSetChanged(); 
    } 
} 

NameListAdapter.java

public class NameListAdapter extends BaseAdapter { 
Context context; 
ArrayList<DataModel> dataModels; 
LayoutInflater inflater; 

public NameListAdapter(Context context, ArrayList<DataModel> dataModels) { 
    this.context = context; 
    this.dataModels = dataModels; 
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

@Override 
public int getCount() { 
    return dataModels.size(); 
} 

@Override 
public Object getItem(int position) { 
    return dataModels.get(position); 
} 

@Override 
public long getItemId(int position) { 
    return dataModels.indexOf(getItem(position)); 
} 

private class Holder { 
    TextView txtName; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    Holder holder; 
    if (convertView == null) { 
     holder = new Holder(); 
     convertView = inflater.inflate(R.layout.test_adapter_raw, parent, false); 
     holder.txtName = (TextView) convertView.findViewById(R.id.txtName); 
     convertView.setTag(holder); 
    } else { 
     holder = (Holder) convertView.getTag(); 
    } 
    holder.txtName.setText(dataModels.get(position).getName()); 
    return convertView; 
    } 
} 

test_adapter_raw.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="100dp" 
android:background="#ffffff" 
android:orientation="vertical"> 

<TextView 
    android:id="@+id/txtName" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_margin="5dp" 
    android:background="#949494" 
    android:gravity="center" 
    android:text="Text" 
    android:textAppearance="?android:attr/textAppearanceMedium" 
    android:textColor="#fff" 
    android:textStyle="bold" /> 
</LinearLayout> 

DataModel.java

public class DataModel { 
String name; 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 
} 
+0

Hallo Techsky folgt. Da die Ansicht wiederverwendet wird, können Sie ihre Farbe nicht direkt in einem onClickListener ändern ... Sie müssen Ihren Adapter aktualisieren und dann wird der Adapter die Farben der Ansicht steuern ... – W0rmH0le

Antwort

0

Dies geschieht, weil ListView Ihre Ansichten rezykliert. Daher wird dieselbe Ansicht für andere Positionen verwendet. Um das Durcheinander zu vermeiden, setzen Sie einen Clicklistener in Ihrem Adapter und behandeln Sie die Farbe im Holder.

public class NameListAdapter extends BaseAdapter { 
Context context; 
ArrayList<DataModel> dataModels; 
LayoutInflater inflater; 

public NameListAdapter(Context context, ArrayList<DataModel> dataModels) { 
this.context = context; 
this.dataModels = dataModels; 
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

@Override 
public int getCount() { 
    return dataModels.size(); 
} 

@Override 
public Object getItem(int position) { 
    return dataModels.get(position); 
} 

@Override 
public long getItemId(int position) { 
    return dataModels.indexOf(getItem(position)); 
} 

private class Holder { 
    TextView txtName; 
    LinearLayout root_layout; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    Holder holder; 
    if (convertView == null) { 
     holder = new Holder(); 
     convertView = inflater.inflate(R.layout.test_adapter_raw, parent, false); 
     holder.txtName = (TextView) convertView.findViewById(R.id.txtName); 
     holder.root_layout=(LinearLayout)convertView.findViewById(R.id.root_layout) 
     convertView.setTag(holder); 
    } else { 
     holder = (Holder) convertView.getTag(); 
    } 
    holder.txtName.setText(dataModels.get(position).getName()); 

    holder.root_layout.setOnClickListener(new View.OnClickListener(){ 

       holder.txtName.setTextColor(Color.GREEN); 
       holder.txtName.setBackgroundColor(Color.YELLOW); 

       //implement your own logic to remove color on second click 
    }); 


    return convertView; 
    } 
} 

eine ID für Ihr Listitem Wurzel Layout Verwendung als

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/root_layout" 
android:layout_width="match_parent" 
android:layout_height="100dp" 
android:background="#ffffff" 
android:orientation="vertical"> 

<TextView 
android:id="@+id/txtName" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:layout_margin="5dp" 
android:background="#949494" 
android:gravity="center" 
android:text="Text" 
android:textAppearance="?android:attr/textAppearanceMedium" 
android:textColor="#fff" 
android:textStyle="bold" /> 
</LinearLayout> 
+0

Entfernen Sie den OnItemClickListener, wenn Sie dies verwenden -> Verknüpfen von Klicks mit Viewholder-Mitglieder verhindert jumbling – Kushan

+0

Vielen Dank für Ihre Antwort und wertvolle Mühe, aber ich muss andere Listenansicht auf Element klicken dieser Listenansicht basierend auf ihren Wert binden. Und das ist in MainActivity das ist, warum ich Update-Ansicht in Aktivität und dann Basis auf diesen Wert, den ich Wert eines anderen Listview filtern muss. –

+0

Hmm .. Entschuldigung konnte dir nicht helfen. Wie auch immer, jetzt weißt du, warum das Rumoren passiert ist. Der Umweg ist die Verwendung des ViewHolders, um Farben usw. einzustellen. Warum nicht einen RecyclerView ausprobieren, es macht zwingend einen ViewHolder und ist viel effizienter als ein Listview. – Kushan

0

Sie können die Ansicht direkt während onClick() ändern, da die Ansicht wieder verwendet wird ....

So können Sie die Farbe einer Ansicht ändern, wird diese Ansicht sein wahrscheinlich in einer anderen Position wiederverwendet und dann wird eine andere Position die farbige Ansicht anzeigen.

Sie müssen die Ansichtsfarbe in Ihrem Adapter steuern. Auf diese Weise aktualisiert Ihre Aktivität nur den Adapter und ruft notifyDataSetChanged() auf, damit ListView den Inhalt aktualisiert.

Sie Aktivität Code

twvTest.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
    @Override 
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
     // Inform the adapter that following item should be displayed in Yellow 
     adapter.displayViewInYellow(position); 
     adapter.notifyDataSetChanged();   
    } 
}); 

Ihr Adapter-Code

public class NameListAdapter extends BaseAdapter { 

    boolean [] arrayOfViewsThatMustShowYellow; 

    public NameListAdapter(Context context, ArrayList<DataModel> dataModels) { 
     ... 
     arrayOfViewsThatMustShowYellow = new boolean[getCount()]; 
    } 

    public void displayViewInYellow(int position) { 
     // boolean array to track view that must be displayed in Yellow 
     arrayOfViewsThatMustShowYellow[position] = true; 
    } 

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

     ..... 

     // Following code could be simplified to convertView.setEnabled(arrayOfViewsThatMustShowYellow[position]) 
     if(arrayOfViewsThatMustShowYellow[position] == true) { 
      holder.txtName.setTextColor(Color.GREEN); 
      holder.txtName.setBackgroundColor(Color.YELLOW); 
     } else { 
      holder.txtName.setTextColor(Color.YELLOW); 
      holder.txtName.setBackgroundColor(Color.GREEN); 
     } 
    } 
} 

Hinweis

Dies ist ein Beispiel ... Es ist nur die Idee zu teilen wie es geht ... Denken Sie daran, wenn Sie eine Ansicht aktualisieren müssen, müssen Sie diese Änderung innerhalb des Adapters verfolgen (und niemals außerhalb - wie in ClickListeners oder Aktivität).

+0

Hallo danke für die Mühe. Ich wollte wissen, was das Problem in Adapter ist.Wie Sie gesagt haben, dass wir alle Listener ListView innerhalb Adapter tun müssen, aber in meiner App gibt es eine andere Aktivität, in der ich Gridview und seine alle Listener in Adapter verwendet, aber es ist das gleiche Problem aufgetreten. Sie können den Link sehen [Gridview Adapter Problem] (http://stackoverflow.com/questions/38247794/listview-update-another-raw-on-update-of-selected-raw) –

0

Wenn die Namen einen leeren Wert haben, wird der Viewholder den ramdom-Wert für it.set setzen "" für den leeren Namen kann vielleicht passen.

+0

Aber ich habe keinen leeren Namen –

+0

Problem kommt auf Rolle –