Android 微调器:获取所选项目更改事件

Android Spinner: Get the selected item change event

提问人:Soni Ali 提问时间:8/27/2009 最后编辑:Vadim KotovSoni Ali 更新时间:11/25/2020 访问量:581327

问:

当所选项目发生更改时,如何为微调器设置事件侦听器?

基本上,我正在尝试做的是类似于以下内容:

spinner1.onSelectionChange = handleSelectionChange;

void handleSelectionChange(Object sender){
    //handle event
}
Android 事件 微调器 android-spinner

评论


答:

8赞 Chiwai Chan 8/28/2009 #1
spinner1.setOnItemSelectedListener(
    new AdapterView.OnItemSelectedListener() {
        //add some code here
    }
);

评论

3赞 Yevgeny Simkin 3/1/2011
这并不能解决在首次启动微调器时调用此回调的问题(从而引发与实际选择的项无关的响应)。
8赞 johndotnet 11/7/2009 #2

微调器小部件的文档说

微调器不支持项目单击事件。

你应该用它来处理你的问题。setOnItemSelectedListener

901赞 znq 11/11/2009 #3

前面的一些答案是不正确的。它们适用于其他小部件和视图,但微调器小部件的文档明确指出:

微调器不支持项目单击 事件。调用此方法将引发 异常。

最好改用 OnItemSelectedListener():

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
        // your code here
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // your code here
    }

});

这对我有用。

请注意,onItemSelected 方法也会在构建视图时调用,因此您可以考虑将其放在方法调用中。onCreate()

评论

53赞 Kennethvr 12/28/2010
这样做的问题是,在构建视图时也会调用 onItemSelected 方法。因此,写入其中的代码也会在启动时执行。有没有办法只有在用户调用了实际项目选择时才执行包含代码?
40赞 Kennethvr 12/28/2010
实际上,这个问题可以通过将 setOnItemSelectedListener 放在重写 OnStart 方法而不是 onCreate 方法中来解决。愚蠢的我......
17赞 Yevgeny Simkin 3/1/2011
我已将侦听器放在 onStart 方法中,但它是在用户看到任何内容之前调用的,就像 onCreate 一样,因此,在我的情况下,在用户选择某些内容之前,一个“继续”按钮是不可见的,该按钮在初始显示时可见。你是说你的经历不同吗?如果是这样,您在我缺少的 onStart 方法中做了什么不同的事情?
7赞 Sam Svenbjorgchristiensensen 3/21/2011
使用匿名侦听器中的另一个字段来记录第一个选择,并告诉 onItemSelected 除非遇到选择,否则不要执行任何操作?只是一个想法。
4赞 Andrew Wyld 3/24/2012
但是,如果用户选择“默认”项目,即顶部的项目呢?然后不被击中。(我知道,因为我刚刚以艰难的方式发现了这一点。onItemSelected(...)
64赞 Santhosh 4/29/2010 #4
Spinner spnLocale = (Spinner)findViewById(R.id.spnLocale);

spnLocale.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
        // Your code here
    } 

    public void onNothingSelected(AdapterView<?> adapterView) {
        return;
    } 
}); 

注意:记住一件事。

Spinner 事件将执行两次:OnItemSelectedListener

  1. 微调器初始化
  2. 手动选择的用户

尝试通过使用 flag 变量来区分这两者。

评论

22赞 Yevgeny Simkin 3/1/2011
只需设置一个全局布尔值,例如 Boolean initialDisplay = true;然后在 onSelect 中查看它是否为 true,如果是,则不要在 select 上执行任何其他操作,而是将标志设置为 false,以便下次调用它时(当用户实际选择时)。
0赞 jedi 11/28/2013
Genia S. 方法效果不佳,因为确实第一次触发 onselect 事件(on onCreate 方法),您可以通过全局变量排除此事件,但如果那时我需要在微调器上选择已选择的项目(默认项目,第一个)它不会被触发。我试图放置一个微调器标签并排除它,但它将在打开的对话框中可见。我同意@Batdude。微调器是一个搞砸了的小部件。
0赞 LarsH 7/25/2019
另请注意,如果您使用 Genia S 的方法,并且有多个微调器使用相同的微调器,则必须单独跟踪每个微调器的 initialDisplay,或者计算初始调用,直到达到微调器的数量。8-2onItemSelectedListener
21赞 Sampath 11/24/2011 #5

https://stackoverflow.com/q/1714426/811625

您可以通过简单的检查来避免调用 OnItemSelectedListener():将当前选择索引存储在整数变量中,并在执行任何操作之前在 onItemSelected(..) 中进行检查。

例如:

Spinner spnLocale;

spnLocale = (Spinner)findViewById(R.id.spnLocale);

int iCurrentSelection = spnLocale.getSelectedItemPosition();

spnLocale.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
    if (iCurrentSelection != i){
            // Your code here
    }
    iCurrentSelection = i;
    } 

    public void onNothingSelected(AdapterView<?> adapterView) {
        return;
    } 
}); 

原因 iCurrentSelection 应该在对象范围内才能正常工作!

评论

1赞 dahvyd 5/19/2012
不能在匿名内部类中使用非 final 变量。如果变量是在这个匿名类中声明的,它将正常工作。您可以将其初始化为 -1,以便在第一次调用时执行代码。iCurrentSelection
1赞 Pinakin Kansara 3/16/2012 #6

我认为最好的方式是拥有一个.并在项目选定的事件上增加该标志,即 ;然后检查flagitemselected = 0;onCreate()flagitemselected++

if(flagitemselected!=1)
{
// do your work here
}

我想这会有所帮助。

0赞 Joe Plante 8/11/2012 #7

我发现的一个技巧是将 setOnItemSelectedListeners 放在 onWindowFocusChanged 而不是 onCreate 中。我还没有发现这样做有任何不良副作用。基本上,在绘制窗口后设置侦听器。我不确定onWindowFocusChanged运行的频率,但是如果您发现它运行得太频繁,可以很容易地为自己创建一个锁定变量。

我认为 Android 可能正在使用基于消息的处理系统,如果您将其全部放在 onCreate 中,您可能会遇到微调器在绘制后被填充的情况。因此,您的侦听器将在您设置项目位置后触发。当然,这是一个有根据的猜测,但请随时纠正我。

9赞 droidster.me 12/10/2012 #8

找到您的微调器名称并找到 id,然后实现此方法。

spinnername.setOnItemSelectedListener(new OnItemSelectedListener() {

    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
        // your code here
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // your code here
    }
});
25赞 anon 3/27/2013 #9

您可以在 Activity 中实现类。AdapterView.OnItemSelectedListener

然后在onCreate()

Spinner spin = (Spinner) findViewById(R.id.spinner);
spin.setOnItemSelectedListener(this);

然后覆盖以下两种方法:

public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
    selection.setText(items[position]);
}

public void onNothingSelected(AdapterView<?> parent) {
    selection.setText("");
}

评论

0赞 Machavity 9/23/2023
原始来源:commonsware.com/Android/excerpt.pdf#page=10
3赞 r-magalhaes 11/12/2013 #10
spinner.setOnItemSelectedListener(
            new AdapterView.OnItemSelectedListener() {

                @Override
                public void onItemSelected(AdapterView<?> arg0, View arg1,
                        int arg2, long arg3) {

                    // TODO Auto-generated method stub
                }

                @Override
                public void onNothingSelected(AdapterView<?> arg0) {
                    // TODO Auto-generated method stub

                }
                //add some code here
            }
        );
4赞 indrajeet 7/27/2016 #11

取一个全局变量来表示当前选择的微调器:

int currentItem = 0;

spinner_counter = (Spinner)findViewById(R.id.spinner_counter);
String[] value={"20","40","60","80","100","All"};
aa=new ArrayAdapter<String>(this,R.layout.spinner_item_profile,value);
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_counter.setAdapter(aa);

spinner_counter.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if(currentItem == position){
                return; //do nothing
            }
            else
            {
                 TextView spinner_item_text = (TextView) view;
                 //write your code here
            }
            currentItem = position;
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

//R.layout.spinner_item_profile
<?xml version="1.0" encoding="utf-8"?>

<TextView  android:id="@+id/spinner_item_text"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" 
android:layout_height="wrap_content"
android:background="@drawable/border_close_profile"
android:gravity="start"  
android:textColor="@color/black"         
android:paddingLeft="5dip"
android:paddingStart="5dip"
android:paddingTop="12dip"
android:paddingBottom="12dip"
/>

//drawable/border_close_profile
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
   <shape android:shape="rectangle">
    <solid android:color="#e2e3d7" />
   </shape>
 </item>
<item android:left="1dp"
android:right="1dp"
android:top="1dp"
android:bottom="1dp">
<shape android:shape="rectangle">
    <solid android:color="@color/white_text" />
</shape>
</item>
</layer-list>
12赞 Leo DroidCoder 8/23/2016 #12

在 onCreate 或 onStart 中设置 OnItemSelectedListener 并不重要 - 它仍然会在 Activity 创建或启动期间(分别)调用。
因此,我们可以在 onCreate 中设置它(而不是在 onStart 中设置它!
只需添加一个标志即可确定第一次初始化:

private Spinner mSpinner;
private boolean mSpinnerInitialized;

然后在 onCreate(或 onCreateView)中:

mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                if (!mSpinnerInitialized) {
                    mSpinnerInitialized = true;
                    return;
                }

                // do stuff
            }

            public void onNothingSelected(AdapterView<?> adapterView) {
                return;
            }
        });
4赞 fishjd 11/22/2016 #13

如果你想要一个真正的 onChangedListener()。将初始值存储在处理程序中,并检查它是否已更改。它很简单,不需要全局变量。如果页面上有多个微调器,则有效。

String initialValue = // get from Database or your object
mySpinner.setOnItemSelectedListener(new SpinnerSelectedListener(initialValue));

...

protected class SpinnerSelectedListener implements AdapterView.OnItemSelectedListener {

        private SpinnerSelectedListener() {
            super();
        }

        public SpinnerSelectedListener(String initialValue) {
            this();
            this.initialValue = initialValue;
        }

        private String initialValue;

        // getter and setter removed.  

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            final String newValue = (String) spinHeight.getItemAtPosition(position);
            if (newValue.equals(initialValue) == false) {
               // Add your code here.  The spinner has changed value. 

               // Maybe useful.   
               // initialValue = newValue;
            }

        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
               // Maybe useful.   
               // initialValue = null; 
        }
    }

对象是你的朋友,使用它们。

2赞 S Kranthi Kumar 1/9/2019 #14

这将起作用 初始化微调器和 FindViewById 并使用它即可工作

    Spinner schemeStatusSpinner;

  schemeStatusSpinner = (Spinner) dialog.findViewById(R.id.spinner);

schemeStatusSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            // your code here
            if(schemeStatusSpinner.getSelectedItemId()==4){
                reasonll.setVisibility(View.VISIBLE);
            }
            else {
                reasonll.setVisibility(View.GONE);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
            // your code here
        }

    });
2赞 Adam Noor 1/23/2020 #15

默认情况下,您将通过以下方式获取微调器数组的第一项

value = spinner.getSelectedItem().toString();

每当您在微调器中选择值时,都会为您提供所选值

如果你想要所选项目的位置,那就这样做

pos = spinner.getSelectedItemPosition();

以上两个答案是针对不应用监听器的

8赞 Abduhafiz 7/18/2020 #16

对于 kotlin,您可以使用:

spinner.onItemSelectedListener =  object : AdapterView.OnItemSelectedListener {
    override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        
    }

    override fun onNothingSelected(p0: AdapterView<*>?) {
        
    }
}

注意:对于方法的参数,我使用自定义变量名称onItemSelected

1赞 UnknownError 11/25/2020 #17

我知道这个问题早就解决了,但我的字符串数组顶部有一个“请选择”字符串。然后,当你编写侦听器时

yourspinner.onItemSelectedListener = object : OnItemSelectedListener {
            override fun onItemSelected(adapterView: AdapterView<*>?, view: View, i: Int, l: Long) {
                yourvalue = yourspinner.getSelectedItem().toString()

                when(yourvalue){
                    "Please Select" -> // DO nothing
                    else -> // Do something
                }
            }

            override fun onNothingSelected(adapterView: AdapterView<*>?) {
                return
            }
        }

当然,您可以扩展 when 语句以具有不同的响应或操作。