1

J'ai un RecyclerView dans un fragment où chaque ligne a un adaptateur qui gonfle une mise en page qui se présente comme suit: enter image description hereMise à jour TextView en lignes RecyclerView sélectionnées


Je veux accéder à la valeur du EditText (dans le code suivant numberET) de chaque ligne et choisissez la valeur si EditText n'est pas vide.
Comment puis-je faire un cycle sur chaque élément de RecyclerView (je pense à l'intérieur de l'adaptateur) pour avoir ce comportement? Comment puis-je accéder à l'EditText pour chaque élément pour récupérer la valeur et les utiliser dans le fragment?

Adaptateur: `

public class UserFBEditTextAdapter <T extends UserFBEditTextAdapter.ViewHolder> extends UserFBAdapter<UserFBEditTextAdapter.ViewHolder>{ 
public UserFBEditTextAdapter(List<UserFB> users,int layoutId, Context context) { 
    super(users, layoutId, context); 
} 

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

@Override 
public void onBindViewHolder(UserFBAdapter.ViewHolder holder, int position) { 
    holder.userFB = users.get(position); 
    holder.usernameTV.setText(holder.userFB.getName()); 
} 

public class ViewHolder extends UserFBAdapter.ViewHolder { 
    protected EditText numberET; 

    public ViewHolder(View itemView) { 
     super(itemView); 
     numberET = (EditText) itemView.findViewById(R.id.number_et); 
    } 
    } 
}` 

Fragment:

public class ExpenseCustomFragment extends Fragment { 

private OnFragmentInteractionListener mListener; 
private UserFBAdapter adapter; 
private RecyclerView userCustomList; 

public ExpenseCustomFragment() { 
    // Required empty public constructor 
} 

public static ExpenseCustomFragment newInstance() { 
    ExpenseCustomFragment fragment = new ExpenseCustomFragment(); 

    return fragment; 
} 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    // Inflate the layout for this fragment 
    View view = inflater.inflate(R.layout.fragment_expense_custom, container, false); 

    userCustomList = (RecyclerView) view.findViewById(R.id.amountlist_rv); 
    userCustomList.setLayoutManager(new LinearLayoutManager(getContext())); 

    NewExpenseDescriptionActivity activity = (NewExpenseDescriptionActivity) getActivity(); 
    adapter = new UserFBEditTextAdapter(activity.getUsersGroup(), R.layout.listitem_expensecustom, getContext()); 

    userCustomList.setAdapter(adapter); 


    return view; 
} 
    public interface OnFragmentInteractionListener { 
     // TODO: Update argument type and name 
     void onFragmentInteraction(Uri uri); 
    } 
} 

Répondre

1

Vous devez conserver ces données dans une structure de données basée sur une carte, puis, chaque fois que ces valeurs sont nécessaires, itérer sur cette structure de données.

Vous ne pouvez pas compter sur l'enregistrement de ces données dans un ViewHolder, car ViewHolder sont en cours de réutilisation dès que vous effectuez un défilement. Si vous ne sauvegardez pas actuellement les données remplies EditText, vous perdrez ces données si vous avez plusieurs éléments et effectuez un défilement (l'écran correspond à 10 éléments, mais votre carte contient 20 éléments, dès que vous faites défiler jusqu'à 15 article, la valeur EditText pour le premier article sera perdue).

private Map<Integer, String> map = new ArrayMap<>(adapterSize); 

... 

@Override 
public void onBindViewHolder(MyViewHolder holder, int position) { 
    String text = map.get(holder.getAdapterPosition()); 
    // maybe we haven't yet saved text for this position 
    holder.editText.setText(text != null ? text : ""); 
    // updated value in map as soon as the `EditText` in this position changes 
    holder.editText.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 
      map.put(holder.getAdapterPosition(), s.toString()); 
     } 

     @Override 
     public void afterTextChanged(Editable s) { 
     } 
    }); 
} 

Maintenant, vous aurez accès à toutes les valeurs EditText dans votre RecyclerView. Le seul changement que vous pouvez envisager est la mise à jour de la carte après que l'utilisateur a cessé de taper. Actuellement, si l'utilisateur tape "123456789", la carte sera mise à jour 9 fois, alors que nous n'en avons besoin qu'une fois. Une solution facile à cela peut être l'utilisation RxJavadebounce operator combiné avec RxBinding bibliothèque. Cela peut sembler compliqué, mais vous pouvez voir à quel point il est in this answer.

Cela fonctionnera. Mais après avoir effectué le défilement, vous découvrirez bientôt qu'il y a du désordre. C'est parce que chaque fois que onBindViewHolder() est appelé un nouveau TextWatcher est ajouté au EditText qui a déjà un TextWatcher attaché à lui. Ainsi, vous devez également prendre soin d'enlever le TextWatcher après que votre ViewHolder soit recyclé.

Mais il n'y a pas d'API pour supprimer tous les TextWatcher du EditText. Vous pouvez utiliser une implémentation personnalisée EditText montré dans this answer qui effacera tous TextWatcher attaché à cette EditText:

@Override 
public void onViewRecycled(MyViewHolder holder) { 
    holder.editText.clearTextChangeListeners(); 
    super.onViewRecycled(holder); 
} 
+0

Merci! Donc, si je récupère le détenteur de 'RecyclerView', je vais avoir le même problème en raison d'un grand nombre de l'élément dans le' RecyclerView'. –

+0

Impossible de comprendre ce que vous voulez dire. Peux-tu le faire? – azizbekian

+0

Je veux dire, je reçois du 'RecyclerView' le support associé à une position donnée par' recyclerView.findViewHolderForLayoutPosition (position) '. Si je cycle sur le 'ViewHolder' contenu dans le' RecyclerView'and 'RecyclerView' a par exemple 20 éléments, alors que mon' Fragment' peut afficher seulement 4 éléments à la fois, je vais perdre le contenu de 'EditText' qui sont Pas affichée. Ai-je bien compris? –