如何在Android中显示下拉框?

91

我该如何在Android中显示一个下拉框?


1
请更清楚地解释您想要什么,以及您已经尝试了什么。 - fretje
35
问题很具体。如果您知道什么是ComboBox,就不需要解释。如果您不知道,您仍然可以通过谷歌了解:http://en.wikipedia.org/wiki/Combo_box - vbence
1
@vbence:我不是在谈论ComboBox。由于Android是一个操作系统,你也可以问“如何在Windows中显示ComboBox”,这并不具体。 - fretje
20
由于Windows可以使用多种编程语言(如C#或Delphi等),所以无法给出具体的答案。但是在Android平台上,我们只有一个开发框架可供选择。因此,当你谈论Android时,就像说Visual Basic .Net一样具体。 - vbence
尝试这个例子https://dev59.com/iWYr5IYBdhLWcg3wy9SA#17650125 - string.Empty
1
https://developer.android.com/guide/topics/ui/controls/spinner.html - Smaillns
6个回答

86

在安卓中,它被称为Spinner,您可以在此处查看教程。

你好,Spinner

这是一个非常模糊的问题,您应该尝试更具体地描述您的问题。


18
建议您考虑这个问题与Android开发的相关性。请参考这个网站:http://www.designerandroid.com/?p=8。在Android开发中,它被称为Spinner。下次请先做好研究。 - gruntled
3
通过查看您提供的网站,可以看到该页面确实提到了ComboBox,但是在API中只有对Spinner的引用(http://developer.android.com/resources/tutorials/views/hello-spinner.html)。 在这里,他们明确表示“Spinner是类似于下拉列表的小部件,用于选择项目”。我同意您的观点,根据其他Java实现,它应该被称为ComboBox,但在这种情况下并不是这样。 - gruntled
3
我理解随着移动UI的出现,比喻有了一些变化。有新的小部件(控件)可以更好地利用有限的屏幕空间。我猜这就是为什么他们对一些熟悉的桌面隐喻的控件使用了新名称的原因。 - 我同意Spinner类似于下拉列表。然而,ListBox(下拉列表)和ComboBox之间的主要区别在于,组合框基本上是一个文本输入字段,扩展了从列表中选择的可能性。 你可以从列表中选择一个元素,也可以输入任意值。 - vbence
16
停止挑剔,承认每个人在第一次编写Android应用程序时都会遇到找不到类似组合框或列表框控件的问题。 - Torp
12
我仍在寻找一个组合框。我见过微调框,也用过微调框。但是实际情况是我需要将文本设置为除给定选项之外的其他内容。也就是说,他们可以在其中输入文字。微调框不是组合框,但通常是有效的替代品。 - IAmGroot
显示剩余2条评论

12

以下是一个自定义的 Android 下拉框示例:

package myWidgets;
import android.content.Context;
import android.database.Cursor;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.SimpleCursorAdapter;

public class ComboBox extends LinearLayout {

   private AutoCompleteTextView _text;
   private ImageButton _button;

   public ComboBox(Context context) {
       super(context);
       this.createChildControls(context);
   }

   public ComboBox(Context context, AttributeSet attrs) {
       super(context, attrs);
       this.createChildControls(context);
}

 private void createChildControls(Context context) {
    this.setOrientation(HORIZONTAL);
    this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
                   LayoutParams.WRAP_CONTENT));

   _text = new AutoCompleteTextView(context);
   _text.setSingleLine();
   _text.setInputType(InputType.TYPE_CLASS_TEXT
                   | InputType.TYPE_TEXT_VARIATION_NORMAL
                   | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
                   | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE
                   | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
   _text.setRawInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
   this.addView(_text, new LayoutParams(LayoutParams.WRAP_CONTENT,
                   LayoutParams.WRAP_CONTENT, 1));

   _button = new ImageButton(context);
   _button.setImageResource(android.R.drawable.arrow_down_float);
   _button.setOnClickListener(new OnClickListener() {
           @Override
           public void onClick(View v) {
                   _text.showDropDown();
           }
   });
   this.addView(_button, new LayoutParams(LayoutParams.WRAP_CONTENT,
                   LayoutParams.WRAP_CONTENT));
 }

/**
    * Sets the source for DDLB suggestions.
    * Cursor MUST be managed by supplier!!
    * @param source Source of suggestions.
    * @param column Which column from source to show.
    */
 public void setSuggestionSource(Cursor source, String column) {
    String[] from = new String[] { column };
    int[] to = new int[] { android.R.id.text1 };
    SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this.getContext(),
                   android.R.layout.simple_dropdown_item_1line, source, from, to);
    // this is to ensure that when suggestion is selected
    // it provides the value to the textbox
    cursorAdapter.setStringConversionColumn(source.getColumnIndex(column));
    _text.setAdapter(cursorAdapter);
 }

/**
    * Gets the text in the combo box.
    *
    * @return Text.
    */
public String getText() {
    return _text.getText().toString();
 }

/**
    * Sets the text in combo box.
    */
public void setText(String text) {
    _text.setText(text);
   }
}

希望能对你有所帮助!


1
谢谢您的回复。我想使用这个小部件,但我想使用一个字符串数组作为数据源,而不是游标。我该怎么办? - Ali Behzadian Nejad

7

尚未测试,但似乎最接近的方法是使用AutoCompleteTextView。您可以编写一个适配器来忽略过滤函数。例如:

class UnconditionalArrayAdapter<T> extends ArrayAdapter<T> {
    final List<T> items;
    public UnconditionalArrayAdapter(Context context, int textViewResourceId, List<T> items) {
        super(context, textViewResourceId, items);
        this.items = items;
    }

    public Filter getFilter() {
        return new NullFilter();
    }

    class NullFilter extends Filter {
        protected Filter.FilterResults performFiltering(CharSequence constraint) {
            final FilterResults results = new FilterResults();
            results.values = items;
            return results;
        }

        protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
            items.clear(); // `items` must be final, thus we need to copy the elements by hand.
            for (Object item : (List) results.values) {
                items.add((String) item);
            }
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    }
}

...然后在你的onCreate方法中:

String[] COUNTRIES = new String[] {"Belgium", "France", "Italy", "Germany"};
List<String> contriesList = Arrays.asList(COUNTRIES());
ArrayAdapter<String> adapter = new UnconditionalArrayAdapter<String>(this,
    android.R.layout.simple_dropdown_item_1line, contriesList);
AutoCompleteTextView textView = (AutoCompleteTextView)
    findViewById(R.id.countries_list);
textView.setAdapter(adapter);

代码未经测试,筛选方法中可能存在一些特性我没有考虑到,但是这里有基本的原则来模拟具有自动完成功能的ComboBox。
编辑:修复了NullFilter实现。我们需要访问项目,因此UnconditionalArrayAdapter的构造函数需要引用列表(一种缓冲区)。您也可以使用例如adapter = new UnconditionalArrayAdapter<String>(..., new ArrayList<String>);,然后使用adapter.add("Luxemburg"),这样您就不需要管理缓冲区列表。

这段代码根本无法编译。调用getFilter()的部分看起来像是无限循环的尝试,而publishResults正在从void方法中返回一个值。总体上想法不错,但需要有人修复这个例子。 - dhakim

6
这个问题非常明确和有效,因为Spinner和ComboBox(读作:您也可以提供自定义值的Spinner)是两个不同的东西。
我自己也在寻找同样的东西,但是我对给出的答案并不满意。所以我创建了自己的组件。也许有些人会发现以下提示有用。由于我的项目中使用了一些传统调用,所以我没有提供完整的源代码。无论如何,它应该非常清晰。
以下是最终结果的屏幕截图: ComboBox on Android 第一件事是创建一个视图,它看起来与尚未展开的Spinner相同。在屏幕截图中,您可以看到位于屏幕顶部(失去焦点)的Spinner和紧接其下方的自定义视图。为此,我使用LinearLayout(实际上,我从LinearLayout继承)并使用style="?android:attr/spinnerStyle"。LinearLayout包含TextView,并带有style="?android:attr/spinnerItemStyle"。完整的XML片段将是:
<com.example.comboboxtest.ComboBox 
    style="?android:attr/spinnerStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

    <TextView
        android:id="@+id/textView"
        style="?android:attr/spinnerItemStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ellipsize="marquee"
        android:singleLine="true"
        android:text="January"
        android:textAlignment="inherit" 
    />

</com.example.comboboxtest.ComboBox>

正如我之前提到的,ComboBox继承自LinearLayout。它还实现了OnClickListener接口,该接口创建了一个对话框,并从XML文件中填充自定义视图。以下是填充的视图:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" 
    >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" 
        >
        <EditText
            android:id="@+id/editText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:hint="Enter custom value ..." >

            <requestFocus />
        </EditText>

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="OK" 
        />
    </LinearLayout>

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
    />

</LinearLayout>

你需要实现两个监听器:列表的onItemClick和按钮的onClick。这两个监听器都会设置所选值并关闭对话框。

对于列表,如果希望其外观与展开Spinner相同,可以通过为列表适配器提供适当的(Spinner)样式来实现,如下所示:

ArrayAdapter<String> adapter = 
    new ArrayAdapter<String>(
        activity,
        android.R.layout.simple_spinner_dropdown_item, 
        states
    );

更或者少,那应该就是这样了。

看起来不错。我正在尝试实现你的解决方案,但我是 Android 开发的新手,对于在哪里放置代码片段有些困惑。你能否稍微修改一下并解释如何实现它? - You'reAGitForNotUsingGit

4

定制化 :) 您可以使用下拉菜单的水平/垂直偏移属性来定位列表,还可以尝试使用android:spinnerMode="dialog",它更酷炫。

布局

  <LinearLayout
        android:layout_marginBottom="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <AutoCompleteTextView
            android:layout_weight="1"
            android:id="@+id/edit_ip"
            android:text="default value"
            android:layout_width="0dp"
            android:layout_height= "wrap_content"/>
        <Spinner
            android:layout_marginRight="20dp"
            android:layout_width="30dp"
            android:layout_height="50dp"
            android:id="@+id/spinner_ip"
            android:spinnerMode="dropdown"
            android:entries="@array/myarray"/>
 </LinearLayout>

Java

          //set auto complete
        final AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit_ip);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, getResources().getStringArray(R.array.myarray));
        textView.setAdapter(adapter);
        //set spinner
        final Spinner spinner = (Spinner) findViewById(R.id.spinner_ip);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                textView.setText(spinner.getSelectedItem().toString());
                textView.dismissDropDown();
            }
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                textView.setText(spinner.getSelectedItem().toString());
                textView.dismissDropDown();
            }
        });

res/values/string

<string-array name="myarray">
    <item>value1</item>
    <item>value2</item>
</string-array>

那对您有帮助吗?

你的答案是什么?在哪里点击AutoCompleteTextView并显示? - ZarNi Myo Sett Win
您可以根据需要向AutoCompleteTextView或Spinner添加其他事件。 - ShAkKiR

0
对于一个允许自由文本输入并带有下拉列表框的组合框(http://en.wikipedia.org/wiki/Combo_box),我使用了vbence建议的AutoCompleteTextView
我使用onClickListener来在用户选择控件时显示下拉列表框。
我认为这是最符合这种组合框的样式。
private static final String[] STUFF = new String[] { "Thing 1", "Thing 2" };

public void onCreate(Bundle b) {
    final AutoCompleteTextView view = 
        (AutoCompleteTextView) findViewById(R.id.myAutoCompleteTextView);

    view.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
                view.showDropDown();
        }
    });

    final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
        this, 
        android.R.layout.simple_dropdown_item_1line,
        STUFF
    );
    view.setAdapter(adapter);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接