当再次选择当前选定的项目时,如何在Android Spinner中获取事件?

当再次选择当前选定的项目时,如何在Android Spinner中获取事件?,android,Android,我已经为微调器编写了一个setOnItemSelectedListener,以便在微调器项更改时作出响应。我的要求是,当我再次单击当前选定的项目时,应该会显示一个祝酒词。如何获得此活动?再次单击当前选定的项目时,微调器没有响应。` StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){ @Override public void onItemSe

我已经为微调器编写了一个setOnItemSelectedListener,以便在微调器项更改时作出响应。我的要求是,当我再次单击当前选定的项目时,应该会显示一个祝酒词。如何获得此活动?再次单击当前选定的项目时,微调器没有响应。`

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  

试试这个

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
@Override
public void onItemSelected(AdapterView adapter, View v, int i, long lng) {  

    if(v.hasFocus() {            
        Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();
    }    
}

希望它能起作用。

我发现,如果在微调器中再次选择同一项,则不会调用OnItemSelectedListener。当我单击微调器并再次选择相同的值时,则不会调用OnItemSelectedListener方法。如果人们单击根据UI设计已经处于活动状态的选择,他们不会期望发生什么

当您再次单击当前选定的项目时,它将无法触发任何事件。因此,您无法捕获用于微调器响应的setOnItemSelectedListener

此微调器将始终告诉您选择已更改:

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
package com.mitosoft.ui.widgets;

import java.lang.reflect.Method;
import android.content.Context;
import android.content.DialogInterface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.AdapterView;
import android.widget.Spinner;

//com.mitosoft.ui.widgets.NoDefaultSpinner
public class NoDefaultSpinner extends Spinner {

    private int lastSelected = 0;
    private static Method s_pSelectionChangedMethod = null;


    static {        
        try {
            Class noparams[] = {};
            Class targetClass = AdapterView.class;

            s_pSelectionChangedMethod = targetClass.getDeclaredMethod("selectionChanged", noparams);            
            if (s_pSelectionChangedMethod != null) {
                s_pSelectionChangedMethod.setAccessible(true);              
            }

        } catch( Exception e ) {
            Log.e("Custom spinner, reflection bug:", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    public NoDefaultSpinner(Context context) {
        super(context);
    }

    public NoDefaultSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void testReflectionForSelectionChanged() {
        try {
            Class noparams[] = {};          
            s_pSelectionChangedMethod.invoke(this, noparams);
        } catch (Exception e) {
            Log.e("Custom spinner, reflection bug: ", e.getMessage());
            e.printStackTrace();                
        }
    } 




    @Override
    public void onClick(DialogInterface dialog, int which) {    
        super.onClick(dialog, which);
            if(lastSelected == which)
                testReflectionForSelectionChanged();

            lastSelected = which;
    }
}

@迪米特尔。哇,太棒了。谢谢你。我不能给你的解决方案投票(分数不够),但是NoDefaultSpinner类可以工作。只有一件事是个问题:因为您调用super.onClick,然后在“onClick”中调用testReflectionForSelectionChanged(),所以如果选择确实发生了更改,您将获得两次调用微调器的onItemSelected处理程序(而如果重新选择相同的项,则功能是正确的)。我通过破解解决了这个问题。我添加了一个onTouchEvent覆盖,记录了被触摸的项目,然后在“onClick”中检查是否发生了更改:

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  

您好&感谢@Dimitar为这个问题提供了创造性的答案。我已经试过了,它在旧的Android版本(如2.x)上运行得很好,但不幸的是,它在3.0和更高版本(试过3.2和4.0.3)上不起作用。由于某些原因,在较新的平台上从未调用过onClick方法。有人在这里为此编写了错误报告:

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
不能在较新的平台上运行意味着我需要一个不同的解决方案。在我的应用程序中,模拟一个未选择的微调器,在开始时有一个隐藏的“虚拟”条目就足够了。然后,如果将“隐藏”项设置为选择项,则单击的每个项都将导致回调。对于某些人来说,一个缺点可能是不会显示任何选定项,但可以使用微调器类覆盖技巧来修复

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  

请参阅

了解更新的平台,尝试将此添加到Dimitar的解决方案中。我认为它有效:)

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
(您必须重写onLayout并删除onClick方法)

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  

我花了好几个小时试图找到解决这个问题的方法。我的结论如下。我不确定它是否在所有情况下都有效,但它似乎对我有效。它只是Spinner类的扩展,它检查选择并在选择设置为相同值时调用侦听器

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Spinner;


/** Spinner extension that calls onItemSelected even when the selection is the same as its previous value */
public class NDSpinner extends Spinner {

    public NDSpinner(Context context)
    { super(context); }

    public NDSpinner(Context context, AttributeSet attrs)
    { super(context, attrs); }

    public NDSpinner(Context context, AttributeSet attrs, int defStyle)
    { super(context, attrs, defStyle); }

    @Override 
    public void setSelection(int position, boolean animate) {
        boolean sameSelected = position == getSelectedItemPosition();
        super.setSelection(position, animate);
        if (sameSelected) {
            // Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
            getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
        }
    } 

    @Override
    public void setSelection(int position) {
        boolean sameSelected = position == getSelectedItemPosition();
        super.setSelection(position);
        if (sameSelected) {
            // Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
            getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
        }
    }

}
试试这个

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
公共类MySpinner扩展微调器{
我选择了一个听者;
公共MySpinner(上下文、属性集属性)
{
超级(上下文,attrs);
}
@凌驾
公共选举(内部职位)
{
超级选举(职位);
if(position==getSelectedItemPosition())
{
listener.onItemSelected(null,null,position,0);
}       
}
public void setOnItemSelectedListener(OnItemSelectedListener侦听器)
{
this.listener=listener;
}
}

我想我应该给那些使用较新Android版本的人留下一个更新的答案

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
我根据上述答案编译了一个函数,它至少适用于4.1.2和4.3(我测试的设备)。此函数不使用反射,而是跟踪最后选择的索引本身,因此即使SDK更改了类彼此扩展的方式,也应该可以安全使用

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Spinner;

public class SelectAgainSpinner extends Spinner {

    private int lastSelected = 0;

    public SelectAgainSpinner(Context context)
    { super(context); }

    public SelectAgainSpinner(Context context, AttributeSet attrs)
    { super(context, attrs); }

    public SelectAgainSpinner(Context context, AttributeSet attrs, int defStyle)
    { super(context, attrs, defStyle); }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if(this.lastSelected == this.getSelectedItemPosition() && getOnItemSelectedListener() != null)
            getOnItemSelectedListener().onItemSelected(this, getSelectedView(), this.getSelectedItemPosition(), getSelectedItemId());
        if(!changed)
            lastSelected = this.getSelectedItemPosition();

        super.onLayout(changed, l, t, r, b);
    } 
}

我的解决方案基于benoffi7的MySpinner。通过保存上次选择的父项和视图,修复了在同一项选择上传递空值的问题

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  
public class MySpinner extends Spinner {

    private OnItemSelectedListener listener;
    private AdapterView<?> lastParent;
    private View lastView;
    private long lastId;

    public MySpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
        initInternalListener();
    }

    public MySpinner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initInternalListener();
    }

    private void initInternalListener() {
        super.setOnItemSelectedListener(new OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> parent, View view,
                int position, long id) {
                lastParent = parent;
                lastView = view;
                lastId = id;
                if (listener != null) {
                    listener.onItemSelected(parent, view, position, id);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                //lastParent = parent; // do we need it?
                if (listener != null) {
                    listener.onNothingSelected(parent);
                }
            }
        });
    }

    @Override
    public void setSelection(int position) {
        if (position == getSelectedItemPosition() && listener != null) {
            listener.onItemSelected(lastParent, lastView, position, lastId);
        } else {
            super.setSelection(position);
        }
    }

    @Override
    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
        this.listener = listener;
    }
}
公共类MySpinner扩展微调器{
私密的被选中的监听器;
私人AdapterView lastParent;
私有视图;
私人长拉斯蒂德;
公共MySpinner(上下文、属性集属性){
超级(上下文,attrs);
initInternalListener();
}
公共MySpinner(上下文、属性集属性、int-defStyle){
超级(上下文、属性、定义样式);
initInternalListener();
}
私有void initInternalListener(){
super.setOnItemSelectedListener(新的OnItemSelectedListener(){
@凌驾
已选择公共视图(AdapterView父视图、视图、,
内部位置,长id){
lastParent=父对象;
lastView=视图;
lastId=id;
if(侦听器!=null){
listener.onItemSelected(父级、视图、位置、id);
}
}
@凌驾
未选择公共无效(AdapterView父级){
//lastParent=parent;//我们需要它吗?
if(侦听器!=null){
listener.onNothingSelected(父级);
}
}
});
}
@凌驾
公共选举(内部职位){
if(position==getSelectedItemPosition()&&listener!=null){
listener.onItemSelected(lastParent、lastView、position、lastId);
}否则{
超级选举(职位);
}
}
@凌驾
public void setOnItemSelectedListener(OnItemSelectedListener侦听器){
this.listener=listener;
}
}

如果您确实想在微调器显示时在XML中执行此任务,请添加一个编辑文本并设置可见性属性;并在view.onclicklisner上为微调器和服装内适配器集创建服装适配器,然后单击事件激发EditText.setText(“0”);在活动集edittext textWatcher事件和事件块中,添加OnSpinerItem Ev
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatSpinner

class MoreSpinner : AppCompatSpinner {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun setSelection(position: Int, animate: Boolean) {
        val sameSelected = position == selectedItemPosition
        super.setSelection(position, animate)
        if (sameSelected) {
            onItemSelectedListener?.onItemSelected(
                this,
                selectedView,
                position,
                selectedItemId
            )
        }
    }

    override fun setSelection(position: Int) {
        val sameSelected = position == selectedItemPosition
        super.setSelection(position)
        if (sameSelected) {
            onItemSelectedListener?.onItemSelected(
                this,
                selectedView,
                position,
                selectedItemId
            )
        }
    }
}