Android 自定义View修炼-如何打造Android自定义的下拉列表框控件
一、概述
Android中的有个原生的下拉列表控件Spinner,但是这个控件有时候不符合我们自己的要求,
比如有时候我们需要类似windows 或者web网页中常见的那种下拉列表控件,类似下图这样的:
这个时候只有自己动手写一个了。其实实现起来不算很难,
本文实现的方案是采用TextView +ImageView+PopupWindow的组合方案。
先来看看我们的自己写的控件效果图吧:(源码在文章下面最后给出哈!)
二、自定义下拉列表框控件的实现
1. 自定义控件用到的布局文件和资源:
结果框的布局页面:dropdownlist_view.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:id="@+id/compound" android:background="@drawable/dropdown_bg_selector" > <TextView android:id="@+id/text" android:layout_width="250dp" android:layout_height="40dp" android:paddingLeft="10dp" android:text="文本文字" android:gravity="center_vertical" android:textSize="14sp" android:padding="5dp" android:singleLine="true" /> <ImageView android:id="@+id/btn" android:layout_width="30dp" android:layout_height="30dp" android:layout_toRightOf="@+id/text" android:src="@drawable/dropdown" android:padding="5dp" android:layout_centerVertical="true" android:gravity="center"/> </RelativeLayout>
下拉弹窗列表布局页面:dropdownlist_popupwindow.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" > <ListView android:id="@+id/listView" android:layout_width="280dp" android:layout_height="wrap_content" android:divider="#666666" android:dividerHeight="1dp" ></ListView> </LinearLayout>
selector资源文件:
dropdown_list_selector.xml:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@color/dropdownlist_item_press"/> <item android:drawable="@color/dropdownlist_item"/> </selector>
dropdown_bg_selector.xml:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@color/dropdownlist_press"/> <item android:drawable="@color/dropdownlist_bg"/> </selector>
2. 自定义下拉列表框控件类的实现:
我们采用了TextView+ImageView+PopupWindow的组合方案,所以我的自定义控件需要重写ViewGroup,由于我们已经知道了,布局方向为竖直方向,所以这里,
我直接继承LinearLayout来写这个控件。具体实现代码如下:
package com.czm.xcdropdownlistview; import java.util.ArrayList; import android.annotation.SuppressLint; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.TextView; @SuppressLint("NewApi") /** * 下拉列表框控件 * @author caizhiming * */ public class XCDropDownListView extends LinearLayout{ private TextView editText; private ImageView imageView; private PopupWindow popupWindow = null; private ArrayList<String> dataList = new ArrayList<String>(); private View mView; public XCDropDownListView(Context context) { this(context,null); // TODO Auto-generated constructor stub } public XCDropDownListView(Context context, AttributeSet attrs) { this(context, attrs,0); // TODO Auto-generated constructor stub } public XCDropDownListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub initView(); } public void initView(){ String infServie = Context.LAYOUT_INFLATER_SERVICE; LayoutInflater layoutInflater; layoutInflater = (LayoutInflater) getContext().getSystemService(infServie); View view = layoutInflater.inflate(R.layout.dropdownlist_view, this,true); editText= (TextView)findViewById(R.id.text); imageView = (ImageView)findViewById(R.id.btn); this.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if(popupWindow == null ){ showPopWindow(); }else{ closePopWindow(); } } }); } /** * 打开下拉列表弹窗 */ private void showPopWindow() { // 加载popupWindow的布局文件 String infServie = Context.LAYOUT_INFLATER_SERVICE; LayoutInflater layoutInflater; layoutInflater = (LayoutInflater) getContext().getSystemService(infServie); View contentView = layoutInflater.inflate(R.layout.dropdownlist_popupwindow, null,false); ListView listView = (ListView)contentView.findViewById(R.id.listView); listView.setAdapter(new XCDropDownListAdapter(getContext(), dataList)); popupWindow = new PopupWindow(contentView,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); popupWindow.setBackgroundDrawable(getResources().getDrawable(R.color.transparent)); popupWindow.setOutsideTouchable(true); popupWindow.showAsDropDown(this); } /** * 关闭下拉列表弹窗 */ private void closePopWindow(){ popupWindow.dismiss(); popupWindow = null; } /** * 设置数据 * @param list */ public void setItemsData(ArrayList<String> list){ dataList = list; editText.setText(list.get(0).toString()); } /** * 数据适配器 * @author caizhiming * */ class XCDropDownListAdapter extends BaseAdapter{ Context mContext; ArrayList<String> mData; LayoutInflater inflater; public XCDropDownListAdapter(Context ctx,ArrayList<String> data){ mContext = ctx; mData = data; inflater = LayoutInflater.from(mContext); } @Override public int getCount() { // TODO Auto-generated method stub return mData.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub // 自定义视图 ListItemView listItemView = null; if (convertView == null) { // 获取list_item布局文件的视图 convertView = inflater.inflate(R.layout.dropdown_list_item, null); listItemView = new ListItemView(); // 获取控件对象 listItemView.tv = (TextView) convertView .findViewById(R.id.tv); listItemView.layout = (LinearLayout) convertView.findViewById(R.id.layout_container); // 设置控件集到convertView convertView.setTag(listItemView); } else { listItemView = (ListItemView) convertView.getTag(); } // 设置数据 listItemView.tv.setText(mData.get(position).toString()); final String text = mData.get(position).toString(); listItemView.layout.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub editText.setText(text); closePopWindow(); } }); return convertView; } } private static class ListItemView{ TextView tv; LinearLayout layout; } }
三、如何使用该自定义下拉列表框控件
使用该控件和使用普通的自带的控件一样,首先需要在布局文件中引用该控件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.czm.xcdropdownlistview.MainActivity" tools:ignore="MergeRootFrame" > <com.czm.xcdropdownlistview.XCDropDownListView android:id="@+id/drop_down_list_view" android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" /> </RelativeLayout>
其次,就是在代码中使用该控件:
package com.czm.xcdropdownlistview; import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; /** * 使用下拉列表框控件 示例 * @author caizhiming * */ public class MainActivity extends Activity { XCDropDownListView dropDownListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dropDownListView = (XCDropDownListView)findViewById(R.id.drop_down_list_view); ArrayList<String> list = new ArrayList<String>(); for(int i = 0;i< 6;i++){ list.add("下拉列表项"+(i+1)); } dropDownListView.setItemsData(list); } }
对了,这个控件中,我没有实现点击item项回调接口,这个可能对有些写惯了回调的可能觉得少了写什么的感觉,有兴趣的你可以自己添加相关回调操作哈,这个大家应该都会把。
四、源码下载
最后给出源码的下载:http://www.demodashi.com/demo/14682.html
感谢真题园网提供支持:http://www.zhentiyuan.com