2016-12-08 15 views
0

Es ist mein dritter Tag, der sich jetzt mit der Handhabung meiner View-Klicks beschäftigt. Ich benutzte ursprünglich ListView, dann wechselte ich zu RecyclerView. Ich habe auf meinem row_layoutandroid:onclick Elemente zu jedem Steuerelement hinzugefügt, und ich bin Umgang mit ihnen in meinem MainActivity wie folgt aus:RecyclerView - Holen Sie sich Position in Activity statt RecyclerViewAdapter

public void MyMethod(View view) {} 

In meiner alten ListView Implementierung habe ich setTag(position) getan in der Lage sein es in MyMethod zu erhalten, indem dies zu tun Darin:

Integer.parseInt(view.getTag().toString()) 

Das funktionierte gut ohne Probleme. Aber jetzt habe ich es mit RecyclerView und gezwungen, die ViewHolder zu verwenden, die keine setTag Methode bietet. Nach der Suche nach 2 Stunden, habe ich festgestellt, dass die Menschen setTag wie folgt verwenden:

holder.itemView.setTag(position) 

Das war akzeptabel. Obwohl, wenn ich versuche, den Wert aus der MyMethod Funktion zu erhalten mit der Zeile:

Integer.parseInt(view.getTag().toString()) 

die Anwendung abstürzt. Ich habe gelesen, mehrere Implementierung von onclick Handhabung in dem Adapter, der funktioniert, aber ich muss die MainActivity verwenden, weil ich etwas verwende, das für diese Aktivität einzigartig ist.

TL; DR Ich möchte auf einfache Weise die Position der angeklickten Zeile an meine MainActivity senden.

Edit: Ich entschuldige mich für die Verwirrung, da mein Thema nicht sehr gründlich war. Ich habe eine RecyclerView und einen Adapter. Der Adapter ist mit meinem row_layout verbunden. Diese row_layout xml hat eine Wurzel LinearLayout. Darin befindet sich eine TextView, eine weitere LinearLayout (die zwei TextViews hat) und eine Button (der Einfachheit halber). Ich will nicht leiden für den Umgang mit den Klicks auf RecylerView wie ich mit der ListView getan habe. Also, ich habe beschlossen, ein android:onclick für jedes Steuerelement hinzufügen, dann verknüpfen TextView und LinearLayout zu einer einzigen Methode und verknüpfen Sie die Button (und zukünftige Button s) zu ihren einzigartigen Methoden. Was ich vermisse, ist, dass ich in der Lage sein möchte, die Position auf jeder der Empfangsmethoden auf meiner MainActivity zu erzählen. Wenn ich alles verbinden muss, was vom Adapter kommt und in den MainActivity zu einem einzigen onclick-Handler geht, so sei es. Wie aber würde ich sagen, welches Steuerelement den Klick ausgelöst hat?

Edit 2: Die gewünschte Layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:onClick="MyMethod" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal" 
    android:weightSum="1"> 
    <TextView 
     android:id="@+id/letter" 
     android:onClick="MyMethod" 
     android:layout_width="60dp" 
     android:layout_height="fill_parent" 
     /> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:onClick="MyMethod" 
     android:layout_width="200dp" 
     android:layout_height="wrap_content" 
     android:orientation="vertical"> 

     <TextView 
      android:id="@+id/firstname" 
      android:onClick="MyMethod" 
      android:layout_width="fill_parent" 
      android:layout_height="17dp" /> 
     <TextView 
      android:id="@+id/longname" 
      android:onClick="MyMethod" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" /> 

    </LinearLayout> 
    <Button 
     android:text="Test" 
     android:onClick="OtherMethod" 
     android:layout_width="match_parent" 
     android:layout_height="fill_parent" 
     android:id="@+id/process"/> 
</LinearLayout> 
+0

Innerhalb Halter können Sie getAdapterPosition tun, um die bestimmte Position des Artikels zu erhalten. Hier müssen Sie 'setTag()' und 'getTag()' nicht machen. –

+0

Ja, ich kann das im Adapter verwenden. Obwohl, was ich will, ist in der Lage, die Position in der MainActivity nicht innerhalb des Adapters selbst zu bekommen. –

+0

Haben Sie hier einige Antworten gelesen? http://stackoverflow.com/questions/24885223/why-doesnt-recyclerview-have-onitemclicklistener-and-how-recyclerview-is-dif –

Antwort

5

Sie dies für eine itemclicklistener durch die Schaffung einer Schnittstelle in Ihrem Adapter und dann können Sie onItemClickListener von Ihrem MainActivity gesetzt erreichen können.

Irgendwo in Ihrem RecyclerViewAdapter Sie die folgende müssten:

private onRecyclerViewItemClickListener mItemClickListener; 

public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) { 
     this.mItemClickListener = mItemClickListener; 
    } 

    public interface onRecyclerViewItemClickListener { 
     void onItemClickListener(View view, int position); 
    } 

Then (als innere Klasse in meinem Adapter hinzugefügt, die ich habe) in Ihrem ViewHolder, können Sie den Hörer auf die Komponenten anwenden würden Sie‘ d wie der Benutzer klicken, etwa so:

class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 
     public ImageView imageview; 

     RecyclerViewHolder(View view) { 
      super(view); 
      this.imageview = (ImageView) view 
        .findViewById(R.id.image); 
      imageview.setOnClickListener(this); 
     } 

     @Override 
     public void onClick(View v) { 
      if (mItemClickListener != null) { 
       mItemClickListener.onItemClickListener(v, getAdapterPosition()); 
      } 
     } 
    } 

Dieses Beispiel zeigt eine onClickListener innerhalb eines ViewHolder auf das Bild angewendet wird.

recyclerView.setAdapter(adapter);// set adapter on recyclerview 
      adapter.notifyDataSetChanged();// Notify the adapter 
      adapter.setOnItemClickListener(new RecyclerViewAdapter.onRecyclerViewItemClickListener() { 
       @Override 
       public void onItemClickListener(View view, int position) { 
//perform click logic here (position is passed) 
        } 
       }); 

diesen Code zu implementieren, Sie würden setOnItemClickListener zu Ihrem Adapter innerhalb MainActivity wie oben gezeigt.

EDIT

Da die View in die OnItemClickListener geleitet zu werden, können Sie eine switch Anweisung innerhalb des Zuhörers durch, um sicherzustellen, dass die richtige Logik auf der rechten Seite Komponente durchgeführt wird. Alles, was Sie tun müssten, ist die Logik aus der MyMethod Funktion zu kopieren und in die Komponente einzufügen, auf die sie angewendet werden soll.

Beispiel:

recyclerView.setAdapter(adapter);// set adapter on recyclerview 
       adapter.notifyDataSetChanged();// Notify the adapter 
       adapter.setOnItemClickListener(new RecyclerViewAdapter.onRecyclerViewItemClickListener() { 
        @Override 
        public void onItemClickListener(View view, int position) { 
     Switch (view.getId()) { 
      case R.id.letter: 
       //logic for TextView with ID Letter here 
      break; 
      case R.id.firstname: 
       //logic for TextView with ID firstname here 
      break; 
      .... 
      //the same can be applied to other components in Row_Layout.xml 
     } 
         } 
        }); 

Sie müssen auch etwas in den ViewHolder ändern. anstatt die OnClickListener auf einen ImageView Anwendung, müssen Sie wie so auf die ganze Reihe gelten:

RecyclerViewHolder(View view) { 
       super(view); 
       this.imageview = (ImageView) view 
         .findViewById(R.id.image); 
       view.setOnClickListener(this); 
      } 

EDIT 2

Erläuterung:

Also, mit jedem RecyclerView. Sie benötigen drei Komponenten, die RecyclerView, RecyclerViewAdapter und die RecyclerViewHolder. Diese definieren die tatsächlichen Komponenten, die der Benutzer sieht (RecyclerView) und die Elemente in dieser Ansicht. Über den Adapter wird alles zusammengefügt und die Logik implementiert. Die Ins und Outs dieser Komponenten werden von Bill Phillips mit dem Artikel RecyclerView Part 1: Fundamentals For ListView Experts bei Big Nerd Ranch schön erklärt.

aber weiter die Logik hinter den Click-Ereignissen zu erklären, es ein interface im Grunde ist die Verwendung Ihres MainActivity passieren Informationen vom RecyclerViewAdapter zum RecyclerViewHolder zu. Wenn Sie also dem Lebenszyklus des RecyclerView Adapters folgen, wird es Sinn machen.

Der Adapter wird in Ihrem MainActivity initialisiert, der Konstruktor des Adapters würde dann mit den übergebenen Informationen aufgerufen. Die Komponenten würden dann über die Methode OnCreateViewHolder in den Adapter geleitet werden. Dies teilt dem Adapter selbst mit, wie die Liste aussehen soll. Die Komponenten in diesem Layout müssten dann einzeln initialisiert werden, wo die ViewHolder ins Spiel kommt.Wie Sie alle anderen Komponenten sehen können, die Sie in Ihrem Activities initialisieren würden, machen Sie das gleiche in dem ViewHolder aber weil das RecyclerViewAdapter das ViewHolder aufbläst, können Sie sie glücklich innerhalb Ihres Adapters verwenden, wie von Zeeshan Shabbir gezeigt. Aber für dieses Beispiel möchten Sie, dass mehrere Komponenten unterschiedliche Logik für jede einzelne in Ihrer Klasse MainActivity anwenden.

Das ist, wo wir den Klick-Listener als globale Variable erstellen (also sowohl von der ViewHolder und der Adapter zugegriffen werden kann) die Aufgabe des Adapters in diesem Fall ist der Zuhörer durch die Schaffung eines Interface existiert, um sicherzustellen, dass Sie den Hörer initialisieren durch.

public interface onRecyclerViewItemClickListener { 
    void onItemClickListener(View view, int position); 
} 

Nachdem Sie die Informationen definiert haben würden Sie die Schnittstelle gerne halten (die Komponente EG und seine Position), können Sie dann eine Funktion erstellen, in dem der Adapter die Logik von Ihrem Activity anzuwenden rufen (So würden Sie View.OnClickListener genannt), aber durch die Erstellung eines setOnItemClickListener können Sie es anpassen.

public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) { 
     this.mItemClickListener = mItemClickListener; 
    } 

Diese Funktion muss dann onRecyclerViewItemClickListener Variable an sie übergeben, wie in Ihrem MainActivity gesehen. new RecyclerViewAdapter.onRecyclerViewItemClickListener() in diesem Fall ist es die Schnittstelle, die Sie vor dem Hinein, dass die mit der Methode würde die angerufene

@Override 
       public void onItemClickListener(View view, int position) { 
       } 

ist daher umgesetzt werden muß.

Alle ViewHolder hat in diesem Szenario ist es, die Informationen weitergeben (die Komponenten es sich von selbst, und die Position ist) in die onItemClickListener mit den angeschlossenen Komponenten (in der onClick Funktion), um die tatsächlichen Klick Funktionalität abzuschließen.

Wenn Sie möchten, dass ich die Erklärung auf jeden Fall aktualisieren, lassen Sie es mich wissen.

+0

Dies ist wirklich eine nette Lösung. Aber ich glaube nicht, dass es für meinen Fall funktionieren wird. Ich könnte falsch liegen. obwohl ich noch lerne. Nach meinem Verständnis wird dies nur für eine Kontrolle funktionieren. Wenn ich es auf mehrere Steuerelemente (Button, TextView, etc.) festlegen. Sie werden alle zu einem Klick-Handler auf meiner MainActivity führen. Also würde ich nicht unterscheiden können, welche Kontrolle den Klick bekommen hat und mit ihrer Logik umgehen. Ich verwende die Option android: onclick, um die Klicks auf mehrere Methoden meiner Aktivität zu erhalten. Wenn ich den SetTag nur in meinem Fall zum Laufen bringen kann, würde das mein Leiden beenden. –

+0

Sie können die Logik auf mehrere Fälle anwenden, dies ist nur ein Beispiel für ein Bild. Sie sollten Onclicklistener wirklich zu den Komponenten innerhalb der MainActivity hinzufügen, die für diese Aktivität (z. B. XML) eindeutig sind, und ich würde sagen, diese Logik auf alle Elemente anwenden, die sich in dem RecyclerView befinden. Es gibt keinen eleganten Weg, einen RecyclerView ohne ViewHolder für das Layout der Elemente im RecyclerView zu verwenden. – BIW

+0

Können Sie das XML für das row_layout hinzufügen? – BIW

1

Ich denke, Sie sind mit der Verarbeitung mehrerer Klicks auf ReceylerView fest, wenn das der Fall ist, dann lassen Sie mich Ihnen die ein Code-Snippet aus meinem Projekt freigeben. Das ist, wie ich das Click-Griff in RecyclerView

public class ExploreItemAdapter extends RecyclerView.Adapter<ExploreItemAdapter.ViewHolder> { 
private WSResponseDTO<Data> wsResponseDTO; 

public ExploreItemAdapter(WSResponseDTO<Data> wsResponseDTO) { 
    this.wsResponseDTO = wsResponseDTO; 
} 

@Override 
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.consumer_dashboard_item, parent, false); 
    return new ViewHolder(view); 
} 

@Override 
public void onBindViewHolder(ViewHolder holder, final int position) { 
    holder.tvCompanyName.setText(wsResponseDTO.getData().getPosts().get(position).getStoreInfo().getStoreName()); 
    holder.tvBranchName.setText("(" + wsResponseDTO.getData().getPosts().get(position).getStoreInfo().getBranchName() + ")"); 
    holder.tvLikes.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getFavoriteCount() + ""); 
    holder.tvShares.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getShareCount() + ""); 
    holder.validity.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getValidFrom() + "-" + 
      wsResponseDTO.getData().getPosts().get(position).getPost().getValidTo()); 
    holder.sTime.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getTime()); 
    holder.tvTitle.setText(wsResponseDTO.getData().getPosts().get(position).getPost().getHeading()); 
    holder.cardView.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      Toast.makeText(view.getContext(), "card is touched", Toast.LENGTH_SHORT).show(); 
      view.getContext().startActivity(new Intent(view.getContext(), ConsumerDetailOfferActivity.class).putExtra("post", wsResponseDTO.getData().getPosts().get(position))); 
     } 
    }); 
} 

@Override 
public int getItemCount() { 
    return wsResponseDTO.getData().getPosts().size(); 
} 

public class ViewHolder extends RecyclerView.ViewHolder { 
    @BindView(R.id.card_explore) 
    CardView cardView; 
    @BindView(R.id.tv_company_name) 
    TextView tvCompanyName; 
    @BindView(R.id.tv_branch_name) 
    TextView tvBranchName; 
    @BindView(R.id.tv_title) 
    TextView tvTitle; 
    @BindView(R.id.tv_like_count) 
    TextView tvLikes; 
    @BindView(R.id.tv_share_count) 
    TextView tvShares; 
    @BindView(R.id.tv_validity) 
    TextView validity; 
    @BindView(R.id.tv_sTime) 
    TextView sTime; 


    public ViewHolder(View itemView) { 
     super(itemView); 
     ButterKnife.bind(this, itemView); 
    } 
} 
} 

Sie setzen Zuhörer auf ein beliebiges Element in bindViewHolder klicken können(), wie ich für cardView tat ich hoffe, dass dies einige helfen.

+0

Ich bin nicht mit der Multiple-Click-Handhabung per se festgefahren. Was ich brauche, ist eine einfache Möglichkeit zu finden, die RecyclerView-Klickposition meiner MainActivity zu präsentieren, während ich weiß, welche Kontrolle sie verursacht hat. Ich kann die Klickbehandlung für alle meine Steuerelemente implementieren und dies innerhalb des Adapters tun, und ich würde keine Probleme behandeln müssen, wenn ich nicht eine Ressource verwenden müsste, die nur innerhalb der MainActivity verfügbar ist. Danke für die Rückmeldung. Sehr geschätzt. –

+0

Überlegen Sie, diese Ressource in Adapter zu übergeben. –

Verwandte Themen