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);
Related
I can populate my spinner with the array list from API. But unable to select or populate the selected item from spinner and display to the user.
The onItemSelected method does not get the position of the selected item in the spinner.
CustomSpinnerAdapter.java
public class CustomSpinnerAdapter extends BaseAdapter {
Context context;
List<String> userNames;
LayoutInflater inflter;
public CustomSpinnerAdapter(Context applicationContext, List<String> userNames) {
this.context = applicationContext;
this.userNames = userNames;
inflter = (LayoutInflater.from(applicationContext));
}
#Override
public int getCount() {
return userNames.size();
}
#Override
public Object getItem(int i) {
return userNames.get(i);
}
#Override
public long getItemId(int i) {
return 0;
}
#NonNull
#SuppressLint({"ViewHolder", "InflateParams"})
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = inflter.inflate(R.layout.custom_spinner_item, null);
CustomTextView names = (CustomTextView) view.findViewById(R.id.tv_spinner_item);
names.setText(userNames.get(i));
return view;
}
}
My logic in fragment.
private SpinnerAdapter customAdapter;
private List<String> eqIds = new ArrayList<>;
apiInterface = ApiRequest.createService(ApiInterface.class);
Call<EquipmentTypeModel> call = apiInterface.getEquipmentType("application/json", token, id);
call.enqueue(new Callback<EquipmentTypeModel>() {
#Override
public void onResponse(Call<EquipmentTypeModel> call, Response<EquipmentTypeModel> response) {
if (response.isSuccessful()) {
eqIds.addAll(response.body().getData().getEquipmentList().getEquipIds());
}
}
#Override
public void onFailure(Call<EquipmentTypeModel> call, Throwable t) {
}
});
customAdapter = new CustomSpinnerAdapter(mContext, eqIds);
spTypeModel.setAdapter(customAdapter);
spTypeModel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(mContext, String.valueOf(parent.getAdapter().getItem(position)), Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
To get the selected value from spinner you should you
String selectedValue = spTypeModel.getSelectedItem().toString();
or
String selectedValue = String.valueOf(parent.getAdapter().getItem(position));
instead of
String selectedValue = String.valueOf(position);
Update: Change getItem method in your custom adapter to
#Override
public Object getItem(int i) {
return userNames.get(i);
}
Update 2: I saw your problem, please change your code.
private SpinnerAdapter customAdapter;
to
private CustomSpinnerAdapter customAdapter;
then add this line after you add new data to your adapter.
eqIds.addAll(response.body().getData().getEquipmentList().getEquipIds());
customAdapter.notifyDataSetChanged(); // Add this line to notify your adapter about new data
Update 3: From your xml file, because your spinner height is 18dp.
In spinner you set padding to 4dp (will be 8dp for top and bot)
In custom text view you also set padding 4dp (will be 8dp for top and bot)
So you only have equal or less than 2dp to display text content, it really small that why you can't see the content.
You can set your spinner height to wrap_content or keep current height but remove padding from spinner or from the custom text view. It's up to you.
Try if this works (It will show you the value, not the position)
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(mContext, parent.getItemAtPosition(position).toString(), Toast.LENGTH_SHORT).show();
}
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.
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
I have a ListView that is within a Fragment. In the onCreateView section I have set a onItemClickListener for the list, which highlights the selected item in the ListView. I have set two ImageButtons that navigate up and down the list. On selection a new Row is inflated that has its TextView's set to the content of the select item (for the purpose of retaining the highlighted selected state). However I am having difficulty adding that item back to the list. The app will not compile due to the line routines.add(selectedPos-1, str); it wants wants int location, Routine object. I believe the issue is with my construction of my SelectedAdapter class, but I have been unable to determine what to change/pass with regard to the Object.
IE:
public SelectedAdapter(Context context, int textViewResourceId,List objects) {
super(getActivity(), R.layout.listview_routines, routines); }
I would greatly appreciate any input as how to correct this issue; as well as any advice if there is a better way to maintain a selected state. Thanks for your help.
Fragment:
public static class FragmentRoutine extends Fragment {
DatabaseHandler db;
private ListView routineListView;
private List<Routine> routines = new ArrayList<Routine>();
ArrayAdapter<Routine> routineAdapter;
Routine longClickedItemRoutines;
private SelectedAdapter selectedAdapter;
public FragmentRoutine() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.routines,
container, false);
db = new DatabaseHandler(getActivity().getApplicationContext());
routineListView = (ListView) rootView.findViewById(R.id.routineList);
registerForContextMenu(routineListView);
db.closeDB();
if (db.getExerciseCount() != 0)
routines.clear();
routines.addAll(db.getAllRoutines());
populateList();
selectedAdapter = new SelectedAdapter(this.getActivity(), 0, routines);
selectedAdapter.setNotifyOnChange(true);
routineListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
longClickedItemRoutines = routines.get(position);
return false;
}
});
routineListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView arg0, View view,
int position, long id) {
selectedAdapter.setSelectedPosition(position);
}
});
routineListView.post(new Runnable() {
#Override
public void run() {
routineListView.setItemChecked(0, true);
}
});
// move up event handler
ImageButton btnMoveUp = (ImageButton) rootView.findViewById(R.id.btnMoveUp);
btnMoveUp.setOnClickListener(new AdapterView.OnClickListener() {
public void onClick(View arg0) {
moveUp();
}
});
// move down event handler
ImageButton btnMoveDown = (ImageButton) rootView.findViewById(R.id.btnMoveDown);
btnMoveDown.setOnClickListener(new AdapterView.OnClickListener() {
public void onClick(View arg0) {
moveDown();
}
});
setHasOptionsMenu(true);
return rootView;
}
// Move selected item "up" in the ViewList.
private void moveUp(){
Routine currentToDoSave = routines.get(selectedAdapter.getSelectedPosition());
int selectedPos = selectedAdapter.getSelectedPosition();
if (selectedPos > 0 ){
routines.remove(selectedPos);
String str = currentToDoSave.getTagName();
//Problem Line Below
routines.add(selectedPos-1, str);
// set selected position in the adapter
selectedAdapter.setSelectedPosition(selectedPos-1);
}
}
// Move selected item "down" in the ViewList.
private void moveDown(){
Routine currentToDoSave = routines.get(selectedAdapter.getSelectedPosition());
int selectedPos = selectedAdapter.getSelectedPosition();
if (selectedPos < routines.size()-1 ){
routines.remove(selectedPos);
String str = currentToDoSave.getTagName();
routines.add(selectedPos+1, str);
// set selected position in the adapter
selectedAdapter.setSelectedPosition(selectedPos+1);
}
}
public class SelectedAdapter extends ArrayAdapter<Routine>{
// used to keep selected position in ListView
private int selectedPos = -1; // init value for not-selected
public SelectedAdapter(Context context, int textViewResourceId,
List objects) {
super(getActivity(), R.layout.listview_routines, routines);
}
public void setSelectedPosition(int pos){
selectedPos = pos;
// inform the view of this change
notifyDataSetChanged();
}
public int getSelectedPosition(){
return selectedPos;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
// only inflate the view if it's null
if (v == null) {
LayoutInflater vi
= (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.selected_row, null);
}
// get text view
TextView label = (TextView)v.findViewById(R.id.txtExample);
// change the row color based on selected state
if(selectedPos == position){
label.setBackgroundColor(Color.CYAN);
}else{
label.setBackgroundColor(Color.WHITE);
}
label.setText(this.getItem(position).toString());
return(v);
}
}
private void populateList() {
routineAdapter = new SaveListAdapterT();
routineListView.setAdapter(routineAdapter);
}
public class SaveListAdapterT extends ArrayAdapter<Routine> {
public SaveListAdapterT() {
super(getActivity(), R.layout.listview_routines, routines);
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null)
view = getActivity().getLayoutInflater().inflate(R.layout.listview_routines, parent, false);
Routine currentToDoSave = routines.get(position);
TextView name = (TextView) view.findViewById(R.id.name);
name.setText(currentToDoSave.getTagName());
return view;
}
}
}
i've noticed an extrage behavior on my app that has a ListView with three EditTexts,
the problem is that whenever i select one textedit and move away from focus and come back the text i wrote in the first row i selected either desapears or moves to a different row, also when an edittext is focused and i go down in the list it seems that i have selected the edittext in the same position but 10 or 11 rows after the one im actually focusing(the one i can write to).
any knowledge on that case?
also im new to android so i dont know if thats supposed to happen.
this is the List im using.
public class In_List {
private int id;
private String text;
private float a;
private float Qty;
public In_List (int id, String text, float a, float Qty) {
this.id = id;
this.text = text;
this.a = a;
this.Qty= Qty;
}
public String get_text() {
return text;
}
public float get_a() {
return a;
}
public int get_id() {
return id;
}
public float get_Qty() {
return Qty;
}
}
here is the adapter:
public abstract class List_Adapter extends BaseAdapter {
private ArrayList<?> ins;
private int R_layout_IdView;
private Context context;
public Lista_adaptador(Context context, int R_layout_IdView, ArrayList<?> ins) {
super();
this.context = context;
this.ins = ins;
this.R_layout_IdView = R_layout_IdView;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R_layout_IdView, null);
}
onInsert (ins.get(position), view);
return view;
}
#Override
public int getCount() {
return ins.size();
}
#Override
public Object getItem(int position) {
return ins.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public abstract void onInsert (Object insert, View view);
}
and here is the main activity. it has a popup window that i used to fill the value of Qty but i its not included.
public class MainActivity extends Activity {
private ListView list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listing);
ArrayList<In_List> data = new ArrayList<>();
for(int i=0; i<100; i++){
data.add(new In_List(i, "Item Number :"+i+1, i*2,0));
}
list = (ListView) findViewById(R.id.ListView_listing);
list.setAdapter(new List_Adapter(this, R.layout.entry, data){
#Override
public void onInsert(Object entr, View view) {
if (entr != null) {
TextView id_Text = (TextView) view.findViewById(R.id.textView_id);
if (id_Text != null)
id_Text.setText(((In_List) entr).get_id());
TextView info_Text = (TextView) view.findViewById(R.id.textView_info);
if (info_Text != null)
info_Text.setText(((In_List) entr).get_text());
TextView inside_Text = (TextView) view.findViewById(R.id.textView_inside);
if (inside_Text != null)
inside_Text.setText(((In_List) entr).get_a());
TextView Qty_Text = (TextView) view.findViewById(R.id.textView_qty);
if (Qty_Text != null || Qty_Text.getText().toString().equals(0))
Qty_Text.setText(((In_List) entr).get_Qty());
Qty_Text.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Add_Qty();
}
});
}
}
});
// list.setOnItemClickListener(new OnItemClickListener() {
// #Override
// public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// In_List chosen = (In_List) parent.getItemAtPosition(position);
//
// CharSequence text = "Selected: " + chosen.get_textoDebajo();
// Toast toast = Toast.makeText(MainActivity.this, texto, Toast.LENGTH_LONG);
// toast.show();
// }
// });
}
}
now, when i scroll down through the list the Qtys that i have entered either disappear or move to another row.
fixed. i wasn't stablishing Qty_Text value at all. also made a method to save into the adapter array.
EditTexts in generally are very tricky. And using them inside a ListView is almost impossible. The special behaviour of EditTexts for example to always automatically assume focus combinded with the View recycling of the ListViews messes with the ListView and causes a lot of problems. I would suggest you look for another solution. For example placing the EditText inside the HeaderView of the ListView is fine, as the HeaderView is not recycled as you scroll through the ListView.