如何在Android中自定义Spinner

172

我想给一个 Spinner 的下拉菜单添加自定义的高度,比如说 30dp,同时隐藏 Spinner 下拉列表中的分隔线。

到目前为止,我尝试将以下样式应用于 Spinner:

<style name="spinner_style">
        <item name="android:paddingLeft">0dp</item>
        <item name="android:dropDownWidth">533dp</item>
        <item name="android:showDividers">none</item>
        <item name="android:dividerHeight">0dp</item>
        <item name="android:popupBackground">@drawable/new_bg</item>
        <item name="android:dropDownHeight">70dp</item>
        <item name="android:scrollbarAlwaysDrawVerticalTrack">true</item>
        <item name="android:dropDownSelector">@android:color/white</item>
 </style>

我的旋转器代码是:

<Spinner
            android:id="@+id/pioedittxt5"
            android:layout_width="543dp"
            android:layout_height="63dp"
            android:layout_toRightOf="@+id/piotxt5"
            android:background="@drawable/spinner"
            style="@style/spinner_style"
            android:dropDownVerticalOffset="-53dp"
            android:spinnerMode="dropdown"
            android:drawSelectorOnTop="true"
            android:entries="@array/travelreasons"
            android:prompt="@string/prompt" />

但似乎什么都没有起作用。


1
请返回翻译后的文本:http://stephenpengilley.blogspot.com/2013/01/android-custom-spinner-tutorial.html http://custom-android-dn.blogspot.com/2012/12/how-to-use-and-custom-spinner-control.html - Houcine
@Houcine:我已经尝试了那些例子..我想要调整下拉列表的高度。 - Shruti
@shree202:没有应用任何样式。 - Shruti
@Shruti 看看这个视频 http://www.youtube.com/watch?v=JX9RmLAoOUY&feature=g-upl - Chirag Patel
1
@ComeIn,这不是Android风格,而是他自己创建的自定义风格。这就是为什么他只有“style=”。 - CyberClaw
显示剩余3条评论
6个回答

214
创建一个自定义适配器,并为您的下拉列表创建自定义布局。
Spinner spinner = (Spinner) findViewById(R.id.pioedittxt5);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
        R.array.travelreasons, R.layout.simple_spinner_item);
adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

R.layout.simple_spinner_item

<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="@style/spinnerItemStyle"
    android:maxLines="1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee" />

R.layout.simple_spinner_dropdown_item

<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="@style/spinnerDropDownItemStyle"
    android:maxLines="1"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/dropdownListPreferredItemHeight"
    android:ellipsize="marquee" />

在样式中添加您自定义的尺寸和高度,以符合您的要求。

 <style name="spinnerItemStyle" parent="android:Widget.TextView.SpinnerItem">

  </style>

  <style name="spinnerDropDownItemStyle" parent="android:TextAppearance.Widget.TextView.SpinnerItem">

  </style>

4
<item name="android:height">更改为<item name="android:layout_height"> - Tarun
1
谢谢回复。我尝试了但没有效果...已经断断续续地在处理这个问题3-4天了...现在只是感到烦躁 :( - 7bluephoenix
5
@Tarun,简单的下拉菜单布局文件simple_spinner_dropdown_item.xml中需要添加android:id="@+android:id/text1"吗? - batbrat
4
在R.layout.simple_spinner_dropdown_item中,将android:layout_height的值更改为"?attr/dropdownListPreferredItemHeight",否则会出现错误:"错误:属性不是public"。 - Loenix
13
将TextView和CheckedTextView直接放入layout_file.xml文件中,不要将它们包含在布局中。对于未来的访问者,请注意:我曾因为这个错误卡了几个小时,直到发现应该直接在布局文件中放置它们。请勿包含在布局中。 - Francisco Romero
显示剩余2条评论

113

您可以创建完全自定义的Spinner设计,如下所示:

步骤1:在drawable文件夹中创建background.xml以设置Spinner的边框。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/transparent" />
<corners android:radius="5dp" />
<stroke
android:width="1dp"
   android:color="@android:color/darker_gray" />
</shape>

第二步:使用此下拉图标或任何图像 drop.png 进行微调设计。 在此输入图片描述

 <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginRight="3dp"
    android:layout_weight=".28"
    android:background="@drawable/spinner_border"
    android:orientation="horizontal">

    <Spinner
        android:id="@+id/spinner2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_gravity="center"
        android:background="@android:color/transparent"
        android:gravity="center"
        android:layout_marginLeft="5dp"
        android:spinnerMode="dropdown" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_gravity="center"
        android:src="@mipmap/drop" />

</RelativeLayout>
最终结果看起来像下面的图片,并且在圆形区域内可点击,无需为imageView编写click Lister。 enter image description here 步骤3:对于下拉设计,请从Dropdown ListView中删除线条并更改背景颜色,创建自定义适配器,例如
Spinner spinner = (Spinner) findViewById(R.id.spinner1);
String[] years = {"1996","1997","1998","1998"};
ArrayAdapter<CharSequence> langAdapter = new ArrayAdapter<CharSequence>(getActivity(), R.layout.spinner_text, years );
langAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown);
mSpinner5.setAdapter(langAdapter);
在layout文件夹中创建R.layout.spinner_text.xml。
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layoutDirection="ltr"
android:id="@android:id/text1"
style="@style/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:paddingLeft="2dp"
/>

在布局文件夹中创建simple_spinner_dropdown.xml

<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="@style/spinnerDropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp"
android:singleLine="true" />

在样式中,您可以根据需要添加自定义尺寸和高度。

<style name="spinnerItemStyle" parent="android:Widget.TextView.SpinnerItem">
</style>

<style name="spinnerDropDownItemStyle" parent="android:TextAppearance.Widget.TextView.SpinnerItem">
</style>

最后看起来像这样

在此输入图片描述

根据要求,您可以通过更改simple_spinner_dropdown.xml的背景颜色或文本颜色来更改下拉颜色的背景颜色和文本。


错误地两次写入了android:width = "1dp"。 - Binesh Kumar
2
没问题,我只是不想自己编辑它,因为我不确定你是否想用“1dp”来指定高度,还是它只是一个重复。不过回答很好。 :) - Willi Mentzel
@BineshKumar 你好,请问你在哪里声明了 CheckedTextView?因为当我把代码粘贴进去时,它告诉我必须先声明该元素。 - QWERTY
不需要声明,因为它是 Android 的一部分。 - Binesh Kumar
6
你本可以在你的布局和可绘制资源中使用名称,我已经花了半个小时还是不知道该怎么做。因为回答不好,所以扣分。 - Anton Kizema
显示剩余4条评论

24

迄今为止,我发现最优雅和灵活的解决方案在这里:http://android-er.blogspot.sg/2010/12/custom-arrayadapter-for-spinner-with.html

基本上,按照以下步骤操作:

  1. 为您的下拉项创建自定义布局xml文件,比如我将其称为spinner_item.xml
  2. 为您的下拉适配器创建自定义视图类。在此自定义类中,您需要在getView()和getDropdownView()方法中重写并设置您的自定义下拉项布局。我的代码如下:

    public class CustomArrayAdapter extends ArrayAdapter<String>{
    
    private List<String> objects;
    private Context context;
    
    public CustomArrayAdapter(Context context, int resourceId,
         List<String> objects) {
         super(context, resourceId, objects);
         this.objects = objects;
         this.context = context;
    }
    
    @Override
    public View getDropDownView(int position, View convertView,
        ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      return getCustomView(position, convertView, parent);
    }
    
    public View getCustomView(int position, View convertView, ViewGroup parent) {
    
    LayoutInflater inflater=(LayoutInflater) context.getSystemService(  Context.LAYOUT_INFLATER_SERVICE );
    View row=inflater.inflate(R.layout.spinner_item, parent, false);
    TextView label=(TextView)row.findViewById(R.id.spItem);
     label.setText(objects.get(position));
    
    if (position == 0) {//Special style for dropdown header
          label.setTextColor(context.getResources().getColor(R.color.text_hint_color));
    }
    
    return row;
    }
    
    }
    
  3. 在您的Activity或Fragment中,使用自定义适配器为您的Spinner视图。类似于这样:

  4. Spinner sp = (Spinner)findViewById(R.id.spMySpinner);
    ArrayAdapter<String> myAdapter = new CustomArrayAdapter(this, R.layout.spinner_item, options);
    sp.setAdapter(myAdapter);
    

其中options是下拉选项字符串的列表。


对我来说,窍门在于重写getDropDownView方法。我一直在重写getView方法,但没有意识到我还需要重写那个方法。 - estebanuri
我该如何更改下拉框的背景颜色?因为如果我更改R.layout.spinner_item的背景颜色,它确实会更改背景颜色,但是下拉箭头及其周围的区域仍然保持“旧”的颜色。 - Blaupunkt

10

试试这个

当我尝试其他解决方案时,我遇到了很多问题...... 经过大量研究和开发,现在我找到了解决方法

  1. 在布局文件夹中创建custom_spinner.xml并粘贴此代码

     <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorGray">
    <TextView
    android:id="@+id/tv_spinnervalue"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="@color/colorWhite"
    android:gravity="center"
    android:layout_alignParentLeft="true"
    android:textSize="@dimen/_18dp"
    android:layout_marginTop="@dimen/_3dp"/>
    <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:background="@drawable/men_icon"/>
    </RelativeLayout>
    
  2. 在您的活动中

  3. Spinner spinner =(Spinner)view.findViewById(R.id.sp_colorpalates);
    String[] years = {"1996","1997","1998","1998"};
    spinner.setAdapter(new SpinnerAdapter(this, R.layout.custom_spinner, years));
    
  4. 创建一个新的适配器类

  5. public class SpinnerAdapter extends ArrayAdapter<String> {
    private String[] objects;
    
    public SpinnerAdapter(Context context, int textViewResourceId, String[] objects) {
        super(context, textViewResourceId, objects);
        this.objects=objects;
    }
    
    @Override
    public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }
    
    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }
    
    private View getCustomView(final int position, View convertView, ViewGroup parent) {
        View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_spinner, parent, false);
        final TextView label=(TextView)row.findViewById(R.id.tv_spinnervalue);
        label.setText(objects[position]);
        return row;
    }
    }
    

这使得在单击下拉列表后,所有项目都显示了men_icon图像,这不是我想要的。如果您不希望在单击下拉列表后在所有行上显示men_icon图像(或其他自定义内容),则请删除“getDropDownView”覆盖。 - Brettins

2
这对我很有用:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),R.layout.simple_spinner_item,areas);
            Spinner areasSpinner = (Spinner) view.findViewById(R.id.area_spinner);
            areasSpinner.setAdapter(adapter);

在我的布局文件夹中,我创建了simple_spinner_item

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
// add custom fields here 
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingRight="?android:attr/listPreferredItemPaddingRight" />

0

我在这个上面建立了一个小的演示项目,你可以看一下 项目链接


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