Pumpanickel
Pumpanickel

Reputation: 91

How to get the Value out of an RecyclerView item

I have a Fragment which carries a Button and a RecyclerView, set up by an RecyclerView Adapter. In the RecyclerView are several Items, one of it is a EditText. Now I want that when the Button is clicked(which is NOT in the RecyclerView object), that I get the values of the EditTexts.

I already tried to get the recyclerView.getItemAtPosition() but there is no function like that, also tried the same for the adapter. So I would need something like ArrayList s.add(recyclerView.getItemAtPosition(position).getEditText().getText().toString());

This is my Adapter:

public class RVSetAdapter extends RecyclerView.Adapter<RVSetAdapter.ViewHolder> {

private Exercise exercise;

public static class ViewHolder extends RecyclerView.ViewHolder {

    public EditText et_weight;
    public TextView tv_sets,tv_indication;

    public ViewHolder(@NonNull final View itemView) {

        super(itemView);
        tv_sets = itemView.findViewById(R.id.tv_sets);
        tv_indication = itemView.findViewById(R.id.tv_indication);
        et_weight = itemView.findViewById(R.id.et_weight);
    }

}

public RVSetAdapter(Exercise exercise) {
    this.exercise = exercise;
}

@NonNull
@Override
public RVSetAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rv_set,viewGroup,false);
    RVSetAdapter.ViewHolder vh_set = new RVSetAdapter.ViewHolder(view);

    return vh_set;
}

@Override
public void onBindViewHolder(@NonNull final RVSetAdapter.ViewHolder viewHolder,final int i) {
    if(exercise.getKind() == 80) {
        viewHolder.tv_sets.setText("");
        viewHolder.tv_indication.setText("sec.");
    }else if(exercise.getKind() == 90) {
        viewHolder.tv_sets.setText("");
        viewHolder.tv_indication.setText("min.");
    }else {
        viewHolder.tv_sets.setText(Integer.toString(i + 1) + ".");
    }
    viewHolder.et_weight.setText(Integer.toString(exercise.getWeights().get(i)));
}

@Override
public int getItemCount() {
    return exercise.getWeights().size();
}

}

this is my Fragment:

final View view = layoutInflater.inflate(R.layout.fragment_exercise, container,false);

    ImageView iv_exercise = view.findViewById(R.id.iv_exercise);
    ImageView iv_musclekind = view.findViewById(R.id.iv_musclekind);
    ImageView iv_save = view.findViewById(R.id.iv_save);
    TextView tv_exercisename = view.findViewById(R.id.tv_exercisename);
    TextView tv_exercisedescription = view.findViewById(R.id.tv_exercisedescription);

    iv_exercise.setImageResource(exercises.get(position).getImage());
    iv_musclekind.setImageResource(exercises.get(position).getMusclekindImage());
    tv_exercisename.setText(exercises.get(position).getName());
    tv_exercisedescription.setText(exercises.get(position).getDescription());

    iv_save.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //here I want to get the Values of the EditTexts and put them into an Array
        }
    });

    recyclerView = view.findViewById(R.id.rv_sets);
    recyclerView.setHasFixedSize(true); //maybe change this
    layoutManager = new LinearLayoutManager(view.getContext());
    adapter = new RVSetAdapter(exercises.get(position));
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(adapter);

    container.addView(view);

    return view;

I don't have any ideas to go on so I would appreciate your help. If there is any uncertainty with my description of the problem please don't hesitate to ask.

Greetings Alexander

Upvotes: 3

Views: 4576

Answers (3)

advice
advice

Reputation: 5988

With RecyclerView, you have to understand that your EditTexts will be recycled. For example, if you have a list of 200 items, and it shows 2 items at one time, you will only ever have 2 EditText. They will reuse the higher EditText for the lower elements.

For example, here is a list that contains EditText showing only 2 at a time, and as the user scrolls, it will recycle and reuse them.

  1. EditText A
  2. Edittext B
  3. EditText A (recycled)
  4. EditText B (recycled)
  5. ....

This means you cannot just loop over all the elements later and get the values, as they don't store their values.

So, what you want to do, is when the user modifies an EditText, you want to store that value right away. You can do this by adding a TextWatcher to your EditText.

Note - I did assume you store your weights as String values, so I just took the value from the EditText and stored it into your Exercise Object. You may want to convert it before that.

public class RVSetAdapter extends RecyclerView.Adapter<RVSetAdapter.ViewHolder> {

    private Exercise exercise;

    // ...

    @Override
    public void onBindViewHolder(@NonNull final RVSetAdapter.ViewHolder viewHolder,final int i) {
        // ...

        viewHolder.et_weight.setText(Integer.toString(exercise.getWeights().get(i)));
        viewHolder.et_weight..addTextChangedListener(new TextWatcher() {

            public void afterTextChanged(Editable s) {
                // This will be the text from the EditText
                String text = s.toString();

                // Store the value back into your exercise Object.
                exercise.getWeights().get(i).setWeight(text);
            }

            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

            public void onTextChanged(CharSequence s, int start, int before, int count) {}
        });
    }

    // ...

    // Add a method for easy access to your weights.
    public ArrayList<String> getWeights() {
        return exercise.getWeights();
    }
}

And now, within your Fragment, you can easily get the values out of your RVSetAdapter.

public View onCreateView() {
    final View view = layoutInflater.inflate(R.layout.fragment_exercise, container,false);

    // ... 

    iv_save.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Use the method we added to your adapter to return the weights.
            ArrayList<String> weights = adapter.getWeights();
        }
    });

    // ...

    return view;
}

Upvotes: 8

vishal mathur
vishal mathur

Reputation: 13

I think you can create static button and you can then access that button in your adapter then implement the functionality on the onclick of your button.

static Button btn;

Then implement like this in your adapter...

btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
         for(int i=0;i<arraylist.size();i++)
         {
              arr[i]= holder.edit_Text.getText().toString();
         }

        }
});

and put this onclick in your onbindviewholder method.

Upvotes: 0

MrFisherman
MrFisherman

Reputation: 738

I think you should use ArrayList in Adapter class to keep your items (or just Strings of EditText components). Add String to ArrayList in your onBindViewHolder() after you set text for editext. Then make a function which will get item from your ArrayList like:

public String getItem(int position){
    arrayList.get(position);
}

and call it from your onClick() function in Fragment.

Upvotes: 0

Related Questions