I used to dynamically populate a Table Layout with different elements per row, among them a Spinner.
To handle the initialization of spinner values i used what most recommended: a boolean flag variable. The code went something like this
public class spinnerHandling implements OnItemSelectedListener{
public void dynamicallyPopulateTableLayout(int a){
...
//initialize spinner with default values
mySpinner.setSelection(a);
mySpinner.setTag(true);
mySpinner.setOnItemSelectedListener(this);
...
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
if(!(Boolean)parent.getTag()){
//my code
...
}
parent.setTag(false);
}
}
This worked fine.
Later i decided that i should use a List View instead of a Table Layout. For that i have a custom ArrayAdapter that uses a row Layout, in which of course i have a Spinner, to populate the List View. As those of you who are familiar with List Views, understand its complex dynamic behavior, would know that the somehow static turn around of the boolean flag method wont work.
After three days of tremendous headache trying to find a way to resolve this issue, i just came across the spinner's isDirty() method that in contrast with isPressed(), isSelected(), etc. actually changes its boolean values when spinner item is selected by user.
the code is something like this:
public class spinnerHandling implements OnItemSelectedListener{
public void dynamicallyPopulateListView(int a){
...
//initialize spinner with default values
mySpinner.setSelection(a);
mySpinner.setOnItemSelectedListener(this);
...
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
if(!parent.isDirty()){
//my code
...
}
}
}
This seems to work fine!
But i would like to make sure that isDirty() handles properly spinner initialization and user selection.
Can you please confirm or contradict this behavior?
Thank you.
Related
this is my situation:
I want to pass a listener to a view generator for using it. but the problem is in my listener I want to use that View to get some data. some how twisted...
is that a way to pre-define a View like a interface that Listener should attach to?
AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long l) {
//but I can not do this and use spinner cause it is not defined
String text = spinner.getSelectedStrings().toString();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {}
};
generateSpinner(attributes, listener);
I'm working on MVC project in android and this issue come out from there, cause I should separate creation and Logic to View and Presenter. So my presenter force view to generate a spinner with given logic.
You have answered more than half of your question yourself. Make an interface like this:
public interface MyViewCallback
{
void run(View view);
}
Now, you can store a instance of this interface and call its run() method from your View's scope whenever you need to - for example,
MyViewCallback callback;
// ... on some action
callback.run(this);
You can create a setter for this callback and use it to register a callback.
Hi guys this is rather a silly question because i'm confused. what i'm trying to do is to call a method(share to facebook) from an activity inside my adapter.
this is the illustration:
Activity:
postToFacebook(Pets dog);
listview that holds list of dogs.
Adapter:
adapter in which i use to create custom view for better looking.
problem is that i want to set an onLongClickListener on the LinearLayout that holds all the dog's info (this way user can hold any part of the info) to be shared to facebook.
is there a way to do this?
thanks a lot!
If I understand your question you are complety on bad way
In your activity you have an ArrayList (or List) with Dogs information
Something like
ArrayList<Pets> listDogs;
now, you should do this (myListView is your ListView obj)
myListView.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int pos, long id) {
postToFacebook(listDogs.get(pos));
return true;
}
});
In this way you get the position of element selected and call your method from activity and not from adapter.
listDogs.get(pos)
this line return the element of the row selected.
So I've been following some advice around similar questions and I somehow couldn't manage to get into it. I have a spinner called 'e' from which I want to retrieve the selected string when the user clicks a button below it.
I implemented the nested class like this:
class SelectedListener implements OnItemSelectedListener{
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id){
String selected = parent.getItemAtPosition(pos).toString();
}
public void onNothingSelected(AdapterView parent){
//does nothing
}
}
e.setOnItemSelectedListener(new SelectedListener());
Just following the advice from other users around here and the android developers tutorial, the thing is, after this, I don't know which call should I make to retrieve it if I want to save it into a String variable like so:
String selected = //don't know what to put here
Hope is clear enough. Thanks in advance.
I'm pretty sure:
e.getSelectedItem().toString()
i have two spinners.
If in the first one the Item "Diesel" is selected i want to display the second one.
sKraftstoffArt.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
if(sKraftstoffArt.getSelectedItem().toString() == "Diesel"){
sPartikelfilterArt.setVisibility(sPartikelfilterArt.VISIBLE);
}
}
public void onNothingSelected(AdapterView<?> adapterView) {
return;
}
});
I've implemented this code in the onCreate method. When i select a item during the runtime i'm not getting the selected item text... It works only if the activity gets created and the default value gets selected....
Where else do i have to implement it?
Regards,
float
Unless your sKraftstoffArt object is not a final one, the check against it's selected item text inside an anonymous class won't work.
The adapterView among the parameters is your ListView instance to which you've assigned the AdapterView.OnItemClickListener.
The view parameter is the actual item (renderer) inside your ListView that has been clicked. This item is provided by your adapter's getView(int position, View convertView, ViewGroup parent) method.
Also, you should use the equals method of String to check whether two String values are equal.
So this won't work:
if(sKraftstoffArt.getSelectedItem().toString() == "Diesel")
Use insetad
if (adapterView.getSelectedItem().toString().equals("Diesel"))
You might also want to add an else clause after this if, to hide the sPartikelfilterArt spinner when the selected item in the previous spinner is not "Diesel".
Please note, that every time you assign a new adapter to this list (which probably you don't, i still mention it just in case...), you should add the AdapterView.OnItemClickListener to it again.
It appears that android's Spinner class (and possibly ListView in general, although I don't know for sure) calls your OnItemSelectedListener's onItemSelected() method after you call setAdapter(), even if the user hasn't explicitly selected anything yet.
I can see how this would be useful in many situations, but there are times when I only want onItemSelected() to be called when an item is actually specifically selected.
Is there a way to control this behaviour and have Spinner NOT call onItemSelected() after setting the adapter?
I haven't used this solution for very long yet so I'm not totally confident that it works as expected, but I've had luck so far with this workaround:
spinner.setOnItemSelectedListener( new OnItemSelectedListener() {
protected Adapter initializedAdapter = null;
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// Always ignore the initial selection performed after setAdapter
if( initializedAdapter !=parent.getAdapter() ) {
initializedAdapter = parent.getAdapter();
return;
}
...
}
}
Is there a better way?
Add listener to spinner like below:
spinner.post(new Runnable(){
public void run()
{
spinner.setOnItemSelectedListener( new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
...
}
}
}
});
I've used the setTag and getTag methods, and created a resource id called "spinnerstate".
Then whenever I programmatically set the adapter, I set the "spinnerstate" tag to "init", and in the fired event, set it to "ready" and ignore the event. (note my code is Mono for Android se it will look different):
Set Adapter:
profileSpn.SetTag (Resource.Id.spinnerstate, "init");
profileSpn.Adapter = new ArrayAdapter (this, Android.Resource.Layout.SimpleSpinnerItem, items.ToArray ());
Item Selected event:
string state = (string)((Spinner)sender).GetTag (Resource.Id.spinnerstate);
if (state == "init") {
((Spinner)sender).SetTag (Resource.Id.spinnerstate, "ready");
return;
}
I agree that this is not desired behaviour in almost 100% of cases, and I don't think it's good design on the part of Google, but there you go.
I did similar things before, I used count value. Using parent adapter object is incomplete because it can be a problem when view is refreshed or getView() called again.
Therefore, I recommend that using array of counter.
At first, define array of count in adapter globally.
private int isInitializedView[];
And then initialize it on getView().
isInitializedView[position] = 0;
In the selection listener, do something that you want if it already initialized.
holder.mySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
isInitializedView[position]++;
if(isInitializedView[position] > 1) {
// do someting that you want
}
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {}
});
(Note that isInitializedView[position]++; can be come after if() routine, and only trigger event when this value is >0 . It's your choice.)
I had three spinner in my activity and all spinner adapter data has been filled at runtime(from web-service data after call from onCreate method). So it automatically call onItemSelected(AdapterView<?> parent, View view, int position, long id) method of spinner.
I solved this issue by using onUserInteraction() method of activity
check this method that user is interacting with spinner or not. if yes then perform the action else not
Declare isUserIntract boolean variable globally
in onItemSelected method use following procedure
If(isUserIntract)
{
//perform Action
}
else{
//not perform action
}
use below code in activity
#Override
public void onUserInteraction() {
super.onUserInteraction();
isUserIntract = true;
}