如何制作一个带有初始文本“选择一个”的Android Spinner?

9 浏览
0 Comments

如何制作一个带有初始文本“选择一个”的Android Spinner?

我想使用一个Spinner,初始时(当用户还没有进行选择时)显示文本“选择一个”。当用户点击Spinner时,会显示项目列表,用户选择其中一个选项。用户选择了一个选项后,选中的项目将显示在Spinner中,而不是“选择一个”。\n我有以下代码来创建一个Spinner:\n

String[] items = new String[] {"One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter adapter = new ArrayAdapter(this,
            android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

\n使用这段代码,最初显示的是“One”项。我可以将一个新项“选择一个”添加到项目中,但是“选择一个”也会作为第一项显示在下拉列表中,这不是我想要的。\n我该如何解决这个问题?

0
0 Comments

如何创建一个带有初始文本"Select One"的Android Spinner?

问题出现的原因:

我尝试使用Spinner来实现这个功能,但是发现Spinner的样式和行为都不太容易自定义。于是我决定使用一个Button来代替Spinner,并通过自定义Button的行为来达到相同的效果。

解决方法:

首先,像通常一样创建一个Adapter:

String[] items = new String[] {"One", "Two", "Three"};

ArrayAdapter adapter = new ArrayAdapter(this,

android.R.layout.simple_spinner_dropdown_item, items);

注意,我在这里使用了simple_spinner_dropdown_item作为布局id。这将在创建警告对话框时帮助创建更好的外观。

在我的Button的onClick处理程序中,我有以下代码:

public void onClick(View w) {

new AlertDialog.Builder(this)

.setTitle("the prompt")

.setAdapter(adapter, new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which) {

// 用户自定义操作

dialog.dismiss();

}

}).create().show();

}

就是这样!

我同意上面的回答。此外,与Spinner相比,按钮更容易进行样式定制。

我已经按照您建议的方法进行了实现,但是之前选择的项没有被高亮显示(意思是单选按钮应该被中间的绿点高亮显示)。在onClick()方法中,如何实现这一点呢?请帮助我,谢谢。

这个Button的布局是完美的:

android:id="@+id/city"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="5dp"

android:gravity="left"

android:background=":drawable/btn_dropdown"

android:text="/city_prompt" />

那么,如何更新按钮的文本以反映选择的项目,就像在Spinner中一样呢?

您可以在对话框的onClick中使用myButton.setText("prompt")来设置按钮的文本。

问题:列表行有"value + 单选按钮",但您无法指定哪一行是“选中”的。

问题解决方法:只需将SetAdapter更改为SetSingleChoiceItems即可。

0
0 Comments

如何在Android Spinner中添加初始文本“Select One”?

问题的出现原因:

- Spinner默认会自动选择列表中的第一个条目,而不是显示“Select One”这个提示文本。

解决方法:

- 创建一个自定义的Spinner类,命名为NoDefaultSpinner。

- 重写setAdapter()方法,在方法内部设置初始位置为-1,并使用代理模式显示提示文本。

- 使用反射调用私有方法setNextSelectedPositionInt()和setSelectedPositionInt()来设置初始位置为-1。

- 创建一个SpinnerAdapterProxy类,拦截getView()方法,在位置小于0时显示提示文本。

- 使用NoDefaultSpinner类替代原始的Spinner类,并在布局文件中添加android:prompt属性来显示提示文本。

以下是完整的解决方案代码:

/**
 * A modified Spinner that doesn't automatically select the first entry in the list.
 *
 * Shows the prompt if nothing is selected.
 *
 * Limitations: does not display prompt if the entry list is empty.
 */
public class NoDefaultSpinner extends Spinner {
    public NoDefaultSpinner(Context context) {
        super(context);
    }
    public NoDefaultSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    public void setAdapter(SpinnerAdapter orig ) {
        final SpinnerAdapter adapter = newProxy(orig);
        super.setAdapter(adapter);
        try {
            final Method m = AdapterView.class.getDeclaredMethod("setNextSelectedPositionInt", int.class);
            m.setAccessible(true);
            m.invoke(this, -1);
            final Method n = AdapterView.class.getDeclaredMethod("setSelectedPositionInt", int.class);
            n.setAccessible(true);
            n.invoke(this, -1);
        } 
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    protected SpinnerAdapter newProxy(SpinnerAdapter obj) {
        return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance(
                obj.getClass().getClassLoader(),
                new Class[] { SpinnerAdapter.class },
                new SpinnerAdapterProxy(obj));
    }
    protected class SpinnerAdapterProxy implements InvocationHandler {
        protected SpinnerAdapter obj;
        protected Method getView;
        protected SpinnerAdapterProxy(SpinnerAdapter obj) {
            this.obj = obj;
            try {
                this.getView = SpinnerAdapter.class.getMethod("getView", int.class, View.class, ViewGroup.class);
            } 
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
            try {
                return m.equals(getView) && (Integer)(args[0]) < 0 ? 
                        getView((Integer)args[0], (View)args[1], (ViewGroup)args[2]) : 
                        m.invoke(obj, args);
            } 
            catch (InvocationTargetException e) {
                throw e.getTargetException();
            } 
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        protected View getView(int position, View convertView, ViewGroup parent) throws IllegalAccessException {
            if (position < 0) {
                final TextView v = (TextView) ((LayoutInflater)getContext().getSystemService(
                        Context.LAYOUT_INFLATER_SERVICE)).inflate(
                                android.R.layout.simple_spinner_item, parent, false);
                v.setText(getPrompt());
                return v;
            }
            return obj.getView(position, convertView, parent);
        }
    }
}

以上是一个解决Android Spinner初始文本问题的通用解决方案。通过重写Spinner类的setAdapter()方法,设置初始位置为-1,并使用代理模式显示提示文本。这个解决方案已经在Android 1.5到4.2上进行了测试,但是由于使用了反射调用私有方法,不能保证在未来的OS更新中能够正常工作。这个解决方案已经得到了广泛应用,并被认为是一个合理的解决方案。

0
0 Comments

问题的原因是Android的Spinner组件默认不支持显示初始文本,而作者想要实现一个带有初始文本"Select One"的Spinner。

为了解决这个问题,作者创建了一个名为NothingSelectedSpinnerAdapter的装饰器适配器,用于在Spinner中显示初始文本。这个适配器可以包装任何SpinnerAdapter,并在第一个位置显示一个特定的View。

作者提供了一个工作示例,包括使用示例代码和布局文件。使用这个示例,开发人员可以自定义初始文本和布局,以及使用自定义适配器。

该解决方法非常优雅,代码可以直接复制到项目中使用,并且不需要使用反射。该解决方案还可以处理Spinner的其他常见问题,如默认选择第一个选项等。

虽然该解决方案非常好,但有些用户报告了在Android 5.0及更高版本上出现问题。作者在后续的回答中更新了代码,以解决这些问题。

总之,虽然Android的Spinner组件默认不支持显示初始文本,但是使用NothingSelectedSpinnerAdapter可以轻松实现这一功能。这个解决方案非常优雅,并且适用于大多数Android版本。

0