首页 文章

在Android中设置微调器onClickListener()

提问于
浏览
31

我试图让一个onClickListener在Spinner上触发,但是我收到以下错误:

Java.lang.RuntimeException是“不要为AdapterView调用setOnClickListener . 你可能需要setOnItemClickListener,”

我确定我想调用onClickListener而不是onItemClickListener . 我在Stack Overflow上找到了其他人提出的问题,Is there a way to use setOnClickListener with an Android Spinner?

答案是:

您必须在微调器的基础视图(通常是带有id:android.R.id.text1的TextView)上设置Click侦听器 . 为此:创建自定义Spinner在构造函数中(使用属性)通过提供布局android.R.layout.simple_spinner_item来创建微调器 . 执行findViewById(android.R.id.text1)以获取TextView现在将onClickListener设置为TextView

我已经尝试过那里提到的答案,但它似乎没有用 . 在执行findViewById()后,我得到一个指向TextView的空指针 .

这就是我正在做的事情:

Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.layoutspinner,dataArray);

spinner.setAdapter(adapter);

TextView SpinnerText = (TextView)findViewById(R.id.spinnerText);
if (SpinnerText == null) {
    System.out.println("Not found");
}
else {
    SpinnerText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {
            //Do something
        }
    });
}

文件layoutspinner.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
                  android:id="@+id/spinnerText"
                  android:singleLine ="true"
                  android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  android:textSize="6pt"
                  android:gravity="right"/>

我究竟做错了什么?

我是Stack Overflow的新手,我没有找到任何方法将一个附加问题发布到另一个帖子(或评论,因为我需要很少代表)所以我开始了一个新问题 .

每个推荐我试过这个:

int a = spinnerMes.getCount();
int b = spinnerMes.getChildCount();
System.out.println("Count = " + a);
System.out.println("ChildCount = " + b);
for (int i = 0; i < b; i++) {
    View v = spinnerMes.getChildAt(i);
    if (v == null) {
        System.out.println("View not found");
    }
    else {
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Click code
            }
        });
    }
}

但是LogCat没有显示出有希望的结果 .

10-14 16:09:08.127: INFO/System.out(3116): Count = 7
10-14 16:09:08.127: INFO/System.out(3116): ChildCount = 0

我已经在API级别7和8上对此进行了测试,结果相同 .

7 回答

  • 2

    这是一个有效的解决方案:

    我们设置OnTouchListener和OnKeyListener,而不是设置微调器的OnClickListener .

    spinner.setOnTouchListener(Spinner_OnTouch);
    spinner.setOnKeyListener(Spinner_OnKey);
    

    和听众:

    private View.OnTouchListener Spinner_OnTouch = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                doWhatYouWantHere();
            }
            return true;
        }
    };
    private static View.OnKeyListener Spinner_OnKey = new View.OnKeyListener() {
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
                doWhatYouWantHere();
                return true;
            } else {
                return false;
            }
        }
    };
    
  • 0

    首先,微调器不支持项目点击事件 . 调用此方法将引发异常 .

    您可以使用setOnItemSelectedListener:

    Spinner s1;
    s1 = (Spinner)findViewById(R.id.s1);
    int selectionCurrent = s1.getSelectedItemPosition();
    
    spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                if (selectionCurrent != position){
                    // Your code here
                }
                selectionCurrent= position;
            }
        }
    
        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
            // Your code here
        }
    });
    
  • 11

    每当您必须在Android中单击Spinner时执行某些操作,请使用以下方法 .

    mspUserState.setOnTouchListener(new OnTouchListener() {
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                doWhatIsRequired();
            }
            return false;
        }
    });
    

    One thing to keep in mind is always to return False while using the above method. If you will return True then the dropdown items of the spinner will not be displayed on clicking the Spinner.

  • 54

    Spinner类实现了 DialogInterface.OnClickListener ,从而有效地劫持了标准 View.OnClickListener .

    如果您没有使用子类Spinner或不打算使用,请选择其他答案 .

    否则,只需将以下代码添加到自定义Spinner:

    @Override
    /** Override triggered on 'tap' of closed Spinner */
    public boolean performClick() {
        // [ Do anything you like here ]
        return super.performClick();
    }
    

    示例:每当打开微调器时,通过Snackbar显示预先提供的提示:

    private String sbMsg=null;      // Message seen by user when Spinner is opened.
    public void setSnackbarMessage(String msg) { sbMsg=msg; }
    @Override
    /** Override triggered on 'tap' of closed Spinner */
    public boolean performClick() {
        if (sbMsg!=null && !sbMsg.isEmpty()) { /* issue Snackbar */ }
        return super.performClick();
    }
    

    Trapping 'click' of closed Spinner

    自定义Spinner是在整个项目中以编程方式标准化Spinner外观的绝佳起点 .

    如果有兴趣,请看here

  • 4

    我建议Spinner的所有事件都分为两种类型:

    • 用户事件(您的意思是“点击”事件) .

    • 计划活动 .

    我还建议,当你想要捕获用户事件时,你只想摆脱“程序事件” . 所以这很简单:

    private void setSelectionWithoutDispatch(Spinner spinner, int position) {
        AdapterView.OnItemSelectedListener onItemSelectedListener = spinner.getOnItemSelectedListener();
        spinner.setOnItemSelectedListener(null);
        spinner.setSelection(position, false);
        spinner.setOnItemSelectedListener(onItemSelectedListener);
    }
    

    关键时刻:你需要setSelection(position,false) . 动画参数中的“false”会立即触发事件 . 默认行为是将事件推送到事件队列 .

  • 24

    就个人而言,我用它:

    final Spinner spinner = (Spinner) (view.findViewById(R.id.userList));
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {                
    
                userSelectedIndex = position;
            }
    
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    
  • 5

    以下是你想要的方式,但它并不理想 .

    public class Tester extends Activity {
    
        String[] vals = { "here", "are", "some", "values" };
        Spinner spinner;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            spinner = (Spinner) findViewById(R.id.spin);
            ArrayAdapter<String> ad = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, vals);
            spinner.setAdapter(ad);
            Log.i("", "" + spinner.getChildCount());
            Timer t = new Timer();
            t.schedule(new TimerTask() {
    
                @Override
                public void run() {
                    int a = spinner.getCount();
                    int b = spinner.getChildCount();
                    System.out.println("Count =" + a);
                    System.out.println("ChildCount =" + b);
                    for (int i = 0; i < b; i++) {
                        View v = spinner.getChildAt(i);
                        if (v == null) {
                            System.out.println("View not found");
                        } else {
                            v.setOnClickListener(new View.OnClickListener() {
    
                                @Override
                                public void onClick(View v) {
                                            Log.i("","click");
                                            }
                            });
                        }
                    }
                }
            }, 500);
        }
    }
    

    让我确切地知道您需要微调器的行为,我们可以找到更好的解决方案 .

相关问题