简体   繁体   English

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

[英]How can I get an event in Android Spinner when the current selected item is selected again?

I have written an setOnItemSelectedListener for spinner to respond when the spinner item is changed.我已经为微调器编写了一个 setOnItemSelectedListener 以在微调器项目更改时做出响应。 My requirement is when I clicks again the currently selected item, a toast should display.我的要求是,当我再次单击当前选定的项目时,应显示祝酒词。 How to get this event?如何获得这个事件? When the currently selected item is clicked again, spinner is not responding.再次单击当前选定的项目时,微调器没有响应。 ` `

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

        }
    });  

I spent a good few hours trying to get something to solve this problem.我花了好几个小时试图找到解决这个问题的方法。 I ended up with the following.我最终得到了以下结果。 I'm not certain if it works in all cases, but it seems to work for me.我不确定它是否适用于所有情况,但似乎对我有用。 It's just an extension of the Spinner class which checks the selection and calls the listener if the selection is set to the same value.它只是 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());
        }
    }

}

try this尝试这个

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

This spinner will always tell you that selection has changed:此微调器将始终告诉您选择已更改:

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

I figured I'd leave an updated answer for those working on newer Android versions.我想我会为那些在更新的 Android 版本上工作的人留下一个更新的答案。

I compiled together a function from the above answers that will work for at least 4.1.2 and 4.3 (the devices I tested on).我从上述答案中编译了一个函数,该函数至少适用于 4.1.2 和 4.3(我测试过的设备)。 This function doesn't use reflection, but instead tracks the last selected index itself, so should be safe to use even if the SDK changes how the classes extend each other.此函数不使用反射,而是跟踪最后选择的索引本身,因此即使 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);
    } 
}

kotlin , hope it helps 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
            )
        }
    }
}

for newer platforms try to add this to Dimitar's solution.对于较新的平台,请尝试将此添加到 Dimitar 的解决方案中。 I think it works :)我认为它有效:)

(you have to override onLayout and to remove onClick method) (您必须覆盖 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);
} 

What I found is, OnItemSelectedListener won't be called if the same item is selected again in a spinner.我发现,如果在微调器中再次选择相同的项目,则不会调用 OnItemSelectedListener。 When i click on spinner and again select the same value, then OnItemSelectedListener method is not called.当我单击微调器并再次选择相同的值时,不会调用 OnItemSelectedListener 方法。 People do not expect something to happen if they click on a selection that is already active as per the UI design.人们不希望如果他们点击一个按照 UI 设计已经处于活动状态的选择会发生什么事情。

This is not full solution but it works if you only want to call this when you're getting back to your fragment/activity from wherever.这不是完整的解决方案,但如果您只想在从任何地方返回片段/活动时调用它,它就可以工作。

Considering mSpinner is your Spinner view, we call its listener like this:考虑到mSpinner是你的 Spinner 视图,我们这样称呼它的监听器:

@Override public void onResume() {
        if (mSpinner.getCount() > 0) {
            mSpinner.getOnItemSelectedListener()
                    .onItemSelected( mSpinner, null, mSpinner.getSelectedItemPosition(), 0 );
        }
        super.onResume();
    }

Continue from this answer https://stackoverflow.com/a/17099104/7392507从这个答案继续https://stackoverflow.com/a/17099104/7392507

In your xml file, create a spinner.在您的 xml 文件中,创建一个微调器。 Replace the spinner tag <Spinner> with <yourdomain.yourprojectname.yourpackagename.spinnerclassname> for example <com.company.appname.utility.MySpinner> .将微调标签<Spinner>替换为<yourdomain.yourprojectname.yourpackagename.spinnerclassname>例如<com.company.appname.utility.MySpinner>

In your java file, define the spinner variable as below: - Spinnerclassname varName = findViewById(R.id.spinnerId);在你的java文件中,定义spinner变量如下: - Spinnerclassname varName = findViewById(R.id.spinnerId);

For example: - MySpinner varSpinner = findViewById(R.id.spinnerId);例如: - MySpinner varSpinner = findViewById(R.id.spinnerId);

@Dimitar. @迪米塔尔。 WOW, brilliant work.哇,精彩的作品。 Thanks for that.感谢那。 I can't upvote your solution (not enough points) but the NoDefaultSpinner class WORKS.我不能赞成您的解决方案(分数不够),但 NoDefaultSpinner 类有效。 Only this one thing was a problem: because you call super.onClick and then testReflectionForSelectionChanged() inside "OnClick", you will get the onItemSelected handler for the spinner being called twice if the selection DOES actually change (while functionality is correct if the same item is re-selected).只有这一件事是一个问题:因为你在“OnClick”中调用了 super.onClick 然后 testReflectionForSelectionChanged(),如果选择确实改变了,你将获得两次调用的微调器的 onItemSelected 处理程序(而功能是正确的,如果相同项被重新选择)。 I solved this by hacking around it.我通过绕过它解决了这个问题。 I added an onTouchEvent override that recorded which item was touched, then checked if this had changed in "onClick":我添加了一个 onTouchEvent 覆盖来记录哪个项目被触摸,然后检查这是否在“onClick”中发生了变化:

private Object ob=null; //class level variable
 @Override
public boolean onTouchEvent(MotionEvent m)
{
    if (m.getAction()==MotionEvent.ACTION_DOWN)
    {
        ob=this.getSelectedItem();
    }
    return super.onTouchEvent(m);
}
@Override
public void onClick(DialogInterface dialog, int which) {    
    super.onClick(dialog, which);
    if (this.getSelectedItem().equals(ob))
        testReflectionForSelectionChanged();
}

My solution is Based on MySpinner by benoffi7.我的解决方案是基于 benoffi7 的 MySpinner。 Fixes passing nulls on same item selection by saving the last selected parent and view.通过保存最后选择的父级和视图,修复了在同一项目选择上传递空值的问题。

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

The Spinner behaviour is not expected for our requeriments.我们的要求不会出现 Spinner 行为。 My solution is not work with Spinners, make it in one similar way, with one ListView inside one BaseFragment to research the functionality we are expected.我的解决方案不适用于 Spinners,以一种类似的方式实现,在一个 BaseFragment 中使用一个 ListView 来研究我们期望的功能。

The beneficts are:好处是:

  1. No more headaches extending Spinner defaults.不再为扩展 Spinner 默认设置而头疼。
  2. Easy implementation and customization.易于实施和定制。
  3. Full compatibility along all Android APIs.完全兼容所有 Android API。
  4. No face against first OnItemSelectedListener.onItemSelected call.没有面对第一个 OnItemSelectedListener.onItemSelected 调用。

The main idea, is do something like this:主要思想是做这样的事情:

The BaseFragment layout could looks similar to: BaseFragment 布局可能类似于:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:background="@null"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:gravity="center">

    <ListView
            android:id="@+id/fragment_spinnerList"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
</LinearLayout>

The code looks something like this:代码如下所示:

public class SpinnerListFragment extends android.support.v4.app.DialogFragment {

    static SpinnerListFragment newInstance(List<String> items) {

        SpinnerListFragment spinnerListFragment = new SpinnerListFragment();
        Bundle args = new Bundle();

        args.putCharSequenceArrayList("items", (ArrayList) items);
        spinnerListFragment.setArguments(args);

        return spinnerListFragment;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        Dialog dialog = new Dialog(getActivity(), R.style.dialog);
        final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_spinner_list, null);

        dialog.getWindow().setContentView(view);
        dialog.setCanceledOnTouchOutside(true);

        // CUSTOMIZATION...

        final List items = (ArrayList) getArguments().getCharSequenceArrayList("items");

        final ListView spinnerList = (ListView) view.findViewById(R.id.fragment_spinnerList);

        ArrayAdapter<String> arrayAdapter =
                new ArrayAdapter<String>(
                        getActivity(),
                        R.layout.search_spinner_list_item,
                        items);

        spinnerList.setAdapter(arrayAdapter);

        spinnerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                // DO SOMETHING...

                SpinnerListFragment.this.dismiss();
            }
        });

        return dialog;
    }

}
class MySpinner extends Spinner {


    public MySpinner(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    public MySpinner(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    @Override
    public void setSelection(int position, boolean animate) {
        ignoreOldSelectionByReflection();
        super.setSelection(position, animate);
    }

    private void ignoreOldSelectionByReflection() {
        try {
            Class<?> c = this.getClass().getSuperclass().getSuperclass().getSuperclass();
            Field reqField = c.getDeclaredField("mOldSelectedPosition");
            reqField.setAccessible(true);
            reqField.setInt(this, -1);
        } catch (Exception e) {
            Log.d("Exception Private", "ex", e);
            // TODO: handle exception
        }
    }

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

}

This has an easy solution because it is possible to set the "selected item" programmatically based on "onTouch", like this:这有一个简单的解决方案,因为可以基于“onTouch”以编程方式设置“选定项目”,如下所示:

spinnerobject.setOnTouchListener(new AdapterView.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            final int MAKE_A_SELECTION = 1; //whatever index that is the normal starting point of the spinner.
            spinnerObject.setSelection(MAKE_A_SELECTION);
            return false;
        }
    });

There is a tiny penalty in that (1) the spinner text will change back to the default just prior to the spinner rows being displayed, and (2), this default item will be part of the list.有一个微小的惩罚,因为 (1) 微调器文本将在微调器行显示之前改回默认值,以及 (2),此默认项将成为列表的一部分。 Perhaps someone can add how to disable a particular item for a spinner?也许有人可以添加如何禁用微调器的特定项目?

Generally speaking, since a spinner selection may execute a repeatable event (like starting a search), the lack of possibility to reselect an item in a spinner is really a missing feature/bug in the Spinner class, a bug that Android developers should correct ASAP.一般来说,由于 Spinner 选择可能会执行可重复的事件(例如开始搜索),因此 Spinner 中无法重新选择项目实际上是 Spinner 类中缺少的功能/错误,Android 开发人员应尽快纠正该错误.

Hi man, this worked for me:嗨,伙计,这对我有用:

ArrayAdapter<String> adaptador1 = new ArrayAdapter<String>( Ed_Central.this, 
                                                            android.R.layout.simple_spinner_item,
                                                            datos1
                                                            );
        lista1.setAdapter( adaptador1 );

        lista1.setOnItemSelectedListener( new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected( AdapterView<?> parent, View view, int position, long id ) {

                lista1.setSelection( 0 );

                switch ( position ) {
                    case 1:
                        Toast.makeText( getApplicationContext(), "msg1", Toast.LENGTH_SHORT ).show();
                        break;
                    case 2:
                        Toast.makeText( getApplicationContext(), "msg2", Toast.LENGTH_SHORT ).show();
                        break;
                    case 3:
                        Toast.makeText( getApplicationContext(), "msg3", Toast.LENGTH_SHORT ).show();
                        break;

                    default:
                        break;
                }
            }

Always the adapter is going to be at position "0", and you can show your toast.适配器始终处于位置“0”,您可以展示您的吐司。

package customclasses;

/**
 * Created by Deepak on 7/1/2015.
 */

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 boolean isDropDownMenuShown=false;

    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 boolean performClick() {
        this.isDropDownMenuShown = true; //Flag to indicate the spinner menu is shown
        return super.performClick();
    }
    public boolean isDropDownMenuShown(){
        return isDropDownMenuShown;
    }
    public void setDropDownMenuShown(boolean isDropDownMenuShown){
        this.isDropDownMenuShown=isDropDownMenuShown;
    }
    @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());
        }
    }
    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }
}

Custom spinner with same item selection callback in Kotlin : Kotlin 中具有相同项目选择回调的自定义微调器:

class StorageSpinner : 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)

    interface StorageSpinnerSelectionCallback {
        fun onItemSelected(position: Int)
    }

    private var selectionCallback: StorageSpinnerSelectionCallback? = null

    fun setSelectionCallback(selectionCallback: StorageSpinnerSelectionCallback) {
        this.selectionCallback = selectionCallback
    }

    fun removeSelectionCallback() {
        selectionCallback = null
    }

    override fun setSelection(position: Int) {
        super.setSelection(position)

        if (position == selectedItemPosition) selectionCallback?.onItemSelected(position)
    }
}

Try this, this might be not the proper solution but is the best working solution available right now, if not making a custom spinner.试试这个,如果不制作自定义微调器,这可能不是正确的解决方案,但它是目前可用的最佳工作解决方案。

what you have to do is to reset spinner adapter on every item click,你需要做的是在每次点击项目时重置微调适配器,

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

    if (position == getSelectedItemPosition())
    {
        //do your thing
        //then at end of statement reset adapter like

       spinner.setAdapter(adapter);
    } 

    }

I hope it helped you solve your problem我希望它能帮助你解决你的问题

Hello & thanks @Dimitar for a creative answer to the problem.您好,感谢@Dimitar 对问题的创造性回答。 I've tried it and it works well on older Android versions like 2.x, but unfortunately it doesn't work on version 3.0 and later (tried 3.2 and 4.0.3).我已经试过了,它在 2.x 等较旧的 Android 版本上运行良好,但不幸的是它不适用于 3.0 及更高版本(尝试过 3.2 和 4.0.3)。 For some reason the onClick method is never called on newer platforms.出于某种原因,在较新的平台上永远不会调用 onClick 方法。 Someone has written a bug report for this here: http://code.google.com/p/android/issues/detail?id=16245有人为此写了一个错误报告: http : //code.google.com/p/android/issues/detail?id=16245

Not functioning on newer platforms means I needed a different solution.无法在较新的平台上运行意味着我需要不同的解决方案。 In my application it was sufficient to simulate an unselected spinner with a hidden "dummy" entry at the start.在我的应用程序中,在开始时模拟一个带有隐藏“虚拟”条目的未选择微调器就足够了。 Then every item clicked will result in a callback if the "hidden" item is set as the selection.如果“隐藏”项目被设置为选择,那么点击的每个项目都将导致回调。 A drawback for some may be that nothing will appear selected, but that could be fixed using Spinner class override tricks.对于某些人来说,一个缺点可能是什么都不会出现,但可以使用 Spinner 类覆盖技巧来修复。

See How to hide one item in an Android Spinner请参阅如何在 Android Spinner 中隐藏一项

if u really want to do this task in your XML when your spinner display add one edit text and set visibility gone attribute;如果您真的想在您的微调器显示添加一个编辑文本并设置可见性消失属性时在您的 XML 中执行此任务; and create costume adapter for spinner and in costume adapter set on view.onclicklisner and when clickevent fired EditText.setText("0");并为微调器和在 view.onclicklisner 上设置的服装适配器创建服装适配器,当点击事件触发 EditText.setText("0"); and in activity set edittext textWatcher Event and in event block you add your onSppinerItem Event Block code;在活动集 edittext textWatcher 事件和事件块中,您添加 onSpinerItem 事件块代码; Your Problem Solved你的问题解决了

您必须执行以下步骤: 1. 为微调器创建一个 Adapter Customer 2. 在覆盖 fun getDropDownView(...) 中,您必须放置一个 view.setOnClickListener {"interface"} 3. 创建一个接口

There is no need to extend the spinner.无需扩展微调器。 I use a SpinnerAdapter in the following manner:我按以下方式使用 SpinnerAdapter:

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle  savedInstanceState) {
    //....
    //Create an ArrayAdapter as usual
    myArrayAdapter = new ArrayAdapter(mParentView.getContext(),R.layout.myarrayadapter_item);
    //Create a Spinner as usual
    mySpinner = (Spinner)mParentView.findViewById(R.id.myspinner);

    //create a spinneradapter
    //selecting the same item twice will not throw an onselectionchange event
    //therefore add an OnTouchlistener to the DropDownView items
    SpinnerAdapter o_SpinnerAdapter = new SpinnerAdapter() {
            private ArrayAdapter m_ArrayAdapter = myArrayAdapter;
            private View.OnTouchListener m_OnTouchListener = new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                    //do something
                   return false; //return false, don't consume the event
            };
            @Override
            public View getDropDownView(int position, View convertView, ViewGroup parent) {
                    TextView o_TextView; //usual the view is a TextView
                    o_TextView = (TextView)m_ArrayAdapter.getView(position,convertView,parent);
                    o_TextView.setOnTouchListener(m_OnTouchListener); //Add the ontouchlistener
                    return o_TextView;
            }

            @Override
            public void registerDataSetObserver(DataSetObserver observer) {
                    m_ArrayAdapter.registerDataSetObserver(observer);
            }
            @Override
            public void unregisterDataSetObserver(DataSetObserver observer) {
                    m_ArrayAdapter.unregisterDataSetObserver(observer);
            }
            @Override
            public int getCount() {
                    return m_ArrayAdapter.getCount();
            }
            @Override
            public Object getItem(int position) {
                    return m_ArrayAdapter.getItem(position);
            }
            @Override
            public long getItemId(int position) {
                    return m_ArrayAdapter.getItemId(position);
            }
            @Override
            public boolean hasStableIds() {
                    return m_ArrayAdapter.hasStableIds();
            }
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                    return m_ArrayAdapter.getView(position, convertView, parent);
            }
            @Override
            public int getItemViewType(int position) {
                    return m_ArrayAdapter.getItemViewType(position);
            }
            @Override
            public int getViewTypeCount() {
                    return m_ArrayAdapter.getViewTypeCount();
            }
            @Override
            public boolean isEmpty() {
                    return m_ArrayAdapter.isEmpty();
            }
    };
    //Set the SpinnerAdapter instead of myArrayAdapter
    m_SpinnerDMXDeviceGroups.setAdapter(o_SpinnerAdapter);

    //.......
    }

Hope it helps希望能帮助到你

This threat was very helpful for me.这个威胁对我很有帮助。 There are two remarks which might help someone:有两句话可能会对某人有所帮助:

First:第一的:

You should check if the OnItemSelecListener is already set.您应该检查 OnItemSelecListener 是否已经设置。 In my case I called setSelection() before I set the OnItemSelecListener, which lead to a crash.在我的例子中,我在设置 OnItemSelecListener 之前调用了 setSelection(),这导致了崩溃。

@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
        AdapterView.OnItemSelectedListener selLis = getOnItemSelectedListener();
        if (selLis != null) {
            selLis.onItemSelected(this, getSelectedView(), position, getSelectedItemId());
        }
    }
}

Second:第二:

Android Studio asks me not to derive from Spinner but from AppCompatSpinner. Android Studio 要求我不要派生自 Spinner,而是派生自 AppCompatSpinner。 This looks like this:这看起来像这样:

import androidx.appcompat.widget.AppCompatSpinner;

public class SpinnerReclickable  extends AppCompatSpinner {
...

Just try out with this.试试这个。

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

Hope it may work.希望它可以工作。

When you clicks again the currently selected item, then it can not fire any event.当您再次单击当前选定的项目时,它不会触发任何事件。 So you can not catch setOnItemSelectedListener for spinner to respond.因此,您无法捕获 setOnItemSelectedListener 以供微调器响应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM