在Android上,有没有办法禁用Spinner的长按行为?

时间:2015-01-13 13:25:45

标签: android spinner long-press

默认的微调器行为是当它“关闭”时,长按它将“打开”它并显示下拉视图。我发现这种行为对用户来说可能是非常有问题的。例如,如果他们试图在屏幕上滚动某些内容,并碰巧“抓住”一个有微调器的地点,那么它会在一秒左右打开下拉视图而不是滚动,并且用户是基本上用手指放在其中一个下拉选项上(他们现在可能会意外按下)。

所以,我想禁用那个长按行为,并且只在点击它时让微调器“打开”,而不是长按。这可能吗?

4 个答案:

答案 0 :(得分:5)

如果您只需要恢复标准点击行为,这是Jordi's answer的更简单,更紧凑的版本:

{{1}}

进一步的想法

这种行为也让我烦恼。经过调查,它似乎有一个名称:拖动打开。您可以在AppCompatSpinner#onTouchEvent()方法的来源中查看它是如何定义的。

我看到这种强制行为的一些问题(以及某些人想要禁用它的原因):

  1. 它允许用户在微调器中选择禁用的值。通过长按,拖动和释放,您可以选择通过正常交互甚至无法选择的值(点击打开+点击选择)
  2. 作为#1的结果,它也可以很容易地使Espresso测试失败。事实上,在Espresso中,点击的持续时间相当不稳定,一次点击可以很快变成长按和选择互动。
  3. 最后,这里最大的问题是没有方法/ XML属性来禁用"拖动打开"行为...
  4. 让我们解决它!

    我在AOSP问题跟踪器上打开了与此相关的故障单:#228953。如果我错过任何内容,请随意关注,或发表评论。

答案 1 :(得分:3)

所以,我已经想出了一个相对简单的方法,即使它不是很优雅。基本上,我在Spinner的顶部创建了一个透明的叠加视图,并将其设置为一个OnClickListener,它只是触发Spinner的点击。

<强> XML:

    <Spinner 
        android:id="@+id/spinner"
        android:layout_width="match_parent" 
        android:layout_height="40dip" />

    <View android:id="@+id/spinner_overlay"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:layout_alignLeft="@id/spinner" 
        android:layout_alignRight="@id/spinner"
        android:layout_alignTop="@id/spinner" 
        android:layout_alignBottom="@id/spinner"  />

<强>爪哇:

        View spinnerOverlay = findViewById(R.id.spinner_overlay);
        spinnerOverlay.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                spinner.performClick();
            }

        });

答案 2 :(得分:0)

你试过android:longClickable =&#34; false&#34;在xml中呢?

或尝试这样的事情:

spinner.setOnTouchListener(new View.OnTouchListener() {
        private static final int MAX_CLICK_DISTANCE = 15;
        private static final int MAX_CLICK_DURATION = 1000;
        private long pressStartTime;
        private float pressedX;
        private float pressedY;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    pressStartTime = System.currentTimeMillis();
                    pressedX = event.getX();
                    pressedY = event.getY();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                long pressDuration = System.currentTimeMillis() - pressStartTime;
                if (pressDuration < MAX_CLICK_DURATION && distance(pressedX, pressedY, event.getX(), event.getY()) < MAX_CLICK_DISTANCE) {
                     //when long clicked.
                }
                break;
            }
        }
        return false;
}

答案 3 :(得分:0)

有点晚了,但对某人可能仍然有用:

设置在OnLongClickListener中返回true的{​​{1}}会阻止({无意)打开onLongClick,因为它就像回调消耗了长按一样在documentation

Spinner

唯一的缺点是,旋转器在长按时仍然会有onTouch动画。