使用RelativeLayout實現自定義下拉列表Spinner

Android有提供Spinner,但並不是什麼時候都可以滿足需求。我們可以通過ReLativeLayout+TextView+ImageView來實現我們自己的一個Spinner,可以完成一些複雜的功能,而且更靈活。

現在進入正題:
先來看一下效果
效果圖

下面開始具體的實現,作爲一個demo,我只寫一些核心的代碼
首先我們把XML文件先寫好。定義一個ListView作爲我們顯示的下拉列表。我們建一個XML,叫myspinner_list.xml,裏面只需放一個ListView即可。
myspinner_list.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="match_parent"
    android:orientation="vertical" 
    android:background="#ffffffff">
        <ListView 
            android:id="@+id/lv_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffffff"
            android:divider="#ffffff"
            android:dividerHeight="0dp"/>
</LinearLayout>

有了ListView,那我們還需要寫ListView裏面的Item的XML文件,新建myspinner_list_item.xml,我們的demo比較簡單裏面就一個TextView。
myspinner_list_item.xml

<TextView
    android:id="@+id/tv_text"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:layout_gravity="center_vertical"
    android:text="item"
    android:padding="10dp"
    android:textSize="17sp"
    android:background="#ffffff"/>

最後在actitity_main.xml,寫好我們的下拉列表的樣式,具體的樣式就根據項目要求去寫就好了。
actitity_main.xml

<RelativeLayout
    android:id="@+id/rl_spinner"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:background="@drawable/relayout_spinner_bg">

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:textSize="18sp"
        android:singleLine="true"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:src="@drawable/invert_triangle"/>
</RelativeLayout>

到這裏我們XML文件就都寫好了,我們開始java代碼的編寫

首先我們需要寫一個適配器,我們定義爲SpinnerListAdapter.java,繼承BaseAdapter
適配器的作用主要是給list_item進行賦值
SpinnerListAdapter.java

public class SpinnerListAdapter extends BaseAdapter {

    private int mPosition;
    private String[] mItems;
    private MySpinner mSpinner;
    private Activity mActivity;
    private onItemClickListener mListener;

    public SpinnerListAdapter(MySpinner spinner, Activity activity, String[] items){
        this.mActivity=activity;
        this.mItems=items;
        this.mSpinner =spinner;
    }

    public int getCount() {
        return mItems.length;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    private class ViewHolder {
        public TextView text;
    }

    public View getView(final int arg0, final View arg1, ViewGroup arg2) {
        //獲取設置好的listener
        mListener= mSpinner.getListener();
        View view=arg1;
        ViewHolder holder=null;
        if(view==null){
            view= View.inflate(mActivity, R.layout.myspinner_list_item, null);
            holder = new ViewHolder();
            holder.text=(TextView) view.findViewById(R.id.tv_text);
            view.setTag(holder);
        }else {
            holder = (ViewHolder) view.getTag();
        }
        holder.text.setText(mItems[arg0]);

        view.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                mPosition=arg0; 
                mSpinner.close();
                mListener.click(mPosition,arg1);
            }
        });
        return view;
    }

    //回調接口
    public interface onItemClickListener{
        public void click(int position, View view);
    }   
}

然後來到我們最重要的一個類,我們定義爲MySpinner.java,繼承PopupWindow,PopupWindow其實也是對話框,與AlertDialog不一樣的是PopupWindow在界面任何地方顯示,像懸浮窗體,具體自行Google,我就不囉嗦了。
MySpinner.java

public class MySpinner extends PopupWindow implements OnItemClickListener {

    private String[] mItems;
    private MySpinner mWindow;
    private SpinnerListAdapter.onItemClickListener mListener;

    public MySpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MySpinner(Activity activity, int width, String[] items){
        LayoutInflater inflater=activity.getLayoutInflater();
        View contentView=inflater.inflate(R.layout.myspinner_list, null);
        // 設置PopupWindow的View 
        this.setContentView(contentView);
        // 設置PopupWindow彈出窗體的寬
        this.setWidth(width);
        // 設置PopupWindow彈出窗體的高  
        this.setHeight(android.view.WindowManager.LayoutParams.WRAP_CONTENT);  
        this.setFocusable(true);  
        this.setOutsideTouchable(true);  
        // 刷新狀態  
        this.update();   
        // 實例化一個ColorDrawable顏色
        ColorDrawable dw = new ColorDrawable(0xffffffff);
        this.setBackgroundDrawable(dw);

        this.mItems=items;
        ListView listView=(ListView) contentView.findViewById(R.id.lv_list);
        mWindow=this;
        SpinnerListAdapter adapter=new SpinnerListAdapter(mWindow,activity, mItems);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(this);
    }

    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        MySpinner.this.dismiss();
    }

    public void showAtLocation(View parent, int gravity, int x, int y) {
        super.showAtLocation(parent, gravity, x, y);
    }

    public void close(){
        this.dismiss();
    }

    public int position(){
        return 0;   
    }

    public void setOnItemClickListener(SpinnerListAdapter.onItemClickListener listener){
        this.mListener=listener;
    }

    public SpinnerListAdapter.onItemClickListener getListener(){
        //可以通過this的實例來獲取設置好的listener
        return mListener;       
    }
}

其實也沒多少東西,上面也有相應的註釋。

準備工作已經做完了,我們來調用上面的方法,實現我們的目的
我們在MainActivity進行調用,我們需要監聽rl_spinner的點擊事件,設置顯示的數據源,當選擇item時,將數據源的值賦給tv_conten進行顯示。
MainActivity .java

public class MainActivity extends AppCompatActivity {

    private RelativeLayout rl_spinner;
    private TextView tv_content;
    private String array[];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rl_spinner = (RelativeLayout) findViewById(R.id.rl_spinner);
        tv_content = (TextView) findViewById(R.id.tv_content);

        //初始化
        array = new String[]{"item1", "item2", "item3", "item4", "item5", "item6"};
        tv_content.setText(array[0]);

        rl_spinner.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MySpinner mySpinner = new MySpinner(MainActivity.this, rl_spinner.getWidth(), array);
                mySpinner.showAsDropDown(rl_spinner, 0, 0);//顯示在rl_spinner的下方
                mySpinner.setOnItemClickListener(new SpinnerListAdapter.onItemClickListener() {
                    @Override
                    public void click(int position, View view) {
                        tv_content.setText(array[position]);
                    }
                });
            }
        });

    }
}

這裏是作爲一個簡單demo,通過這種方法我們可以實現更多更豐富的功能,比如在ListView裏可以顯示圖片,比Spinner會更靈活一點,更多的用法可以自己進行研究。

最後附上源碼
源碼 http://pan.baidu.com/s/1c0jW2cC

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章