Android 微调器关闭

发布于 2024-12-02 20:07:10 字数 1079 浏览 1 评论 0原文

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

整个故事是,在后台我正在一个单独的线程上运行一个进程。该流程完成后,我在主活动上调用处理程序,并根据结果执行一些任务。然后我想关闭微调器,如果用户打开了它。

微调器位于 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);
    }
}

干杯!

I have an activity with a spinner, and I was wondering if it is possible to close the spinner programmatically, if the user has opened it.

The whole story is that in the background I am running a process on a separate thread. When the process has finished, I invoke a Handler on the main activity and, depending on the outcome, I perform some tasks. It is then that I want to close the spinner, it the user has opened it.

The spinner is in the main.xml layout:

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

and this is the Handler:

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

Cheers!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

浅笑依然 2024-12-09 20:07:10
  public static void hideSpinnerDropDown(Spinner spinner) {
    try {
        Method method = Spinner.class.getDeclaredMethod("onDetachedFromWindow");
        method.setAccessible(true);
        method.invoke(spinner);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  public static void hideSpinnerDropDown(Spinner spinner) {
    try {
        Method method = Spinner.class.getDeclaredMethod("onDetachedFromWindow");
        method.setAccessible(true);
        method.invoke(spinner);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
抱着落日 2024-12-09 20:07:10

这对我有用:

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

This works for me:

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

and the click listener:

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));
    }
}
开始看清了 2024-12-09 20:07:10

嗯,它比我想象的有点复杂。

我在这里添加逐步详细信息。尝试遵循它。我能够在 api 级别 10 中实现这一目标。

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

第一步是通过扩展 Spinner 类来创建自定义 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 或当 Activity 移动到后台时关闭对话框。为此,我们像这样重写 onPause(),

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

现在在 onPause() 中调用方法 spin.onDetachedFromWindow(); ,该方法会为您关闭提示对话框。

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

Well its a little complicated than I thought.

I am adding the step by step details here. Try to follow it. I was able to achieve this in api level 10.

And this solution assumes that you are supposed to close the prompt dialog programatically when the user clicks on Home Button or If you had to move to next activity without user interaction

The first step is to create a Custom Spinner by extending Spinner Class.
Let's say, I have created a class called CustomSpinner in the package com.bts.sampleapp

My CustomSpinner class looks like this,

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

Now in your Xml file, replace Spinner element by this custom spinner,

        <com.bts.sampleapp.CustomSpinner
        android:id="@+id/spin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

The next step is to initialize and set adapter to this spinner in your Activity class,

    @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.
}

The final step is to close the dialog when the user clicks on HomeButton or When the Activity moves to background. To do this, we override the onPause() like this,

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

Now within the onPause() call the method spin.onDetachedFromWindow(); which does the job of closing the prompt dialog for you.

Now that being said, calling spin.onDetachedFromWindow(); from anywhere in your Activity should help you to close the spinner programatically. So if this is what you want, then remove the onpause().

时光清浅 2024-12-09 20:07:10

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

唯一的解决方法是克隆 Spinner 的源代码并自行添加一些代码以关闭该对话框。但是,同样,它无法在 Honeycomb 或更高版本上运行,除非您也可以看到并克隆代码。

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

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

I don't see a way to accomplish that -- there is no method on Spinner to close it. The "open" part of a Spinner is an AlertDialog on Android 1.x and 2.x, and I'm not completely sure how it is implemented on Honeycomb when using the holographic theme.

The only workaround would be to clone the source for Spinner and add in some code yourself to dismiss the dialog. But, again, it would not work on Honeycomb or higher until you can see and clone that code as well.

Beyond that, I would think that what you want is poor UX. If the user opened the Spinner, they are most likely actively examining the Spinner's contents and making a selection. Yanking that out from under their finger will confuse them, at best. Please consider an alternative approach.

Also, don't use getApplicationContext() unless you know why you are using getApplicationContext(). You do not need or even want getApplicationContext() when creating an ArrayAdapter.

情话墙 2024-12-09 20:07:10

我认为你应该放弃使用 Spinner ,而是使用 ImageView帧动画(即)来创建您自己的微调器。您只需将 ImageView 的背景设置为您的帧动画可绘制对象。

然后您可以轻松地执行这样的操作来开始并停止它。

I think you should scrap your use of Spinner and instead use an ImageView with a Frame Animation (i.e. <animation-list>) to create your own spinner. You just set the ImageView's background to be your Frame Animation drawable.

Then you can easily do something like this to start and stop it.

倦话 2024-12-09 20:07:10

您想从任何地方关闭旋转器。 BACK 按下的按键注入是一个很好的解决方案,但是,在这里您将立即关闭所有视图。

setPressed(false) 怎么样?
关联:
同时单击组视图中的所有旋转器中的两个时关闭旋转器下拉列表

否则:
尝试使 Spinner focusablefocusableInTouchMode 并使用 clearFocus()
在它上面。尝试使用 requestFocus() 方法将焦点集中在其下方的视图上。

检查微调器下拉菜单是否关闭

You would like to close your spinners from anywhere. Key injection for BACK pressed is the good solution but, here you are closing all the views at once.

How about setPressed(false)?
Link:
Close Spinners dropdown when two among all in a groupview are clicked simultaneously

Otherwise:
Try to make the Spinner focusable and focusableInTouchMode, and use clearFocus()
on it. Try to focus on the view below it using requestFocus() method.

Check if the spinner drop-down closes

青瓷清茶倾城歌 2024-12-09 20:07:10

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

spinner.clearFocus();

Use the clearFocus() to close the spinner programitically

spinner.clearFocus();
酒与心事 2024-12-09 20:07:10

在代码中添加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" />

Add clearfocus() in code.

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

Use transparent background in 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" />
一花一树开 2024-12-09 20:07:10

科尔廷反射

fun AppCompatSpinner.dismiss() {
    val popup = AppCompatSpinner::class.java.getDeclaredField("mPopup")
    popup.isAccessible = true
    val listPopupWindow = popup.get(this) as ListPopupWindow
    listPopupWindow.dismiss()
}

Koltin Reflection

fun AppCompatSpinner.dismiss() {
    val popup = AppCompatSpinner::class.java.getDeclaredField("mPopup")
    popup.isAccessible = true
    val listPopupWindow = popup.get(this) as ListPopupWindow
    listPopupWindow.dismiss()
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文