How to get Recyclerview item's value in Android? - android

Recyclerview has 4 items i.e; textView1, textView2, EditText1 and Checkbox1.
Recyclerview has got 24 rows as well. EditText is invisible on initial stage thenit will be visible only when the corresponding checkbox checked by the user. EditText accepts only numbers.
The app is working fine so far this much.
Now I need to get value of all EditTexts and need to display it on another Textview which is not in the part of Recyclerview?
Recyclerview Screenshot- Output Link
Code Samples.
ExamFragment.java
public class ExamFragment extends Fragment {
RecyclerView recyclerView;
ExamFragmentAdapter adapter;
ArrayList<tblChapters> datalistChapters = new ArrayList<>();
TextView txtQcount,txtQCounttotal;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v= inflater.inflate(R.layout.fragment_exam, container, false);
txtQCounttotal=(TextView) v.findViewById(R.id.txtQCounttotal);
txtQcount=(TextView) v.findViewById(R.id.txtQCount);
recyclerView=(RecyclerView)v.findViewById(R.id.recycler_view);
conn = new ConnectionClass(); //connection initialisation
datalistChapters = conn.getChaptersAndCount(modeid, subjectid);
adapter = new ExamFragmentAdapter(datalistChapters, getActivity());
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
return v;
}
}
ExamFragmentAdapter.java
public class ExamFragmentAdapter extends RecyclerView.Adapter<ExamFragmentAdapter.MyViewHolder> {
private LayoutInflater inflater;
MyViewHolder holder;
Context mContext;
ArrayList<tblChapters> chapterList=new ArrayList<>();
public ExamFragmentAdapter(ArrayList<tblChapters> chapterList, Context context) {
inflater = LayoutInflater.from(context);
this.chapterList = chapterList;
mContext=context;
}
#Override
public ExamFragmentAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.chapter_list_row, parent, false);
holder = new MyViewHolder(view, new MyCustomEditTextListener());
return holder;
}
#Override
public void onBindViewHolder(final ExamFragmentAdapter.MyViewHolder holder, final int position) {
holder.title.setTextColor(Color.BLACK);
holder.slno.setTextColor(Color.BLACK);
holder.noOfQst.setTextColor(Color.BLACK);
holder.noOfQst.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
holder.noOfQst.setGravity(Gravity.CENTER);
holder.title.setText(chapterList.get(position).getTitle()); // Setting Chapter title
holder.slno.setText(String.valueOf(position + 1)+"."); //Setting sl no
holder._myCustomEditTextListener.updatePosition(position);
holder.noOfQst.setText(chapterList.get(position).getNoofQstns()); //Setting no of qstn
if (chapterList.get(position).isVisibled()) {
holder.noOfQst.setVisibility(View.VISIBLE);
} else {
holder.noOfQst.setVisibility(View.INVISIBLE);
}
//in some cases, it will prevent unwanted situations
holder.cbox.setOnCheckedChangeListener(null);
//if true, your checkbox will be selected, else unselected
holder.cbox.setChecked(chapterList.get(position).isSelected());
holder.cbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//set your object's last status
chapterList.get(position).setSelected(isChecked);
chapterList.get(position).setVisibled(isChecked);
//if checkbox checked display EditText(No of qstns), else hide it.
if (holder.cbox.isChecked()) {
holder.noOfQst.setVisibility(View.VISIBLE);
holder.noOfQst.requestFocus();
holder.noOfQst.setText("10");
chapterList.get(position).setNoofQstns(holder.noOfQst.getText().toString());
/* txtQcount.setText("0");
if (txtQcount.getText().toString().equals("")) {
txtQcount.setText("0");
}
txtQcount.setText(Integer.valueOf(txtQcount.getText().toString())+Integer.parseInt(holder.noOfQst.getText().toString()));*/
}
else {
holder.noOfQst.setVisibility(View.INVISIBLE);
holder.noOfQst.setText(""); //remove entered value when uncheck
chapterList.get(position).setNoofQstns("");
}
}
});
}
// we make TextWatcher to be aware of the position it currently works with
// this way, once a new item is attached in onBindViewHolder, it will
// update current position MyCustomEditTextListener, reference to which is kept by ViewHolder
private class MyCustomEditTextListener implements TextWatcher
{
private int position;
private String oldval;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
// no op
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
chapterList.get(position).setNoofQstns(charSequence.toString());
int j = i;
j = i2;
j = i3;
}
#Override
public void afterTextChanged(Editable editable) {
}
}
#Override
public int getItemCount() {
return chapterList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView title;
CheckBox cbox;
TextView slno;
EditText noOfQst;
public MyCustomEditTextListener _myCustomEditTextListener;
public MyViewHolder(View itemView,MyCustomEditTextListener myCustomEditTextListener) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.txtTitle);
cbox = (CheckBox) itemView.findViewById(R.id.cboxChapter);
slno = (TextView) itemView.findViewById(R.id.txtRowSlno);
noOfQst = (EditText) itemView.findViewById(R.id.etNoOfQstns);
this._myCustomEditTextListener = myCustomEditTextListener;
try {
if (noOfQst.getVisibility() == View.VISIBLE) {
holder.noOfQst.setVisibility(View.INVISIBLE);
//adding textchange listener to no of qstn(EditText)
noOfQst.addTextChangedListener(myCustomEditTextListener);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

You can register an AdapterDataObserver for the recycler view adapter.
For each item in the adapter when it's updated (user updates the EditText), the adapter can call notifyItemChanged(int position, Object payload). the observer will receive the payload in its onItemRangeChanged (int positionStart, int itemCount, Object payload) callback, you can pass whatever you want in the payload object so that you accumulate the values of all the EditTexts.
You can also unregister the observer in your Activity/Fragment onStop by calling unregisterAdapterDataObserver

Related

Get selected item position of RecyclerView

I am trying to get position of the clicked item in RecyclerView. In adapter class, I am trying to create intent and send clicked item's contents. Also I created popup menu for two option. It is in adapter class too. onBindViewHolder position is works for puting contents in the rows of RecyclerView. However I couldn't reach that position from outside of method.
This is adapter class.
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements PopupMenu.OnMenuItemClickListener {
public ArrayList<MovieModel.Results> resultList;
public Context context;
public RecyclerViewAdapter(ArrayList<MovieModel.Results> list, Context context) {
this.resultList = list;
this.context = context;
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView posterImage;
ImageView addIcon;
TextView movieName;
TextView date;
TextView overview;
public ViewHolder(#NonNull View itemView) {
super(itemView);
posterImage = itemView.findViewById(R.id.movie_poster);
addIcon = itemView.findViewById(R.id.addImage);
movieName = itemView.findViewById(R.id.movieNameText);
date = itemView.findViewById(R.id.dateText);
overview = itemView.findViewById(R.id.overviewText);
}
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_2, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
if (position < getItemCount()) {
String title = resultList.get(position).getTitle();
String date = resultList.get(position).getRelease_date();
String overview = resultList.get(position).getOverview();
String posterPath = resultList.get(position).getPoster_path();
holder.movieName.setText(title);
holder.date.setText(date);
holder.overview.setText(overview);
if (posterPath == null) {
holder.posterImage.setImageDrawable(context.getDrawable(R.drawable.no_poster));
} else {
Glide.with(context).load(FeedActivity.BASE_PHOTO_URL + posterPath).into(holder.posterImage);
}
int finalPosition = position;
holder.addIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(context, "You clicked : " + finalPosition, Toast.LENGTH_SHORT).show();
showPopup(v);
}
});
}
position++;
}
private void showPopup(View v) {
PopupMenu popup = new PopupMenu(context,v);
popup.setOnMenuItemClickListener(this);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu, popup.getMenu());
popup.show();
}
#Override
public boolean onMenuItemClick(MenuItem item) {
// Here I need to position of clicked item in Recyclerview, and I will get title, date etc.
int pos;
if(item.getItemId() == R.id.menuAdd){
// Find here to get position of clicked movie.
String title = resultList.get(pos).getTitle();
String date = resultList.get(pos).getRelease_date();
String overview = resultList.get(pos).getOverview();
String posterpath = resultList.get(pos).getPoster_path();
Intent intent1 = new Intent(context,ListActivity.class);
intent1.putExtra("title",title);
intent1.putExtra("date",date);
intent1.putExtra("overview",overview);
intent1.putExtra("posterpath",posterpath);
context.startActivity(intent1);
return true;
}
else if(item.getItemId() == R.id.menuShowDetails){
int movieId = resultList.get(pos).getMovieId();
Intent intent1 = new Intent(context, MovieDetails.class);
intent1.putExtra("movie_id",movieId);
context.startActivity(intent1);
return true;
}
return false;
}
#Override
public int getItemCount() {
return resultList.size();
}
}
You can use the ViewHolder's getAdapterPosition() to retrieve the item's position within an interface method. Then store the clicked position in a member variable.
Additionally, there shouldn't be a need to call position++ from within your onBindViewHolder.
// Create a member variable to store the clicked position
public int clickedPos = -1;
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
// ...
holder.addIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// When you're inside the click listener interface,
// you can access the position using the ViewHolder.
// We'll store the position in the member variable in this case.
clickedPos = holder.getAdapterPosition();
}
});
// Remove the 'position++' call as the position should already be handled without explicitly updating it.
}
#Override
public boolean onMenuItemClick(MenuItem item) {
// You can use clickedPos here to perform whatever tasks you need.
// ...
}

Recyclerview problem with multiple spinner problem

I have 2 spinners in my recycler view. Now my 2nd spinner value depends on the 1st spinner selected item.
I am able to bind data in spinner 1 but when I try to bind spinner 2 data based on setOnItemSelectedListener of spinner 1 it will only bind for a visible item on the screen.
I want to bind spinner 2 data even if it is not visible on the screen. I have the following code for the adapter :
public class CustomerAdapter extends RecyclerView.Adapter<CustomerAdapter.CardViewHolder> {
private ArrayList<MainDetails> mMainDetails;
private Context mContext;
public CustomerAdapter(Context mcontext, ArrayList<MainDetails> mainDetails) {
mContext = mcontext;
mMainDetails = mainDetails;
}
private Context getContext() {
return mContext;
}
#Override
public CardViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
Context context = viewGroup.getContext();
View itemView = LayoutInflater.from(context).inflate(R.layout.row_bind_data, viewGroup, false);
return new CardViewHolder(itemView);
}
#Override
public void onBindViewHolder(final CardViewHolder cardViewHolder, int position) {
final MainDetails testMainDetails = mMainDetails.get(position);
ArrayAdapter<Products> spinnerUserAdapter = new ArrayAdapter<Products>(getContext(), R.layout.dropdown_item, testMainDetails.getUsers());
spinnerUserAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cardViewHolder.spinner1.setAdapter(spinnerUserAdapter);
cardViewHolder.spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
try {
Products pp = (Products) parent.getSelectedItem();
ArrayAdapter<Orders> spinnerPPAdapter = new ArrayAdapter<Orders>(getContext(), R.layout.pc_estimator_dropdown_item, pp.getOrders());
spinnerPPAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cardViewHolder.spinner2.setAdapter(spinnerPPAdapter);
} catch (Exception e) {
Log.e("error", e.toString());
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
cardViewHolder.spinner2.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//other operation
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
#Override
public int getItemCount() {
return mMainDetails.size();
}
public static class CardViewHolder extends RecyclerView.ViewHolder {
public Spinner spinner1;
public Spinner spinner2;
public CardViewHolder(View v) {
super(v);
spinner1 = (Spinner) v.findViewById(R.id.spinner1);
spinner2 = (Spinner) v.findViewById(R.id.spinner2);
}
}
}
My spinner cardViewHolder.spinner1.setOnItemSelectedListener method only calls for visible items on screens but I want to bind all data even if it not visible.
I think you need to implement everything inside ViewHolder. Let me show you an example:
#Override
public void onBindViewHolder(#NonNull SomeHolder holder, int position) {
if (SomeDataList.size() > 0) {
SomeData data = SomeDataList.get(position);
holder.bindData(data);
}
}
Then in holder class:
public class SomeHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
private final TextView tvAddress;
private final TextView tvAccountNumber;
private final TextView tvName;
private SomeData someData;
public SomeHolder(#NonNull View itemView) {
super(itemView);
tvAccountNumber = itemView.findViewById(R.id.item_point_account_number);
tvName = itemView.findViewById(R.id.item_point_subscr_name);
tvAddress = itemView.findViewById(R.id.item_point_address);
itemView.setOnClickListener(this);
}
public void bindData(SomeData data) {
someData = data;
tvAddress.setText(data.getAddress());
//other stuff
}
#Override
public void onClick(View v) {
if (someData!=null){
tvName.setText(someData.getName());
//code for click event
}
}
}
straight inside onBindViewHolder you are setting only one adapter, for spinner1 and nothing for spinner2 - it got its adapter only after onItemSelected call of spinner1
if you want to set some initial values for spinner2 you have to initiate its adapter inside onBindViewHolder, not only in onItemSelected
move your adapter initiation code to separated method
public void setUpSpinner2(Spinner spinner, Products pp) {
try {
ArrayAdapter<Orders> spinnerPPAdapter = new ArrayAdapter<Orders>(getContext(), R.layout.pc_estimator_dropdown_item, pp.getOrders());
spinnerPPAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerPPAdapter);
} catch (Exception e) {
Log.e("error", e.toString());
}
}
then inside onItemSelected call it
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Products pp = (Products) parent.getSelectedItem();
setUpSpinner2(cardViewHolder.spinner2, pp);
}
and also call setUpSpinner2 straight inside onBindViewHolder with null check (is item selected on start)
if (spinnerUserAdapter.getSelectedItem() != null) {
Products pp = (Products) spinnerUserAdapter.getSelectedItem();
setUpSpinner2(cardViewHolder.spinner2, pp);
}
btw. I see you aren't storing spinner1 selected value anywhere, so after recycling both spinners will be empty again. so inside onItemSelected get position of selected item (there is method getSelectedItemPosition) and store it in some array
//top of adapters code
private ArrayList<MainDetails> mMainDetails;
private Context mContext;
private SparseArray<Integer> selectedItemsForPositions = new SparseArray<>();
inside onItemSelected and onNothingSelected put/clear selected value with this line (don't mix positions of onBindViewHolder and onItemSelected, name them differently)
selectedItemsForPositions.put(onBindViewHolderPosition, parent.getSelectedItemPosition());
// or put null if nothing selected
when you have this array which is keeping selected positions then restore this position just after spinner1 adapter set up
cardViewHolder.spinner1.setAdapter(spinnerUserAdapter);
Integer selectedPosition = selectedItemsForPositions.get(onBindViewHolderPosition);
if(selectedPosition != null) spinnerUserAdapter.setSelection(selectedPosition);

RecyclerView shows previous values entered in an EditText in new rows

I'm creating an android app, in which I'm using recyclerView and the row of recyclerView is having editText.
This is my ReadingAdapter class
public class ReadingAdapter extends RecyclerView.Adapter<ReadingAdapter.ViewHolder> implements AdapterView.OnItemSelectedListener {
Context context;
String valOpenReading, valClosReading, valConsumption;
private List<ReadingData> readingList;
static String[] arrValOpenRead, arrValClosRead, arrValConsumption;
public ReadingAdapter(Context context, List<ReadingData> readingList) {
this.context = context;
this.readingList = readingList;
arrValOpenRead = new String[readingList.size()];
arrValClosRead = new String[readingList.size()];
arrValConsumption = new String[readingList.size()];
}
#Override
public ReadingAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.reading_sheet_layout, parent, false);
return new ReadingAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(final ReadingAdapter.ViewHolder holder, final int position) {
ReadingData tempData = readingList.get(position);
holder.pdtName.setText(tempData.pdtName);
holder.keyId.setText("Key "+tempData.keyId);
holder.etClosRead.addTextChangedListener(new TextWatcher() {
boolean ignore = false;
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (ignore)
return;
ignore = true;
valOpenReading = holder.etOpenRead.getText().toString();
arrValOpenRead[position] = valOpenReading;
valClosReading = s.toString().equals("") ? "0": s.toString();
arrValClosRead[position] = valClosReading;
if (!valOpenReading.equals("")) {
if (Integer.parseInt(valClosReading) < Integer.parseInt(valOpenReading)) {
Toast.makeText(context, "Check once! closing reading should be more than opening reading!", Toast.LENGTH_LONG).show();
valConsumption = "0";
holder.consumption.setText("");
} else {
valConsumption = (Integer.parseInt(valClosReading) - Integer.parseInt(valOpenReading))+"";
arrValConsumption[position] = valConsumption;
holder.consumption.setText(valConsumption);
}
} else
Toast.makeText(context, "Please fill the opening reading!", Toast.LENGTH_SHORT).show();
ignore = false;
}
});
}
#Override
public int getItemCount() {
return readingList.size();
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView pdtName, keyId, consumption;
EditText etOpenRead, etClosRead;
public ViewHolder(View view) {
super(view);
pdtName = (TextView)view.findViewById(R.id.txt_list_pdt_supp);
keyId = (TextView)view.findViewById(R.id.key_set);
etOpenRead = (EditText)view.findViewById(R.id.open_val_set);
etClosRead = (EditText)view.findViewById(R.id.clos_val_set);
consumption = (TextView)view.findViewById(R.id.consumption_val);
}
}
}
This is my ReadingData.java
public class ReadingData {
String pdtName, keyId, openReading, closReading, consumption;
public ReadingData(String pdtName, String keyId) {
this.pdtName = pdtName;
this.keyId = keyId;
}
}
Here, if I enter value in the starting items of the recyclerView then as I scroll up the items to the bottom of the list, the last item will have that value.
Please ignore the quality of image as we can't upload above of 2MiB of snap.
Here the views are recycled as the list is scrolled. How to prevent the copying values to the other item in the list.
And that Toast is also repeated several times. How to stop this.
update:
By the suggetion of LQ Gioan through the SO question How ListView's recycling mechanism works , I got the logic how ListView actually works with recycling of views.
But I'm not sure whether the recyclerView also works same.
But here in my case, how can I implement this process. pls someone help me here.
RecyclerView reuse views, in fact it only generate the as many as views that is visible on the screen. so it's expected if you can see a value you set for other rows
The solution would be set all attributes of the view that you are changing to default or whatever the row should present from your data set
So put addTextChangedListener insode ViewHolder constructor(you can get position by calling getAdapterPosition()) for better performance and set the editText value inside onBindViewHolder method from your data set
Your Activity Code:
ListView listview = (ListView) findViewById(R.id.list_view);
listview.setItemsCanFocus(true);
Adapter adapter = new Adapter (YourActivity.this, YourArrayList);
listview .setAdapter(adapter);
Adapter class
public class Adapter extends BaseAdapter {
// Declare Variables \\
Context mContext;
LayoutInflater inflater;
Activity act;
String[] temp;
public Adapter(Context context, ArrayList<String> list) {
mContext = context;
inflater = LayoutInflater.from(mContext);
act = (Activity) context;
//-------Temp String Array-------\\
temp = new String[this.count];
for (int i = 0; i < this.count; i++) {
temp[i] = list.get(i);
}
//---------------------------\\
}
public class ViewHolder {
TextView optionTitle;
EditText optionText;
int ref;
}
#Override
public int getCount() {
return list.size;
}
#Override
public Object getItem(int position) {
return temp[position];
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.lv_items_add_ques_options_mcq, null);
holder.optionTitle = (TextView) view.findViewById(R.id.add_ques_opts_count_mcq_tv);
holder.optionText = (EditText) view.findViewById(R.id.add_ques_opts_title_mcq_et);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.ref = position;
holder.optionTitle.setText(getCharForNumber(position) + ":");
holder.optionText.setText(temp[position]);
holder.optionText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
#Override
public void afterTextChanged(Editable arg0) {
temp[holder.ref] = arg0.toString().trim();
}
});
return view;
}
public void getList() {
StaticValues.arrayListOptions = new ArrayList<String>(Arrays.asList(temp));
StaticValues.arrayListOptionsCount = new ArrayList<String>();
for (int i = 0; i < count; i++) {
StaticValues.arrayListOptionsCount.add(String.valueOf(i+1));
Log.e("err_al", StaticValues.arrayListOptions.get(i));
Log.e("err_al", StaticValues.arrayListOptionsCount.get(i));
}
}
private String getCharForNumber(int i) {
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
if (i > 25) {
return null;
}
return Character.toString(alphabet[i]);
}}

Clear EditText value in a RecyclerView row

I have a RecyclerView in my android project. There I am adding rows from searching from a AutoCompleteTextView. Each row has TextView and one EditText field. As well as adding, I am also removing rows. I have a remove button in a each row.
Everything works fine. Problem is I cannot clear EditText value in removing. For example if I add three rows and remove the second one, the third row should come to second place with its own EditText value. But the problem is, the value from the row removed is not clearing and the third row's EditText value is replaced by it instead. Then if I add another row (to the third place), automatically that EditText field is filled with previous third row's EditText value.
How can I clear EditText value also???
This is my adapter code.
public class SelectItemAdapter extends RecyclerView.Adapter<SelectItemAdapter.ItemHolder> {
private List<String> itemsName, itemsQty, itemsPCode, itemPlant, _retData;
private OnItemClickListener onItemClickListener;
private LayoutInflater layoutInflater;
private String[] mDataset;
public ArrayList myItems = new ArrayList();
private Context context;
private String[] arrayForSaveEditTextValue;
public SelectItemAdapter(Context context, String[] mDataset) {
layoutInflater = LayoutInflater.from(context);
itemsName = new ArrayList<String>();
itemsQty = new ArrayList<String>();
itemsPCode = new ArrayList<String>();
itemPlant = new ArrayList<String>();
_retData = new ArrayList<String>();
this.arrayForSaveEditTextValue = mDataset;
}
#Override
public SelectItemAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = layoutInflater.inflate(R.layout.custom_row_selected_item, parent, false);
return new ItemHolder(itemView, this);
}
#Override
public void onBindViewHolder(final SelectItemAdapter.ItemHolder holder, final int position) {
holder.setItemName(itemsName.get(position));
holder.setItemQty(itemsQty.get(position));
holder.setItemPCode(itemsPCode.get(position));
holder.setItemPlant(itemPlant.get(position));
holder.numPicker.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,int arg3) {}
#Override
public void afterTextChanged(Editable arg0) {
_retData.set(position, arg0.toString());
Log.d("arg0",arg0.toString());
}
});
}
#Override
public int getItemViewType(int position) {
return position;
}
public String retrieveData(int i) {
return _retData.get(i);
}
#Override
public int getItemCount() {
return itemsName.size();
}
public Object getItemName(int position) {
return itemsName.get(position);
}
public Object getItemQty(int position) {
return itemsQty.get(position);
}
public Object getItemPCode(int position) {
return itemsPCode.get(position);
}
public Object getItemPlant(int position) {
return itemPlant.get(position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
onItemClickListener = listener;
}
public OnItemClickListener getOnItemClickListener() {
return onItemClickListener;
}
public interface OnItemClickListener {
public void onItemClick(ItemHolder item, int position);
}
public void add(int location, String iName, String iQty, String iPCode, String iPlant) {
itemsName.add(location, iName);
itemsQty.add(location, iQty);
itemsPCode.add(location, iPCode);
itemPlant.add(location, iPlant);
_retData.add(location,"0");
notifyItemInserted(location);
notifyDataSetChanged();
}
public void remove(int location) {
if (location >= itemsName.size())
return;
itemsName.remove(location);
itemsQty.remove(location);
itemsPCode.remove(location);
itemPlant.remove(location);
_retData.remove(location);
notifyItemRemoved(location);
notifyDataSetChanged();
}
public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private SelectItemAdapter parent;
TextView textItemName, txtPCode, txtAvailableQty, txtTempQty, txtPlant;
Button bRemove;
EditText numPicker;
public ItemHolder(View itemView, SelectItemAdapter parent) {
super(itemView);
this.parent = parent;
textItemName = (TextView) itemView.findViewById(R.id.txtProductName);
txtAvailableQty = (TextView) itemView.findViewById(R.id.txtAvailbleQty);
txtPCode = (TextView) itemView.findViewById(R.id.txtPCode);
txtPlant = (TextView) itemView.findViewById(R.id.txtPlant);
bRemove = (Button) itemView.findViewById(R.id.bRemove);
numPicker = (EditText) itemView.findViewById(R.id.numberPicker);
bRemove.setOnClickListener(this);
}
public void setItemName(CharSequence name) {
textItemName.setText(name);
}
public void setItemQty(CharSequence name) {
txtAvailableQty.setText(name);
}
public void setItemPCode(CharSequence name) {
txtPCode.setText(name);
}
public void setItemPlant(CharSequence name) {
txtPlant.setText(name);
}
public CharSequence getItemName() {
return textItemName.getText();
}
#Override
public void onClick(View v) {
final OnItemClickListener listener = parent.getOnItemClickListener();
if (listener != null) {
listener.onItemClick(this, getPosition());
}
}
}
public class RetItem {
public String _itemNumPic;
}
}
And the remove method...
#Override
public void onItemClick(SelectItemAdapter.ItemHolder item, int position) {
Toast.makeText(this,
"Remove " + " : " + item.getItemName(),
Toast.LENGTH_SHORT).show();
myRecyclerViewAdapter.remove(position);
}
First of all use a list of an Object instead of using lots of string arrays!
and then to achieve the behavior you want, you need to remove the item from the main list and call notifyDataSetChanged();
Here is an ex:
List<DayEntity> days = new ArrayList<>();
Here is a list of day items, you set this list to your adapter like this:
MyDayAdapter adapter = new MyDayAdapter(context, days);
So for removing an item in position 'x' you can do this way:
days.remove(x);
adapter.notifyDataSetChanged();
have fun...
1- Create a model class for your data, with all your getters and setters in one list:
public class SelectItemAdapter extends RecyclerView.Adapter<SelectItemAdapter.ItemHolder> {
private final ArrayList<MyData> mDataList = new ArrayList<>();
2- remove at method
//Remove from the list on click
private void removeAt(int position) {
mUserList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataList.size());
}
3- Now inside onClick() method you can call removeAt method, and you just pass the position which is the adapter position
removeAt(getAdapterPosition());
You need to keep track of the values entered in the EditText of your RecyclerView. You've an array named arrayForSaveEditTextValue for saving the EditText values I think, but I see no usage of it. Your code is a little bit clumsy too. So I would like to suggest a different approach of implementing this list for you.
Create an object for your list items.
public class ListItem {
public String itemsName;
public String itemsQty;
public String itemsPCode;
public String itemPlant;
public String _retData;
public String editTextValue = ""; // Default EditText Value
}
And your adapter should look like this.
public class SelectItemAdapter extends RecyclerView.Adapter<SelectItemAdapter.ItemHolder> {
private List<ListItem> listItems;
private OnItemClickListener onItemClickListener;
private LayoutInflater layoutInflater;
public SelectItemAdapter(Context context, List<ListItem> listItems) {
layoutInflater = LayoutInflater.from(context);
this.listItems = listItems;
}
#Override
public SelectItemAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = layoutInflater.inflate(R.layout.custom_row_selected_item, parent, false);
return new ItemHolder(itemView, this);
}
#Override
public void onBindViewHolder(final SelectItemAdapter.ItemHolder holder, final int position) {
final ListItem tempListItem = listItems.get(position);
holder.textItemName.setText(tempListItem.itemsName);
holder.txtAvailableQty.setText(tempListItem.itemsQty);
holder.txtPCode.setText(tempListItem.itemsPCode);
holder.txtPlant.setText(tempListItem.itemPlant);
holder.numPicker.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
#Override
public void afterTextChanged(Editable arg0) {
// Calculate your _retData and set the TextView
tempListItem._retData = calculateRetData(position, arg0.toString());
tempListItem.editTextValue = arg0.toString();
// Replace the item with the value updated
listItems.add(position, tempListItem);
notifyDataSetChanged();
}
});
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getItemCount() {
return listItems.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
onItemClickListener = listener;
}
public OnItemClickListener getOnItemClickListener() {
return onItemClickListener;
}
public interface OnItemClickListener {
public void onItemClick(ItemHolder item, int position);
}
public void add(ListItem listItem) {
listItems.add(listItem);
notifyDataSetChanged();
}
public void remove(int location) {
if (location >= listItems.size())
return;
listItems.remove(location);
notifyDataSetChanged();
}
public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private SelectItemAdapter parent;
TextView textItemName, txtPCode, txtAvailableQty, txtTempQty, txtPlant;
Button bRemove;
EditText numPicker;
public ItemHolder(View itemView, SelectItemAdapter parent) {
super(itemView);
this.parent = parent;
textItemName = (TextView) itemView.findViewById(R.id.txtProductName);
txtAvailableQty = (TextView) itemView.findViewById(R.id.txtAvailbleQty);
txtPCode = (TextView) itemView.findViewById(R.id.txtPCode);
txtPlant = (TextView) itemView.findViewById(R.id.txtPlant);
bRemove = (Button) itemView.findViewById(R.id.bRemove);
numPicker = (EditText) itemView.findViewById(R.id.numberPicker);
bRemove.setOnClickListener(this);
}
#Override
public void onClick(View v) {
final OnItemClickListener listener = parent.getOnItemClickListener();
if (listener != null) {
listener.onItemClick(this, getPosition());
}
}
}
}
The idea is to save the EditText value in the corresponding object and in case of adding and deleting an item from the RecyclerView, you have to update the list of the items accordingly and then call notifyDataSetChanged().
I haven't tested the code, but I think you get the idea. Please let me know if there's anything else I can help you with.

My recycleView only call/count elements from screen

I have a problem to updae my recycle when updating scroll up/down.
I have 3 (Custom ítems with respect views) but my onBindViewHolder only calls 2, when I try down list, my list not update correctly aparently It makes a cut (0.2 sec)
I don't know why not update correctly with 3 (ítems with 3 images)
My holder : (Why count 2?) but I when down, count 3 ...
public class CAPusheenAdapter_Fragment_0_7 extends RecyclerView.Adapter<CAPusheenAdapter_Fragment_0_7.ViewHolder> {
private ArrayList<CustomItem_0_ALL> pusheenArrayList;
private int itemLayout;
private Context context;
DBHelper db ;
RecyclerView recyclerView;
public CAPusheenAdapter_Fragment_0_7(ArrayList<CustomItem_0_ALL> data, int itemLayout, Context context, RecyclerView recyclerView){
setHasStableIds(true);
this. pusheenArrayList = data;
this. itemLayout = itemLayout;
this. context = context;
db = new DBHelper(context);
this. recyclerView = recyclerView;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ArrayList<TextView> allTextViews;
//public TextView text1,text2,text3,text4,text5,text6,text7;
public LinearLayout l1;
public ViewHolder(View itemView) {
super(itemView);
int numOfTextViews=6;
allTextViews = new ArrayList<TextView>(); allTextViews.add(0,null);
l1 = (LinearLayout)itemView.findViewById(R.id.l1);
for(int i=1;i<=numOfTextViews;i++){
allTextViews.add(i,Config.getViewsComplext(context,itemView, "text" + i));
}
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//final int itemPosition = Fragment_0.recyclerView.getChildPosition(view); // todo SOO COOL LINE !
final int itemPosition = recyclerView.getChildPosition(view); // todo SOO COOL LINE !
//Toast.makeText(context, "No plantejada", Toast.LENGTH_SHORT).show();
//MainActivity.FragmentReutil2(new Class[]{Fragment_0_4_1.class}, 0, context);
}
});
}
}
#Override
public CAPusheenAdapter_Fragment_0_7.ViewHolder onCreateViewHolder(ViewGroup parent, int i) {
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
Config.totalConfigFull2(context, itemLayoutView);
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(CAPusheenAdapter_Fragment_0_7.ViewHolder viewHolder, int position) {
CustomItem_0_ALL pusheen = pusheenArrayList.get(position);
ArrayList<String> texts = new ArrayList<>();
texts.add(0,null);
texts.add(1,pusheen.getText1());
texts.add(2,pusheen.getText2());
texts.add(3,pusheen.getText3());
texts.add(4,pusheen.getText4());
texts.add(5,pusheen.getText5());
texts.add(6,pusheen.getText6());
for ( int i = 1 ; i < viewHolder.allTextViews.size() ; i+=1 ){
if(texts.get(i).length()>0){
viewHolder.allTextViews.get(i).setText(texts.get(i));
viewHolder.allTextViews.get(i).setVisibility(View.VISIBLE);
}else{
viewHolder.allTextViews.get(i).setVisibility(View.GONE);
}
}
//viewHolder.l1.setBackgroundResource(pusheen.getImg());
int w =Config.getWigthHeightScreen(context)[0];
int h =Config.getWigthHeightScreen(context)[1];
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(w, (int) (h/2.5));
viewHolder.l1.setBackgroundResource(pusheen.getImg());
viewHolder.l1.setLayoutParams(lp);
}
#Override
public int getItemCount() {
return this.pusheenArrayList.size();
}
}
Note : only call/count elements from screen not call out elements, only call when you move list up/down
I found problem :
This is the problem : and solution
AsyncTask loading image RecyclerView

Categories

Resources