2017-08-14 1 views
0

Je veux créer un RecyclerView avec quelques colonnes dans chaque ligne qui doivent être cliquables pour différents événements. Malheureusement, je n'ai pas été en mesure de déterminer quel onclick est cliqué dans la ligne, car ils appellent tous la même méthode. Quelle est la meilleure façon de gérer cela? Devrais-je déclarer plusieurs vues dans la rangée et assigner un onclick à chaque vue?RecyclerView avec plusieurs événements onclick sur les textviews

Voici mon fichier recyclerview.xml:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

    <RelativeLayout 
     android:id="@+id/layout" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <TextView 
      android:text="Description" 
      android:id="@+id/description_textview" 
      android:layout_width="180dp" 
      android:layout_height="wrap_content" 
      android:textSize="18sp" 
      android:textStyle="bold" 
      android:textColor="@color/colorBlack" 
      android:paddingLeft="4dp" 
      /> 

     <TextView 
      android:text="99" 
      android:id="@+id/qty_textview" 
      android:layout_width="60dp" 
      android:layout_height="wrap_content" 
      android:textSize="18sp" 
      android:textStyle="bold" 
      android:textColor="@color/colorBlack" 
      android:layout_toRightOf="@id/description_textview" 
      android:gravity="center" 
      /> 

     <TextView 
      android:text="N" 
      android:id="@+id/accept_textview" 
      android:layout_width="80dp" 
      android:layout_height="wrap_content" 
      android:textSize="18sp" 
      android:textStyle="bold" 
      android:textColor="@color/colorBlack" 
      android:layout_toRightOf="@id/qty_textview" 
      android:gravity="center" 
      /> 

    </RelativeLayout> 

    <View 
     android:layout_width="match_parent" 
     android:layout_height="1dp" 
     android:background="@color/colorBackgroundGray" 
     android:layout_below="@id/layout" 
     style="?android:listSeparatorTextViewStyle" 
     /> 

</RelativeLayout> 

Voici mon code de porte-recyclerview (de recyclerview normal). Je veux remplacer l'événement onLongClick avec une autre colonne:

private class RecyclerHolder2 extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { 
    private TextView descriptionTextView; 
    private TextView qtyTextView; 
    private TextView acceptTextView; 
    private VerificationModel verificationModel; 

    public RecyclerHolder2(View itemView) { 
     super(itemView); 
     itemView.setOnClickListener(this); 
     itemView.setOnLongClickListener(this); 
     descriptionTextView = (TextView) itemView.findViewById(R.id.description_textview); 
     qtyTextView = (TextView) itemView.findViewById(R.id.qty_textview); 
     acceptTextView = (TextView) itemView.findViewById(R.id.accept_textview); 
    } 

    public void bindRecyclerData(VerificationModel newItem) { 
     verificationModel = newItem; 
     descriptionTextView.setText(verificationModel.getDescription()); 
     qtyTextView.setText(verificationModel.getQty()); 
     acceptTextView.setText(verificationModel.getAccept()); 
    } 

    @Override 
    public void onClick(View v) { 
     boolean accepted = true; 
     for (int i = 0; i < mVerifys.size(); i++) { 
      if (mVerifys.get(i).equals(verificationModel)) { 
       if (mVerifys.get(i).getAccept().equals("N")) { 
        mVerifys.get(i).setAccept("Y"); 
        mVerifys.get(i).setSelected(true); 
        Timber.d(verificationModel.getDescription() + " was accepted"); 
       } else { 
        mVerifys.get(i).setAccept("N"); 
        mVerifys.get(i).setSelected(false); 
        Timber.d(verificationModel.getDescription() + " was unaccepted"); 
       } 
      } 
      if (mVerifys.get(i).getAccept().equals("N")) { 
       accepted = false; 
      } 
     } 
     mRecyclerAdapter2.notifyDataSetChanged(); 
     if (accepted) { 
      mAcceptedButton.setEnabled(true); 
     } 

    } 

    @Override 
    public boolean onLongClick (View v) { 
     Timber.d(verificationModel.getDescription() + " will be adjusted"); 
     Intent intent = new Intent(VerificationDetailActivity.this, InvoiceAuthorizationActivity.class); 
     startActivity(intent); 
     return true; 
    } 
} 
+0

Je pense que cela est une bonne façon de résoudre votre problème: https://stackoverflow.com/questions/36369913/how-to-implement-multi-select-in-recyclerview –

Répondre

1

En ce moment, vous configurez vos auditeurs comme ceci:

itemView.setOnClickListener(this); 
    itemView.setOnLongClickListener(this); 

Il existe deux façons différentes, vous pouvez réaliser ce que vous cherchez. Le premier est d'utiliser le même View.OnClickListener pour chaque vue, puis modifiez ce que vous faites en fonction de l'ID de la vue cliquée.

public RecyclerHolder2(View itemView) { 
    super(itemView); 
    ... 
    descriptionTextView.setOnClickListener(this); 
    descriptionTextView.setOnLongClickListener(this); 
    qtyTextView.setOnClickListener(this); 
    qtyTextView.setOnLongClickListener(this); 
    acceptTextView.setOnClickListener(this); 
    acceptTextView.setOnLongClickListener(this); 
    ... 
} 

@Override 
public void onClick(View v) { 
    if (v.getId() == R.id.description_textview) { 
     ... 
    } 
    else if (...) { 
     ... 
    } 
} 

Le deuxième (et celui que je recommande) est d'utiliser un View.OnClickListener() différent pour chaque vue. Cela vous amènera à écrire un peu plus de code, mais il est plus évident que des clics différents font des choses différentes. (Et si vous utilisez RetroLambda, vous pouvez finir par omettre la plus grande partie de la plaquette).

private View.OnClickListener descriptionListener = new View.OnClickListener() { 

    @Override 
    public void onClick(View view) { 
     ... 
    } 
}; 

private View.OnClickListener quantityListener = new View.OnClickListener() { 

    @Override 
    public void onClick(View view) { 
     ... 
    } 
}; 

public RecyclerHolder2(View itemView) { 
    super(itemView); 
    ... 
    descriptionTextView.setOnClickListener(descriptionListener); 
    qtyTextView.setOnClickListener(quantityListener); 
    ... 
} 
0

Vous pouvez appeler getAdapterPosition() de votre ViewHolder, qui renvoie la position de l'élément dans la RecyclerView. Et en utilisant cette position, vous pouvez trouver quelle ligne a été cliquée.

La position renvoyée est la position basée sur le nombre total d'éléments dans le RecyclerView et pas seulement les éléments visibles à l'écran.

+0

Désolé, peut-être ma question WASN n'est pas clair.J'ai déjà un événement qui répond à quelle ligne est cliqué. Je veux répondre à quel bouton COLUMN a été cliqué. – Jay

+0

Au lieu de définir 'clickListener' sur' itemView', vous devez le définir individuellement 'view' (ou column). – Bob

0

Vous devriez écouter à votre recherche TextView. En utilisant itemView.setOnClickListener(this); vous écoutez l'élément entier de l'adaptateur. Vous devez utiliser acceptTextView.setOnClickListener(this); car vous souhaitez écouter une vue spécifique et dans la méthode onClick() vérifier l'élément cliqué.

switch(view.getId()) { 
    case R.id.accept_textview: 
     // do what you want when click accept textview 
    break; 
} 
0

La méthode la plus simple pour gérer les événements de clic est d'utiliser la bibliothèque Butterknife et d'avoir une méthode distincte pour tous les clics. Il enlève tellement de code standard et vraiment facile à utiliser. Voir comment utiliser Butterknife ici - http://jakewharton.github.io/butterknife/

Une autre façon est de fournir différentes méthodes onClick pour chaque TextView. Comme cette

android:onClick="textButton1Clicked" 

Une autre approche est d'obtenir l'ID des TextViews dans le onclick et voir qui, l'utilisateur a cliqué

if (view.getID() == R.id.textView1) { 

} else (view.getID() == R.id.textView2) { 

} else (view.getID() == R.id.textView3) { 

} 

Vous pouvez également utiliser une instruction switch pour une meilleure maintenabilité.