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

ind*_*ira 56 android

我为spinner编写了一个setOnItemSelectedListener,以便在更改微调器项时进行响应.我的要求是当我再次点击当前选择的项目时,应显示一个Toast.如何举办此活动?再次单击当前选定的项目时,微调器没有响应.`

    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();

        }
    });  
Run Code Online (Sandbox Code Playgroud)

小智 124

我花了几个小时试图找到解决这个问题的方法.我最终得到了以下内容.我不确定它是否适用于所有情况,但它似乎对我有用.它只是Spinner类的扩展,它检查选择并在选择设置为相同值时调用侦听器.

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());
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 请注意使用"setSelection(int position)",它是Spinner.java类的一部分,是一个公共API."setSelection(int position,boolean animate)"是AbsSpinner的一部分,对我来说不是在JB平台上调用的. (12认同)
  • +1不使用反射并坚持使用公共API! (6认同)
  • 让我知道如何在我的活动中使用它 (2认同)
  • 谢谢,效果很好。只是不要忘记尝试在此处捕获NullPointer:getOnItemSelectedListener()。onItemSelected(this,getSelectedView(),position,getSelectedItemId()); (2认同)

ben*_*fi7 25

试试这个

public class MySpinner extends Spinner{

OnItemSelectedListener listener;

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

    @Override
    public void setSelection(int position)
    {
        super.setSelection(position);

        if (position == getSelectedItemPosition())
        {
            listener.onItemSelected(null, null, position, 0);
        }       
    }

    public void setOnItemSelectedListener(OnItemSelectedListener listener)
    {
        this.listener = listener;
    }
}
Run Code Online (Sandbox Code Playgroud)


Dim*_*man 15

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不适用于最新的Android版本,onclick永远不会被调用. (6认同)

Dem*_*yro 7

我想我会为那些处理较新Android版本的人留下更新的答案.

我汇总了上述答案中的一个函数,该函数至少适用于4.1.2和4.3(我测试过的设备).此函数不使用反射,而是跟踪最后选择的索引本身,因此即使SDK更改了类相互扩展的方式,也应该安全使用.

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);
    } 
}
Run Code Online (Sandbox Code Playgroud)


do0*_*o01 6

kotlin,希望它有帮助

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
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

对于较新的平台,请尝试将其添加到Dimitar的解决方案中.我觉得它有效:)

(你必须覆盖onLayout并删除onClick方法)

    @Override
public void onClick(DialogInterface dialog, int which) {    
    super.onClick(dialog, which);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    if(this.lastSelected == this.getSelectedItemPosition())
        testReflectionForSelectionChanged();
    if(!changed)
        lastSelected = this.getSelectedItemPosition();

    super.onLayout(changed, l, t, r, b);
} 
Run Code Online (Sandbox Code Playgroud)


Dat*_*nde -22

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

  • 为什么这个答案被标记为正确答案?还有+50???我认为这对解决问题没有任何帮助!如果我错了,有人纠正我。 (70认同)
  • 我也有同样的问题。为什么+50呢。问:我怎样才能让它发挥作用。答:目前还不行。哎呀。 (3认同)
  • 这不是@indira 正在寻找的答案。告诉一种方法如何实现这一目标。 (3认同)
  • 你可以做到,只需制作一个自定义旋转器并遵循 Dimitar 的答案 (2认同)