Android 开发之自定义 Spinner

Android 开发之自定义 Spinner

官方自带的 Spinner 不算好用,所以要想要特定的效果只能自己动手了

  • Spinner 概述
  • 完全自定义

Spinner 概述

Spinner 就是一个下拉选择器,是 Android 开发中很常用的一种控件,但是确实挺难用,比较死板,变化不灵活。

当我们需要特定样式的 Spinner 的时候,就很纠结,用还是不用它呢?今天就来自定义 Spinner ,满足所有需求。


Spinner 有几个特点:

  1. 右下角图标难看;
  2. 下拉列表包括已选分类;
  3. 下拉列表样式单一;

我需要的 Spinner 也有几个特点:

  1. 可以自定义右下角图标;
  2. 下拉列表样式可自定义;
  3. 下拉列表显示项不包括已选分类;
  4. 想怎么样就怎么样!

完全自定义 Spinner

准备工作
新建一个数组 res/values/arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="category">
        <item>国内</item>
        <item>国际</item>
        <item>体育</item>
        <item>社会</item>
        <item>科技</item>
        <item>娱乐</item>
    </string-array>
    <string-array name="category_id">
        <item>topNewsCN</item>
        <item>topNewsWorld</item>
        <item>sports</item>
        <item>eco</item>
        <item>technology</item>
        <item>entertainment</item>
    </string-array>
</resources>

自定义已选分类的 layout(打开+关闭)
spinner_item.xml

<?xml version="1.0" encoding="utf-8"?><!--Custom spinner item layout-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/spinner_arrow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableEnd="@drawable/btn1_1"
    android:drawableRight="@drawable/btn1_1"
    android:gravity="center_vertical"
    android:singleLine="true"
    android:textAlignment="inherit"
    android:textColor="@color/white"
    tools:ignore="UnusedAttribute" />

spinner_item_open.xml

<?xml version="1.0" encoding="utf-8"?><!--Custom spinner item layout-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/spinner_arrow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableEnd="@drawable/ic_arrow_drop_up_white_24dp"
    android:drawableRight="@drawable/ic_arrow_drop_up_white_24dp"
    android:gravity="center_vertical"
    android:singleLine="true"
    android:textAlignment="inherit"
    android:textColor="@color/white"
    tools:ignore="UnusedAttribute" />

弹窗选项(PopupWindow)

弹窗使用 PopupWindow + ListView

<?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">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/list_bg"
        />
</LinearLayout>

ListView 这里简单使用 TextView 作为 item ,具体用什么布局,就要看你自己的需求了

<?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="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="@color/white" />
</LinearLayout>

前期准备已经搞定,接下来就是 Activity 中的代码了

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //ButterKnife好东西
        ButterKnife.bind(this);
        mContext = this;
        styleSpinner();
        
    public void styleSpinner() {
        //标记各个分类
        hashMap = new HashMap<String, Integer>();
        hashMap.put(Constants.CN, 0);
        hashMap.put(Constants.WORLD, 1);
        hashMap.put(Constants.SPORTS, 2);
        hashMap.put(Constants.ECO, 3);
        hashMap.put(Constants.TECHNOLOGY, 4);
        hashMap.put(Constants.ENTERTAINMENT, 5);

        catname.setText(Utils.getCurrentCatogery());
        
        //分类
        cat = getResources().getStringArray(R.array.category);
        list = Arrays.asList(cat);
        arrayList = new ArrayList<String>(list);
        
        //下拉列表选项中去除已选分类
        arrayList.remove(Utils.getCurrentCatogeryPos());
        
        //设置弹窗布局
        layout = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.spinner_dropdown, null);
        //CustomSpinnerAdapter 就是一个自定义的 Adapter
        adapter = new CustomSpinnerAdapter(mContext, arrayList);
        listView.setAdapter(adapter);
    }
    
    public void showWindow(View view, final TextView txt) {
        adapter.notifyDataSetChanged();
        
        //设置弹窗 PopopWindow 属性,去除已选分类
        popupWindow = new PopupWindow(view);
        popupWindow.setWidth(position.getWidth());
        popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        popupWindow.setBackgroundDrawable(new BitmapDrawable(getResources(), (Bitmap) null));
        popupWindow.setOutsideTouchable(true);
        popupWindow.setFocusable(true);
        popupWindow.setContentView(layout);
        //设置弹窗的位置
        popupWindow.showAsDropDown(position, 0, 0);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                String selected = arrayList.get(arg2);
                txt.setText(selected);//设置已选分类
                arrayList.clear();
                arrayList.addAll(list);

                int pos = hashMap.get(selected);
                String[] categories = getResources().getStringArray(R.array.category_id);
                arrayList.remove(pos);//更新弹窗列表(去除已选分类)
                category_id = categories[pos];

                popupWindow.dismiss();//关闭弹窗
                popupWindow = null;
                
                doSomething();//进行选中分类的相应处理工作
            }
        });

    }

到这里就基本完成自定义 Spinner了

对了,你可以直接把 spinner_item.xml 放在你想要放的位置,还可以设置其打开的状态(箭头变化等),使用 spinner_item_open.xml。只需要监听弹窗的出现和消息就可以了。

现在就可以实现完全自定义的 Spinner了

posted @ 2016-07-25 17:59  shadowxs  阅读(777)  评论(0)    收藏  举报