2016-04-10 49 views
2

Ich habe ein Problem mit beiden ListView und RecyclerViewXamarin, Both Listview und RecyclerView, ein Element klicken, eine andere ausgewählte

Zunächst ich ein ListView erstellt, ist alles in Ordnung. Dann setze ich das Ereignis onClick so, dass jedes Mal, wenn ich auf ein Element klicke, seine Farbe gelb wird. Die Funktion schrieb ich in der MainActivity. Problem ist, dass wenn ich teste, ändert nicht nur dieses Element seine Farbe, aber 2 Elemente ändern. Ich habe gelesen, dass es daran liegt, dass ich die Ansicht wiederverwende.

Also wechsle ich meine Taktik mit RecyclerView statt, aber das gleiche Problem tritt auf. Wenn ich auf ein Element klicke, um seine Farbe zu ändern, ändert sich auch ein anderes Element. Ich nehme an, es liegt daran, dass sowohl ListView als auch RecyclerView diese Elemente wiederverwenden, so dass sie verwirren, wenn ich auf eins klicke.

Ich weiß nicht, wie ich dieses Problem lösen kann, ich fand eine Lösung, ein Array von boolean hinzuzufügen, das markiert, welches Element angeklickt wird, aber es funktioniert nicht. Irgendwelche Ideen Jungs?

So, hier ist der Code MainActivity

class MainActivity : Activity 
    { 
     public RecyclerView recyclerView; 
     public RecyclerView.LayoutManager manager; 
     public RecyclerView.Adapter adapter; 
     List<Row> lst; 

     protected override void OnCreate(Bundle bundle) 
     { 
      base.OnCreate(bundle); 

      // Set our view from the "main" layout resource 
      SetContentView(Resource.Layout.Main); 
      init(); 
      recyclerView = (RecyclerView)FindViewById(Resource.Id.recyclerView); 
      manager = new LinearLayoutManager(this); 
      recyclerView.SetLayoutManager(manager); 
      CustomAdapter adapter = new CustomAdapter(lst, this); 
      adapter.ItemClick += onItemClick; 
      recyclerView.SetAdapter(adapter); 
     } 

     public void init() 
     { 
      lst = new List<Row>(); 
      for (int i = 0; i < 15; i++) 
      { 
       Row row = new Row() { field1="1:43:00", field2="09-Apr-16", field3="KPI/Overflow", field4="Kevin Bacon", field5="Unowned", field6= "People Counting @ IPCAM-ID-C-1-1" }; 
       lst.Add(row); 
      } 
     } 
     public void onItemClick(object sender, int position) 
     { 
      int itemPos = position + 1; 
      //Toast.MakeText(this, "this is " + itemPos, ToastLength.Short).Show(); 
      recyclerView.GetChildAt(position).SetBackgroundColor(Android.Graphics.Color.Green); 
     } 
    } 

Individuelle Adapter

public class CustomAdapter : RecyclerView.Adapter 
    { 
     public Activity _activity; 
     public List<Row> lst; 
     public event EventHandler<int> ItemClick; 

     public CustomAdapter(List<Row> lst, Activity activity) 
     { 
      this.lst = lst; 
      this._activity = activity; 
     } 

     public override int ItemCount 
     { 
      get 
      { 
       return lst.Count; 
      } 
     } 

     public void OnClick(int position) 
     { 
      if (ItemClick!=null) 
      { 
       ItemClick(this, position); 
      } 
     } 

     public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) 
     { 
      MyViewHolder myholder = holder as MyViewHolder; 

      myholder.textView1.Text = lst[position].field1; 
      myholder.textView2.Text = lst[position].field2; 
      myholder.textView3.Text = lst[position].field3; 
      myholder.textView4.Text = lst[position].field4; 
      myholder.textView5.Text = lst[position].field5; 
      myholder.textView6.Text = lst[position].field6; 


     } 

     public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) 
     { 
      View v = this._activity.LayoutInflater.Inflate(Resource.Layout.item, parent, false); 

      TextView tv1 = (TextView)v.FindViewById(Resource.Id.textView1); 
      TextView tv2 = (TextView)v.FindViewById(Resource.Id.textView2); 
      TextView tv3 = (TextView)v.FindViewById(Resource.Id.textView3); 
      TextView tv4 = (TextView)v.FindViewById(Resource.Id.textView4); 
      TextView tv5 = (TextView)v.FindViewById(Resource.Id.textView5); 
      TextView tv6 = (TextView)v.FindViewById(Resource.Id.textView6); 

      MyViewHolder holder = new MyViewHolder(v, OnClick) { textView1 = tv1, textView2 = tv2, textView3 = tv3, textView4 = tv4, textView5 = tv5, textView6 = tv6 }; 
      return holder; 
     } 
    } 

    class MyViewHolder : RecyclerView.ViewHolder 
    { 
     public TextView textView1, textView2, textView3, textView4, textView5, textView6; 
     public View mainView; 

     public MyViewHolder(View view, Action<int> listener) : base(view) 
     { 
      mainView = view; 
      mainView.Click += (sender, e) => listener(base.Position); 
     } 
    } 

ich das Beispiel für die OnClic k-Handler gefolgt auf Xamarin site https://developer.xamarin.com/guides/android/user_interface/recyclerview/

+0

Es ist besser, wenn Sie was Sie bisher getan haben, andere können Sie – Pooya

+0

Dank helfen, ich habe den Code hinzugefügt – LaXuanLinh

+0

Ihre xml teilen auch für recyclerview bitte item – Pooya

Antwort

2

Ihr Problem ist mit Ihrem Code. Sie senden die richtige Position an Ihren Ereignishandler, aber Sie erhöhen es dann in der Aktivität um eins. Beide Enden sollten den 0-basierten Index der Artikelposition verwenden. Es besteht keine Notwendigkeit, um eins zu erhöhen.

Um die Hintergrundfarbe des ausgewählten Elements zu ändern, können Sie einen Selektor in XML verwenden, sodass Sie dies nicht einmal im Code ausführen müssen.

Hier ist ein Beispiel.

row_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_selected="true" android:color="@android:color/green" /> 
    <item android:state_selected="false" android:color="@android:color/transparent"/> 
</selector> 

row_content.axml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/row_layout_parent" 
    android:background="@drawable/row_selector"> 

    <!-- your row content --> 

</LinearLayout> 

Dann würde Ihre Ansicht Halter diese aktualisiert werden ...

class MyViewHolder : RecyclerView.ViewHolder 
{ 
    public TextView textView1, textView2, textView3, textView4, textView5, textView6; 
    public View mainView; 
    private LinearLayout _layoutParent; 

    public MyViewHolder(View view, Action<int> listener) : base(view) 
    { 
     mainView = view; 
     _layoutParent = mainView.FindViewById<LinearLayout>(Resource.Id.row_layout_parent); 
     _layoutParent.Click += (sender, e) => _layoutParent.Selected = true; 
    } 
} 

Ich entfernte die anderer Klick e Entlüftung. Wenn Sie es aus anderen Gründen noch benötigen, können Sie es hinzufügen, aber es ist nicht notwendig, nur die Hintergrundfarbe des Elements festzulegen, wenn Sie ausgewählt sind.

+0

Vielen Dank für Ihre Antwort, ich habe noch nie von XML-Selektor gehört, also war alles, was ich kam Click Event Handler. Eigentlich muss ich die Objektansicht ändern, wenn es angeklickt wird, ich habe nicht gefunden, wie es geht, ich habe setBackgroundResource und Inflater in Handler versucht, aber nicht funktioniert. Ich denke also, teste das Item-Click-Event zuerst, indem ich jedes Mal, wenn ich klicke, seine Farbe ändere. Haben Sie ein Beispiel dafür, wie Sie mit dem Selektor die Objektansicht ändern können, wenn Sie darauf klicken? – LaXuanLinh

+0

Mein Code oben sollte funktionieren. Die Datei 'row_selector.xml' sollte sich im Verzeichnis' drawable' befinden. –

0

Für Listview sollten Sie choiceMode wie folgt setzen.

listView.ChoiceMode = ChoiceMode.Single; 

Hoffe, dass es Ihnen helfen:) -