I have an issue with the Spinner in Android. Selecting an item from the dropdown will adjust the offset of that dropdown the next time it is opened. So for example if I choose item 100 in a 500 item dropdown, the next time I open the dropdown, item 100 will be at the top of the list. This is the behaviour I want.
There seems to be an issue when I combine the selector functionality with calling setSelection(int). With the following steps I seem to have broken the offset system on dropdown spinners.
Open the Spinner and select the second item.
Open the Spinner again and this time dismiss it without selecting anything.
Call setSelection(int) on the Spinner with a value greater than 2.
Open the Spinner a third time. Note that the offset is the same as back in Step 1.
I've taken a look at the code in Spinner and AdapterView, but I can't see anything public calls that I've missed. Is this a bug in Spinner or a bug in my code?
Did you try public void setSelection (int position, boolean animate)? I haven't tried it, but I think passing true as the second parameter should make the list scroll to the selected position. The other alternative is to calculate the scroll offset (item height x selected item position) and call setDropDownVerticalOffset.
Update: I tried modifying the Spinner example in API demos to use setSelection(7, true) and it seems to work when following the 4 steps you provided in your question. I just added a Handler and modified showToast as follows:
private final Handler handler = new Handler();
void showToast(CharSequence msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
handler.postDelayed(new Runnable(){
public void run() {
Toast.makeText(Spinner1.this, "auto setting", Toast.LENGTH_SHORT).show();
Spinner s2 = (Spinner) findViewById(R.id.spinner2);
s2.setSelection(7, true);
}
}, 5000);
}
I tested as follows:
open the second spinner and picking 'Venus' (the second selection).
open the second spinner, then press back to dismiss
after 5 seconds, the postDelayed call causes 'Neptune' (the seventh selection) to be selected
open the spinner and the offset is correct
I think you can solve that problem with sending List to Adapter. When an item selected, sort your List then use notifyDataSetChanged() function of adapter. When you called setSelection(int) function again sort your List and use notifyDataSetChanged() function.
Related
Scenario:
my adapter supports two different view types: A & B
the adapter is notified about 100 items of type A - everything is rendered correctly
the adapter is notified about one item of type B insertion using
notifyItemRangeInserted at position 0 - this item is "invisible"
by default and in order to see it I have to manually scroll up.
How can I get this first item of type B "automatically" visible?
You can use this line of code after notify item of type B:
yourRecyclerView.smoothScrollToPosition(0);
using https://stackoverflow.com/a/54899984/8144663 only wont resolve your issue.
You will need to call smoothScrollToPosition() in the next frame like,
recyclerview.post(new Runnable() {
#Override
public void run() {
recycleview.smoothScrollToPosition(n);
}
});
I have an app where on click of an item I am updating the background image in viewholder in adapter. However, i want to do it such that when I click on one item all other items revert to default images( sort of like toggle back ). Say I have a play button on item 1 and I click it, it switches to pause, then I click on item 2 and it switches to pause and the first button in item 1 switches back to play button. Is there a way to do that in recycler view?
Here's my code in onclick:
#Override
public void onClick(View v) {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
if(!tracks.get(getAdapterPosition()).getMediaUrl().equals(currenturl) ){
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
currenturl = tracks.get(getAdapterPosition()).getMediaUrl();
currentposition = getAdapterPosition();
playAudio(tracks.get(getAdapterPosition()).getMediaUrl());
}
I want to update the currently clicked image such that
mediaUrl.setBackgroundResource(android.R.drawable.ic_media_pause);
for the current item, but reverts back to
mediaUrl.setBackgroundResource(android.R.drawable.ic_media_play);
for the previous item clicked , or can be refreshed to the default value for all other items in the recycleview. Any idea how to go about this in the easiest way posssible? Thanks!
create variable inside your recyclerview adapter itemselected = "number of currently selected item".
in your viewHolder bind check the itemSelectedIndex and apply the style appropriately.
Make onClickListener for the event where you waht to select some item. In the onClick set the itemSelectedIndex = "item number which was clicked". And then call (also in the same method) notifyDataSetChahged.
This will do the job.
notifyDataSetChanged will make your recyclerview to redraw whole item. And, since the "selected" view will also be applied to the itemSelectedIndex item, others will turn unselected.
In order to improve performance of this solution you might want to introduce two indexes:
itemSelected
itemSelectedPrevious.
In this case, in onClick do:
itemSelectedPrevious = itemSelected
itemSelected = "index of current clicked item"
notifyItemChanged(itemSelectedPrevious)
notifyItemChanged(itemSelected)
in this case you'll avoid redrawing of the whole recycleradapter view, but will only update previously selected item to change it's state to non-selected, and also the current item to be active.
Hope this helps :)
When i click on the first item of ListView, the first item is selected. But when i scroll down, the 12th item is selected too, but i didn;t click on the 12th item. Why it was happend?
First screen: http://oi59.tinypic.com/9iw7b8.jpg
Second screen : oi60.tinypic.com/1zxunv4. jpg [delete whitespace]
My sourse code is like that :
http://startandroid.ru/en/uroki/vse-uroki-spiskom/85-urok-44-sobytija-v-listview.html
But i add the white recolor after utem click.
This question was answered here: Checking a checkbox in listview makes other random checkboxes checked too
Basically, when you scroll down you list, it recycles its present state as well as listeners attached to it.
One way I solved this problem is (suposing that your list is called check in java):
Create a boolean array (let's name it listCheck), same size as your checkbox, all values false
Write in your adapter getView method:
check.setChecked(listCheck[position]); //listCheck is your array of booleans.
check.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox checkBox = (CheckBox) v.findViewById(R.id.checkEspecialidade);
listCheck[position] = check.isChecked();
}
});
Basically, we set the check value the same as the one on the array, and when the user clicks it, we also change de value of that check in the array. That works because the boolean array is not recycled.
I currently have a whole bunch of spinners in my application. I wasn't thinking much and for each spinner, the first index is filled with N/A. It's not a big deal, but I was hoping to make it a bit cleaner.
I was wondering if there was a way that instead of calling setSelection( index ), I wanted to know if there was a way to set a Spinner to have nothing selected.
Basically, I want the spinner to have a list of items within it, but display none of them until you click on it. I also don't want there to be a blank index at the top.
I think its quite possible that there is no way to do this, so if anyone is sure of this, please let me know.
Thanks.
Its better to put first position as blank, so that it can be seen as nothing selected.
spinners have to have a selected state. i would recommend having a "no selection" option
Another option is to have the bottom button selected and then set that one to be invisible (the reason i set the last one to selected is so that you dont have a chunk of blank space in your app as that looks a bit trashy):
case SPINNER_OPTION_FIRST:
yourSpinnerLabel.setVisibility(View.VISIBLE);
yourTextField.setVisibility(View.VISIBLE);
break;
// do this for all your other ones if you want
case SPINNER_OPTION_LAST:
yourSpinnerLabel.setVisibility(View.GONE);
yourTextField.setVisibility(View.GONE);
maybe not the most efficient but it works so i hope that helps (still new so cut me some slack)!
Modifying the list which holds data can lead lots of errors or tough to manage the data.
Instead of manipulating the list,you can add item in adapter with NONE item.
Like this
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
adapter.add("NONE");
adapter.addAll(products);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSpinner.setAdapter(adapter);
I tried
// getSelectedItemPosition() returns -1 if there is nothing selected
spinner.setSelection(-1);
but it failed [spinner was setting 1st element from list].
I added "empty position" to spinner data which mimics that "nothing is selected". Note that 'empty position' is not visible on 'drop down' list.
BTW. Sorry for C#, hope the concept is clearly visible.
Custom adapter:
class CustomAdapter<T> : ArrayAdapter<T> {
public override int Count {
get { return base.Count - 1; }
}
}
Init spinner:
var data = new List<string> { "elem 1", "elem 2", "" };
spinner.Adapter = new CustomAdapter<String>(this, Resource.Layout.SimpleSpinnerItem, data);
spinner.SetSelection(2);
I am having problems scrolling up in a spinner to select the first item in a Robotium test case. Here is my code:
int pos = solo.getCurrentSpinners().get(0).getSelectedItemPosition();
solo.pressSpinnerItem(0, 0 - pos);
pos is 1 when I debug, but Robotium still presses the spinner on index 1 even though I order it to press on -1. What am I doing wrong?
Thanks
Markus
Seems they took those classes out now. Just ran into this myself but found a way to do this properly and generically.
// 0 is the first spinner in the layout
View view1 = solo.getView(Spinner.class, 0);
solo.clickOnView(view1);
solo.scrollToTop(); // I put this in here so that it always keeps the list at start
// select the 10th item in the spinner
solo.clickOnView(solo.getView(TextView.class, 10));
The API to use here with Robotium is rather flaky, so I decided to go down the direct API route:
instrumentation.runOnMainSync(new Runnable() {
#Override
public void run() {
Spinner spinner = (Spinner) solo.getView(resourceId);
spinner.setSelection(position, true);
}
});
This won't show you the popup of the Spinner, but it will select the desired item.
are you able just to get the view and call the perform click on it?
solo.getCurrentSpinners().get(0).performClick()