1. 程式人生 > >Android自定義Spinner下拉框,可以設定提示文字

Android自定義Spinner下拉框,可以設定提示文字

近期公司專案中需要用到下拉框,為了省事於是就用了自帶的Spinner,但使用後發現一個問題,就是不能設定提示文字。。並且,在父類是FragmentActivity的時候,還會有不一樣的顯示,總之使用起來非常的不爽。。於是就決定自己動手封裝一個Spinner來實現自己的效果,其實實現起來也是比較的簡單的,下面我們來一起看看吧。

首先來看看使用效果:

     

就是上圖中的景區級別選框。

其實這個的主要思路就是一個TextView負責顯示和監聽使用者的點選事件,還有一個PopupWindow負責顯示內容和監聽使用者點選事件。

下面來看看詳細程式碼吧:

首先是自定義一個PopupWindow:(程式碼很容易看懂,我就不寫註釋了)

/**
 * 自定義PopupWindow
 * Created by 05 on 2016/9/29.
 */
public class SpinnerPopWindow<T> extends PopupWindow {
    private LayoutInflater inflater;
    private ListView mListView;
    private List<T> list;
    private PopUpAdapter popAdapter;

    public SpinnerPopWindow(Context context, List<T> list,OnItemClickListener clickListener) {
        super(context);
        inflater = LayoutInflater.from(context);
        this.list = list;
        init(clickListener);
    }

    private void init(OnItemClickListener clickListener){
        View view = inflater.inflate(R.layout.spiner_window_layout, null);
        setContentView(view);
        setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
        setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
        setFocusable(true);
        ColorDrawable dw = new ColorDrawable(0x00);
        setBackgroundDrawable(dw);
        mListView = (ListView) view.findViewById(R.id.popup_listview);
        mListView.setAdapter(popAdapter = new PopUpAdapter());
        mListView.setOnItemClickListener(clickListener);
    }

    private class PopUpAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Object getItem(int position) {
            return list.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if(convertView == null){
                viewHolder = new ViewHolder();

                convertView = inflater.inflate(R.layout.pop_up_spinner_layout_item,null);
                viewHolder.textTv = (TextView) convertView.findViewById(R.id.pop_up_item_text_tv);

                convertView.setTag(viewHolder);
            }else{
                viewHolder = (ViewHolder) convertView.getTag();
            }
            viewHolder.textTv.setText(getItem(position).toString());
            return convertView;
        }
    }

    private class ViewHolder{
        private TextView textTv;
    }
}
自定義PopupWindow的介面程式碼:(只有一個ListView,在這裡一定要記得給佈局寫一個邊框和背景顏色,不然會有透明度的問題
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/popup_listview"
        android:scrollbars="none"
        android:background="@drawable/default_border_line_style"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

接下來是自定義Spinner程式碼:(在寫的時候記得分別準備一張顯示向上和向下圖片。)
/**
 * 自定義Spinner
 * Created by 05 on 2016/9/29.
 */
public class CustomSpinner extends RelativeLayout {

    private Context context;
    private List<String> textList;
    private View customSpinnerView;
    public TextView showTextTv;
    private SpinnerPopWindow<String> mpopWindow;
    private String showTitle;
    private String showText;

    private OnCustomItemCheckedListener onCustomItemCheckedListener;

    public CustomSpinner(Context context, String showTitle, List<String> textList) {
        super(context);
        this.context = context;
        this.showTitle = showTitle;
        this.textList = textList;
        init();
    }

    public interface OnCustomItemCheckedListener{
        void OnCustomItemChecked(int position);
    }

    public void setOnCustomItemCheckedListener(OnCustomItemCheckedListener onCustomItemCheckedListener){
        this.onCustomItemCheckedListener = onCustomItemCheckedListener;
    }

    private void init() {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        customSpinnerView = inflater.inflate(R.layout.custom_spinner_layout, this);

        showTextTv = (TextView) customSpinnerView.findViewById(R.id.custom_msg_tv);
        showTextTv.setText(showTitle);

        showTextTv.setOnClickListener(clickListener);

        mpopWindow = new SpinnerPopWindow<>(getContext(), textList, itemClickListener);
        mpopWindow.setOnDismissListener(dismissListener);
    }

    //設定顯示的提示文字
    public String getShowText(){
        return showText;
    }

    //對PopupWindow監聽選中使用者點選的項
    public void setSelectionItem(int position){
        showTextTv.setText(textList.get(position));
    }

    /**
     * 監聽popupwindow取消
     */
    private PopupWindow.OnDismissListener dismissListener = new PopupWindow.OnDismissListener() {
        @Override
        public void onDismiss() {
            setTextImage(R.mipmap.spinner_up);
        }
    };

    /**
     * popupwindow顯示的ListView的item點選事件
     */
    private AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            mpopWindow.dismiss();
            showTextTv.setText(textList.get(position));
            showText = textList.get(position);

            //這個介面是用來在其他介面做點選操作的時候負責呼叫的
            if(onCustomItemCheckedListener!= null){
                onCustomItemCheckedListener.OnCustomItemChecked(position);
            }
        }
    };

    /**
     * 顯示PopupWindow
     */
    private View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.custom_msg_tv:
                    mpopWindow.setWidth(showTextTv.getWidth());
                    mpopWindow.showAsDropDown(showTextTv);
                    setTextImage(R.mipmap.spinner_down);
                    break;
            }
        }
    };

    /**
     * 給TextView右邊設定圖片
     *
     * @param resId
     */
    private void setTextImage(int resId) {
        Drawable drawable = getResources().getDrawable(resId);
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());// 必須設定圖片大小,否則不顯示
        showTextTv.setCompoundDrawables(null, null, drawable, null);
    }

}

自定義Spinner的佈局程式碼也非常簡單,就是一個TextView設定一個邊框加白色背景,還有一張預設向下的圖片即可。通過以上的方法就完成Spinner的自定義了,怎麼樣,非常的簡單吧?嘿嘿嘿~~

現在來看一下怎樣使用這個自定義的Spinner。

<span style="white-space:pre">	</span>scenicLevels = getResources().getStringArray(R.array.levels);
        List<String> levelList = Arrays.asList(scenicLevels);
        levelSpinner = new CustomSpinner(getContext(), "請選擇評分", levelList);
        levelLl.addView(levelSpinner);

在例項化CustomSpinner之後記得用一個線性佈局.addView方法將自定義的Spinner新增進去。

通過這些方法,一個自定義的Spinner就做好了,當然了,由於自己能力有限,可能還有一些小問題,使得這個Spinner不夠優雅,但起碼這也算是一種思路,你們也可以把我的這個方法做一個更好的優化,讓它更加的優雅。。。哈哈哈,如果有什麼問題的話,歡迎來和我一起交流,在碼農的這條路上我們一起進步。~~