why was the onNothingSelected in spinner not invok

2019-04-09 20:06发布

I have an Android Spinner and I want to listen the event when the user press "Back Key" when the spinner's select panel is showing.I have implement the OnItemSelectedListener ,but the onNothingSelected(AdapterView arg0) was not invoked when press back key.

I just want to listen the event when user select nothing( or the select panel disappear) .

Is there a correct way to do this?

Thanks!


 Spinner s1 = (Spinner) findViewById(R.id.spinner1);
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
            this, R.array.colors, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    s1.setAdapter(adapter);
    s1.setOnItemSelectedListener(
            new OnItemSelectedListener() {
                public void onItemSelected(
                        AdapterView<?> parent, View view, int position, long id) {
                    showToast("Spinner1: position=" + position + " id=" + id);
                }

                public void onNothingSelected(AdapterView<?> parent) {
                    showToast("Spinner1: unselected");
                }
            });

This is a sample in Android 2.2 SDK,it's also not show "Spinner1: unselected" when the select panel disappear.

2条回答
啃猪蹄的小仙女
2楼-- · 2019-04-09 20:44

Another approach is to create a minimal custom spinner dropdown item, ie:

<com.mypackage.MyTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    style="?android:attr/spinnerDropDownItemStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"

    android:textSize="25dp"
 />

and then intercept onDetachedFromWindow():

public class MyTextView extends TextView {

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

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

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

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        // Callback here
    }
}

You can finesse this if you use a custom ArrayAdapter to set only one of the dropdown items to do the callback, as well as setting suitable context for the callback, etc.

Depending on what you do inside the callback, you may want to post it as a runnable, so that the spinner is fully cleaned up before it does anything.

查看更多
放荡不羁爱自由
3楼-- · 2019-04-09 20:53

It looks like you won't be able to do what you want without extending the Spinner class. It seems that Spinner doesn't register an OnCancelListener with the AlertDialog it builds to display the items.

Code from Spinner.java:

  @Override
    public boolean performClick() {
        boolean handled = super.performClick();

        if (!handled) {
            handled = true;
            Context context = getContext();

            final DropDownAdapter adapter = new DropDownAdapter(getAdapter());

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            if (mPrompt != null) {
                builder.setTitle(mPrompt);
            }
            mPopup = builder.setSingleChoiceItems(adapter, getSelectedItemPosition(), this).show();
        }

        return handled;
    }

    public void onClick(DialogInterface dialog, int which) {
        setSelection(which);
        dialog.dismiss();
        mPopup = null;
    }

Also, setSelection is only called when an item in the dialog is clicked. This won't be called when the user presses the back button since that is an OnCancel event.

Extending Spinner will be a bit of a pain since you have to copy everything back to AdapterView into your source from the android source since various member fields necessary for implementation are only exposed at the package level.

查看更多
登录 后发表回答