Recyclerview item contains spinner and textviews. All item's spinners are correctly set. Whenever ith item spinner changes, ith item textviews values will also be changed.
The problem here is, one item spinner click action changes other items spinner values.
Adapter class:
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
//do not re-initialize spinner when behaviour of item is changing
if (holder.spinnerWeightUnit.getAdapter() == null) {
List<String> unit_list = new ArrayList<>();
for (Productsku x : productskuList) {
unit_list.add(x.getWeight() + x.getUnit());
}
initializeUnitSpinner(holder.spinnerWeightUnit, unit_list);
holder.spinnerWeightUnit.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
Timber.d("adapter item changed");
setPriceStockValues(holder, position, i);
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {}
});
}
}
private void initializeUnitSpinner(Spinner spinnerUnit, List<String> unit_list) {
ArrayAdapter<String> unitArrayAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, unit_list);
unitArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerUnit.setAdapter(unitArrayAdapter);
}
private void setPriceStockValues(MyViewHolder holder, int position, int unit_position) {
//set textviews
}
scenario:
0th item spinner value selected -> all spinners are correct
1st item spinner value selected -> all spinners are correct
again 0th item spinner value selected -> all spinners are set to 1st item's spinner values
again 1st item spinner values selected -> all spinner are set to 0th item's spinner values
..and so on.
I am unable to find out the solution for this. Please any one can help?
Thank you.
try with removing this line
if (holder.spinnerWeightUnit.getAdapter() == null)
set up your adapter every time when onBindViewHolder get called. RecyclerView uses recycling pattern - reusing previously used/shown Views/ViewHolders. above if prevents to re-set paticluar item on proper position, keeps old OnItemSelected listener and adapter
Related
This is how my viewHolder looks like. It has the spinner element. I have called the getItemCount() method using adapter to get the size of the list that is populated on recycler view. Now User can select an item from the spinner. After user has made all the changes i.e. by changing the spinners in all the views needed, i want to retrieve the changed position of spinners for all the viewholders in a array list. I am working on android recyclerview. There is a list of objects that is passed to the adapter and the list is displayed perfectly. Each of my viewholder have three views in it. These are two text views and one spinner. User can select one of the options available from the spinner and that's how my recyclerview will be updated.
I need help for saving the updated list of object i.e., the spinner position selected by the user for all the list items to generate an xml out of it.
my code looks like this:
int size = mAdapter.getItemCount();
int val[]= new int[size]; //till here it's working perfectly fine
for(int i=0; i<size; i++){
View view_temporary = recyclerView.getChildAt(i);
Spinner spin = (Spinner)view_temporary.findViewById(R.id.action);
val[i] = spin.getSelectedItemPosition();
Log.d("OfficeSpace", ""+val[i]);
}
//here activity crashes
I have resolved the issue. I wanted to save the status of my spinner item present in my view holder after scrolling back to the top. Inside my onBind method of recyclerView, i added this code:
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
final Features feature = mFeatures.get(position); //to get the current object from the list
holder.mSpinner.setSelection(feature.getVal());
holder.mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
mFeatures.get(position).setVal(pos);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
I have a spinner and I want to get the last selected value of it when I click on the spinner (basically just before the items in the list are being shown).
How can I achieve this?
Update:
Example: There are a dynamic amount of spinners. User clicks in spinner 1 and selects a value, let's say "house". Then clicks somewhere else. Then clicks in spinner 1 again. What I now need is to return the value "house" that was previously was selected before the user selects a different value i.e. "car" in that spinner. I can not use the local storage to save that value beforehand because it's going to be a dynamic amount of spinners to be added.
And yes, I did in fact read the documentation at http://developer.android.com/guide/topics/ui/controls/spinner.html already but what I need isn't explained there.
Maybe you can declare a String array and then use it to storage the items values. Showing this in a TextView is a way to see if it works.
Something like this:
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
selection.setText(items[arg2]);
}
I already have faced a similar situation, but I don't remember exactly how I solved it. Tell me if it gives a better idea to you, I'm new participating here.
Spinner mySpinner=(Spinner) findViewById(R.id.your_spinner);
String text = mySpinner.getSelectedItem().toString();
When the user selects an item from the drop-down, the Spinner object
receives an on-item-selected event.
To define the selection event handler for a spinner, implement the
AdapterView.OnItemSelectedListener interface and the corresponding
onItemSelected() callback method. For example, here's an
implementation of the interface in an Activity:
public class SpinnerActivity extends Activity implements OnItemSelectedListener {
...
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
// An item was selected. You can retrieve the selected item using
// parent.getItemAtPosition(pos)
}
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
}
}
The AdapterView.OnItemSelectedListener requires the onItemSelected()
and onNothingSelected() callback methods.
Then you need to specify the interface implementation by calling
setOnItemSelectedListener():
Spinner spinner = (Spinner) findViewById(R.id.spinner);
spinner.setOnItemSelectedListener(this);
IN YOUR CASE:
TO se if the user clicked on the spinner, do this:
if (spin.getSelectedItemPosition() < 0) {
Spinner mySpinner=(Spinner) findViewById(R.id.your_spinner);
String text = mySpinner.getSelectedItem().toString();
}
This means user clicked the spinner, but not any items of it.
EDIT AGAIN
public class SpinnerActivity extends Activity implements OnItemSelectedListener {
> ...
>
> public void onItemSelected(AdapterView<?> parent, View view,
> int pos, long id) {
> parent.getItemAtPosition(pos) //THIS GETS YOU THAT VALUE THAT THE USER CLICKED ON DYNAMICALLY
> }
>
> public void onNothingSelected(AdapterView<?> parent) {
> // Another interface callback
> }
> }
http://developer.android.com/guide/topics/ui/controls/spinner.html
Solution is to add a TextView widget with each added Spinner. Set the TextView to "gone" (not visible). When the spinner changes set the value to that TextView. This way you can store the last selected spinner value in the TextView. When the user clicks on the spinner and changes the value you can still access the previously selected/unselected value from the spinner through the TextView widget.
// Use this TextView to temporarily store the spinner value
final TextView hiddenTextView = new TextView(getContext());
hiddenTextView.setVisibility(View.GONE);
final Spinner spinner = new Spinner(getContext());
spinner.setPrompt(getString(R.string.email_other));
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(), R.array.email_types, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
Log.d(TAG, "TextView Value before spinner change: " + hiddenTextView.getText());
String spinnerValue = String.valueOf(spinner.getSelectedItem());
hiddenTextView.setText(spinnerValue);
Log.d(TAG, "TextView Value after spinner change: " + hiddenTextView.getText());
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
return;
}
});
In my application there are lot's of views(spinner, buttons, editText, textView, ImageButton etc).
After selecting one value in the spinner it not reflect the value which I selected. The old value is till there on the spinner. But when I tap on other views like editTest then spinner value automatically updated.
I think no need to mention the code because normal spinner is there which populating data from ArrayAdapter and I am doing small task after selecting value.
CODE:-
spinnerWard = (Spinner) findViewById(R.id.spinnerWard);
aAdapterWard = new ArrayAdapter<WardList>(this,
android.R.layout.simple_spinner_item, listWard);
aAdapterWard.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerWard.setAdapter(aAdapterWard);
spinnerWard.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View v,
int pos, long id) {
intWardPosition = pos;
intFinalWardId = listWard.get(pos).getId();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {}
});
I have two spinner in dialog. Second one is dependent on first one. I want to bind it and then select it in edit mode. All works fine but second spinner does not get selected. However it get selected when I open my dialog next time.
Here is a part of my code.
ArrayAdapter<String> myAdap1 = (ArrayAdapter<String>) spnForeignKeyTable
.getAdapter();
int spinnerPosition1 = myAdap1.getPosition(objcolumn_schema
.getForeignKeyTable());
spnForeignKeyTable.setSelection(spinnerPosition1);
// Bind Column Spinner.Second spinner
dblist = DBAdapter.getColumns(pf.getString("dbid", ""),String.valueOf(objcolumn_schema.getForeignKeyTableID()));
ArrayAdapter<String> adpf = new ArrayAdapter<String>(
column.this, android.R.layout.simple_spinner_item,
dblist);
adpf.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnForeignKeyColumn.setAdapter(adpf);
int spinnerPosition2 = adpf.getPosition(objcolumn_schema.getForeignKey());
spnForeignKeyColumn.setSelection(spinnerPosition2);
for changing selected item in second spinner when first spinner selection change you will need to set setOnItemSelectedListener for first spinner as:
spinnerPosition1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> arg0, View v,
int position, long id)
{
// change second Spinner selection here
}
public void onNothingSelected(AdapterView<?> arg0)
{
//
}
});
Spinner OnclickListener event executes twice -
Spinner initialization
User selected manually
where as implementation of listener is as :
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
Problem definition
I want to save user selected text into data storage, when user choose any item from spinner, and I am able to do this. But my another task is that to show previously selected item (access from data storage) as selected item in spinner, but each time when I call spinner's activity, spinner shows first item as default selected item, and also in data storage it make change previous item to default.
How can I make difference between 'Spinner initialization' and 'User selected manually' events?
You have to handle both events logically. As these references (Android Spinner selection, problem on spinner) says that you have to use flag variable to handle this, I am putting a code sample.
Hope this will help you to clear your logic.
public class TestActivity extends Activity {
//Checks report spinner selection is default or user selected item
private boolean isDefaultSelection;
//Spinner setup
Spinner spinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
// Set true at onCreate
isDefaultSelection = true;
spinner = (Spinner) findViewById(R.id.id_of_spinner);
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String> (this, R.layout.drop_down_custom_row, data);
//Implement custom view for drop down of spinner
//spinnerAdapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerAdapter);
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(isDefaultSelection) { //If spinner initializes
spinner.setSelection("Set_here_id_of_data_item_from_storage_which_was_previously_stored");
isDefaultSelection = false;
} else { //If user manually select item
int itemPosition = spinner.getSelectedItemPosition();
//Write here code to store selection (itemPosition) of user into data storage
}
}
public void onNothingSelected(AdapterView<?> parent) {
//User selected same item. Nothing to do.
}
});
}
}
Hope it will clear your doubt.
You can call the setSelection at the same time that the items are added to the adapter, see this example: How to avoid onItemSelected to be called twice in Spinners