实现简单的多选下拉"spinner"

来源:互联网 发布:大数据时代的阅读答案 编辑:程序博客网 时间:2024/05/20 04:29

         在这里之所以是带引号的Spinner是因为他并不是使用的系统的spinner,而是利用popupwindow来实现的一个spinner.

      效果图如下:(比较粗糙,可以仿照原理美化下)

     

_________________________________________________________________________


     下面正式介绍

     首先第一步:上边的两个类似spinner的东西,

     事先准备好9.png图片

      

      写一个style作为我们spinner实现的样式

style.xml

<style name="spinner_style">        <item name="android:background">@drawable/spinner</item>        <item name="android:padding">4dp</item>    </style>
    接着构造我们两个spinner的布局在其中引用我们的style.

layout_month_selector.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="horizontal"    android:layout_width="match_parent"    android:layout_height="match_parent">    <LinearLayout        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="2"        android:background="#ffffff"        android:gravity="center">    <ImageView        android:layout_width="20dp"        android:layout_height="20dp"        android:src="@drawable/date"/>    </LinearLayout>    <TextView        android:id="@+id/year"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="5"        android:textColor="#000000"        android:gravity="center"        style="@style/spinner_style">    </TextView>    <TextView        android:id="@+id/month"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="5"        android:textColor="#000000"        android:gravity="center"        style="@style/spinner_style">    </TextView></LinearLayout>
    

     开始定义我们的控件:

    

import android.content.Context;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;/** * Created by lenovo on 2016/11/2. */public class MonthSelector extends LinearLayout{    private View root;    private TextView yearText;    private TextView monthText;    private MonthSelectorDorp drop;//后面定义的下拉window    public MonthSelector(Context context) {        super(context);        initView(context);    }    public MonthSelector(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public MonthSelector(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initView(context);    }    private void initView(Context context){        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);        root = inflater.inflate(R.layout.layout_month_selector,this);//加载我们上面定义的布局,放到this中        yearText = (TextView)root.findViewById(R.id.year);        drop = new MonthSelectorDorp(context,this.getMeasuredWidth(),this.getMeasuredHeight()*4);        drop.setOnItemSelectedListener(new OnItemSelectedListener() {            @Override            public void onYearSelected(String year, int id) {                yearText.setText(year);   //年份选择时修改yearText中的文字            }            @Override            public void onMonthSelected(String month, int id) {               monthText.setText(month);   //月份修改时同上            }        });        yearText.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                drop.press(MonthSelectorDorp.YEAR_BUTTON);  //告诉drop是选的谁,以便初始布局                drop.showAsDropDown(MonthSelector.this);            }        });        monthText = (TextView)root.findViewById(R.id.month);        monthText.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                drop.press(MonthSelectorDorp.MONTH_BUTTON);                drop.showAsDropDown(MonthSelector.this);//drop要显示在这个控件之下            }        });    }    public String getMonth(){        String result = "";        result = result+yearText.getText().toString();        result = result+"-"+monthText.getText().toString().replace("月","");        return result;    }    public void setMonth(int year,int month){        this.yearText.setText(""+year);        this.monthText.setText(month + "月");    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        drop.setWidth(widthMeasureSpec);    //设置drop的宽度和高度,在这才会有效        drop.setHeight(heightMeasureSpec*4);    }}

这样,我们上边两个spinner大概就实现了,接下来就是我们下拉框了

根据效果,我这次的布局大概是这样实现(最后再讨论更通用的布局)。

popupwindow_month_selector.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="horizontal"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:padding="1dp"    android:background="@drawable/popupwindow_bg">    <LinearLayout        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="2"        android:orientation="vertical">        <TextView            android:id="@+id/year_select"            android:layout_width="match_parent"            android:layout_height="0dp"            android:layout_weight="1"            android:clickable="true"            android:text="@string/by_year"            android:gravity="center"            android:focusable="true" />        <TextView            android:id="@+id/month_select"            android:layout_width="match_parent"            android:layout_height="0dp"            android:layout_weight="1"            android:text="@string/by_month"            android:gravity="center"            android:focusable="true" />    </LinearLayout>    <ListView        android:id="@+id/year_list"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="5"        android:background="#ffffff">    </ListView>    <ListView        android:id="@+id/month_list"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="5"        android:background="#ffffff">    </ListView></LinearLayout>
在这里我们要让popupwindow有个边界,或者可以设置背景色与popupwindow背景色有差异,我采取前者

定义drawable,使他有左右下三条描边

popupwindow_bg.xml

<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item>    <shape>        <solid android:color="#ffffff"/>        <stroke android:color="#c0c0c0"            android:width="1dp"/>    </shape></item><item    android:left="1dp" android:right="1dp" android:bottom="1dp">    <shape>        <solid android:color="#ffffff"/>    </shape></item></layer-list>
以上是多层drawable来实现描三条边。

再往下我们开始写MonthSelectorDrop了

import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.widget.*;/** * Created by lenovo on 2016/11/4. */public class MonthSelectorDorp extends PopupWindow {    public final static int YEAR_BUTTON = 1;    public final static int MONTH_BUTTON = 2;    private TextView yearbtn;    private TextView monthbtn;    private ListView years;    private ListView months;    private View contentView;    private String yearss[];    private String monthss[];    private OnItemSelectedListener listener;    private int flag;    public MonthSelectorDorp(Context context,int width, int height) {        super(width,height);        initView(context);    }    private void initView(final Context context){        LayoutInflater inflater = LayoutInflater.from(context);        contentView = inflater.inflate(R.layout.popwindow_month_selector,null);        this.setContentView(contentView);        this.setFocusable(true);        this.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.popupwindow_bg));        yearbtn = (TextView)contentView.findViewById(R.id.year_select);        monthbtn = (TextView)contentView.findViewById(R.id.month_select);        years = (ListView)contentView.findViewById(R.id.year_list);        months = (ListView)contentView.findViewById(R.id.month_list);        years.setDivider(null);        months.setDivider(null);        years.setVerticalScrollBarEnabled(false);        months.setVerticalScrollBarEnabled(false);//不显示滑动条        yearss = context.getResources().getStringArray(R.array.years); //加载预定义的数组        final ListAdapter yearadapter = new ListAdapter(context,R.layout.listview_item_textview,yearss);        years.setAdapter(yearadapter);//适配器,自定义的        monthss = context.getResources().getStringArray(R.array.months);        final ListAdapter monthadapter = new ListAdapter(context,R.layout.listview_item_textview,monthss);        months.setAdapter(monthadapter);        years.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                listener.onYearSelected(yearadapter.getItem(position),position); //点击year时执行listener中year函数                dismiss();//popupwindow消失            }        });        months.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                listener.onMonthSelected(monthadapter.getItem(position),position);<span style="font-family: Arial, Helvetica, sans-serif;">//因为这里可以获得item所以我listener中增加了参数</span>                dismiss();            }        });        yearbtn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                flag = YEAR_BUTTON;                monthbtn.setBackgroundResource(R.drawable.text_normal);//根据选择切换背景                yearbtn.setBackgroundResource(R.drawable.text_focused);                months.setVisibility(View.INVISIBLE);                years.setVisibility(View.VISIBLE);            }        });        monthbtn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                flag = MONTH_BUTTON;                yearbtn.setBackgroundResource(R.drawable.text_normal);                monthbtn.setBackgroundResource(R.drawable.text_focused);                years.setVisibility(View.INVISIBLE);                months.setVisibility(View.VISIBLE);            }        });    }    public void setOnItemSelectedListener(OnItemSelectedListener listener){        this.listener = listener;    }    public void press(int bId){//用来预先设置好背景,判断点哪个出现的popupwindow        switch (bId){            case YEAR_BUTTON:                flag = YEAR_BUTTON;                monthbtn.setBackgroundResource(R.drawable.text_normal);                yearbtn.setBackgroundResource(R.drawable.text_focused);                months.setVisibility(View.INVISIBLE);                years.setVisibility(View.VISIBLE);                break;            case MONTH_BUTTON:                flag = MONTH_BUTTON;                yearbtn.setBackgroundResource(R.drawable.text_normal);                monthbtn.setBackgroundResource(R.drawable.text_focused);                years.setVisibility(View.INVISIBLE);                months.setVisibility(View.VISIBLE);                break;            default:                throw new IllegalArgumentException("don't have this argument"); //抛出非法参数异常        }    }}
两个点和没点的drawabel

text_focused.xml

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android">    <solid android:color="#ffffff"/></shape>
text_normal.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="#c0c0c0"/></shape>
为年份和月份选择准备的OnItemSelectedListener

/** * Created by lenovo on 2016/11/4. */public interface OnItemSelectedListener {    public void onYearSelected(String year,int id);    public void onMonthSelected(String month,int id);}
自定义的ListView的Item

listview_item_textview.xml

<?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">    <TextView        android:id="@+id/list_item"        android:layout_width="match_parent"        android:layout_height="30dp"        android:gravity="center"        android:textColor="#000000"/></LinearLayout>
自己的ListAdapter

import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.TextView;import csu.scrovor.cn.inote.R;/** * Created by lenovo on 2016/11/4. */public class ListAdapter extends ArrayAdapter<String> {    private TextView textView;    private int resource;    private String[] objects;    public ListAdapter(Context context, int resource, String[] objects) {//resource 为自定义Item layout的resId        super(context, resource, objects);        this.resource = resource;        this.objects = objects;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        String str = objects[position];        View v = LayoutInflater.from(getContext()).inflate(R.layout.listview_item_textview,null);        textView = (TextView)v.findViewById(R.id.list_item);        textView.setText(str);        return v;    }}

如果你有耐心看完以上的内容说明你真的是一个准备研究ui的人,虽然我的代码有很多冗余在以上。。

———————————————————————————————————————————————————

下面我们讨论下更通用的下拉布局实现。

在这里我只是有年份和月份,故直接写死,定格成这样,如果我们不止有2个呢?可能今天是3个明天4个呢?每次都重新写一个吗?

答案是否定的。

我们可以这样设计(预想中这样,没去实现呢):

drop 分为左右

左部:

   LinearLayout(vertical).需要新的时,我动态往里面增加View,width match parent,height我们设置统一规格。

右部:

  ListView就可以解决。根据左边不同的clicklistener,为listview适配不同的数据。这时我们在drop中添加一个flag来标记左边的哪个类别,并将此flag作为自定义Listener函数的参数回掉验证是哪个,再把相应的item设置到对应的下拉spinner中就可以解决了。大笑

 

ps:  做过几次UI设计,发现listener真的是一个很奇妙的东西,感觉它像是一个“管道”一般,在另一端发生的事情,让你在这一端触手可及。又像是是一个函数作为参数传递一般,但函数能操作不同空间中的事务,有时间再专门说一下这个listener的理解吧。







0 0
原创粉丝点击