Android微调器关闭

时间:2011-09-02 17:34:41

标签: android view spinner handler

我有一个带有微调器的活动,我想知道是否可以以编程方式关闭微调器,如果用户已经打开它。

整个故事是在后台我在一个单独的线程上运行一个进程。当进程完成时,我在主要活动上调用一个Handler,并根据结果执行一些任务。然后,我想关闭微调器,用户已打开它。

微调器位于main.xml布局中:

<Spinner android:id="@+id/birthPlaceSpinner" android:layout_weight="1" 
android:layout_height="wrap_content" android:prompt="@string/select"
android:layout_width="fill_parent" />

这是处理程序:

private class BirthplaceChangedHandler extends Handler {

    @Override
    public void handleMessage(Message msg) {
        String placeFilterStr = birthPlaceFilterText.getText().toString();
        if ("".equals(placeFilterStr) || placeFilterStr == null || validNewAddresses.isEmpty()) {
            birthPlaceSpinner.setEnabled(false);
            hideGeoLocationInformation();
        } else {
            birthPlaceSpinner.setEnabled(true);
        }
        adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.multiline_spinner_dropdown_item, validNewAddressesStr)
        birthPlaceSpinner.setAdapter(adapter);
    }
}

干杯!

9 个答案:

答案 0 :(得分:16)

这对我有用:

class SomeAdapter extends BaseAdapter implements SpinnerAdapter {
    //......   
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            //......
        }
        view.setOnClickListener(new ItemOnClickListener(parent));
        return view;
    }
    //.....
}

和点击监听器:

class ItemOnClickListener implements View.OnClickListener {
    private View _parent;

    public ItemOnClickListener(ViewGroup parent) {
        _parent = parent;
    }

    @Override
    public void onClick(View view) {
        //.......
        // close the dropdown
        View root = _parent.getRootView();
        root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
        root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
    }
}

答案 1 :(得分:8)

我没有办法实现这一点 - Spinner上没有方法可以关闭它。 Spinner的“开放”部分是Android 1.x和2.x上的AlertDialog,我不完全确定在使用全息主题时它是如何在Honeycomb上实现的。

唯一的解决方法是克隆Spinner的源代码并自行添加一些代码来关闭对话框。但是,再次,它将无法在Honeycomb或更高版本上工作,直到您可以看到并克隆那个代码。

除此之外,我认为你想要的是糟糕的用户体验。如果用户打开Spinner,他们很可能会主动检查Spinner的内容并进行选择。从他们的手指下面说出来,最多会让他们感到困惑。请考虑另一种方法。

另外,请不要使用getApplicationContext(),除非您知道为什么您正在使用getApplicationContext()。创建getApplicationContext()时,您不需要甚至不想ArrayAdapter

答案 2 :(得分:8)

这比我想象的要复杂一点。

我在这里添加了一步一步的细节。尝试遵循它。我能够在api 10级实现这一目标。

此解决方案假定您应该在用户单击主页按钮时以编程方式关闭提示对话框,或者如果您必须在没有用户交互的情况下转到下一个活动

第一步是通过扩展Sp​​inner Class来创建Custom Spinner。 比方说,我在包 com.bts.sampleapp

中创建了一个名为 CustomSpinner 的类

我的CustomSpinner类看起来像这样,

package com.bts.sampleapp;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Spinner;

    public class CustomSpinner extends Spinner{
        Context context=null;

        public CustomSpinner(Context context) {
            super(context);
            this.context=context;
        }

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

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

        @Override
        public void onDetachedFromWindow() {
            super.onDetachedFromWindow();
        }
    }

现在在您的Xml文件中,用此自定义微调器

替换Spinner元素
        <com.bts.sampleapp.CustomSpinner
        android:id="@+id/spin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

下一步是在Activity类

中初始化并设置适配器到此微调器
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    CustomSpinner spin=null;
    spin=(CustomSpinner)findViewById(R.id.spin);
    spin.setAdapter(spinnerAdapter); //you can set your adapter here.
}

最后一步是在用户单击HomeButton或活动移至后台时关闭对话框。为此,我们覆盖onPause(),如下所示,

@Override
    protected void onPause() {
        Log.i("Life Cycle", "onPause");
        spin.onDetachedFromWindow();
        super.onPause();
    }

现在在onPause()中调用方法spin.onDetachedFromWindow();,它为您完成关闭提示对话框的工作。

现在说,从您的Activity中的任何位置调用spin.onDetachedFromWindow();应该可以帮助您以编程方式关闭微调器。因此,如果这是您想要的,请删除onpause()

答案 3 :(得分:8)

  public static void hideSpinnerDropDown(Spinner spinner) {
    try {
        Method method = Spinner.class.getDeclaredMethod("onDetachedFromWindow");
        method.setAccessible(true);
        method.invoke(spinner);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

答案 4 :(得分:3)

我认为你应该放弃使用Spinner,而是使用ImageViewFrame Animation(即<animation-list>)创建自己的微调器。您只需将ImageView的背景设置为您的Frame Animation drawable。

然后你可以轻松地做一些事情like this来启动和停止它。

答案 5 :(得分:1)

如何克隆“后退”按键?

好的,我刚试过

[current activity].dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_BACK));

并且它没有做任何我能看到的事情 - 然后按下物理后退键并且下拉消失了。也尝试在向下之后立即执行ACTION_UP - 也没有效果。

答案 6 :(得分:1)

您想从任何地方关闭您的纺纱厂。 BACK按下的键注入是一个很好的解决方案,但是,您现在可以立即关闭所有视图。

setPressed(false)怎么样?
链接: Close Spinners dropdown when two among all in a groupview are clicked simultaneously

否则: 尝试制作微调器focusablefocusableInTouchMode,然后使用clearFocus() 在上面。尝试使用requestFocus()方法关注其下方的视图。

检查微调器下拉是否关闭

答案 7 :(得分:0)

在代码中添加clearfocus()。

Spinner spinner = (Spinner) findViewById(R.id.spinner);
spinner.clearFocus();

在xml中使用透明背景

android:background="@android:color/transparent

<Spinner 
    android:id="@+id/spinner"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:clickable="false"
    android:focusable="?android:attr/windowOverscan"
    android:focusableInTouchMode="false"
    android:pointerIcon="arrow"
    android:spinnerMode="dialog"
    android:theme="@style/ThemeOverlay.AppCompat.Light" />

答案 8 :(得分:-1)

使用clearFocus()以程序方式关闭微调器

spinner.clearFocus();