zoukankan      html  css  js  c++  java
  • android中自定义下拉框(转)

    android自带的下拉框好用不?我觉得有时候好用,有时候难有,项目规定这样的效果,自带的控件实现不了,那么只有我们自己来老老实实滴写一个新的了,其实最基本的下拉框就像一些资料填写时,点击的时候出现在编辑框的下面,然后又很多选项的下拉框,可是我在网上找了一下,没有这种下拉框额,就自己写了一个,看效果图先:

    ,这个是资料填写的一部分界面,三个下拉框,选择故乡所在地;

    点击之后弹出下拉框,选择下面的选项;

    三个下拉框时关联的,第一个决定了第二数据内容,第二个决定了第三个数据内容,如果三个全部选好之后,再次点击第一个,那么第二个、第三个都会清空,点击第二个则第三个会清空。

    要实现它,也就是一个PopupWindow时主要的界面,下面来看看代码:

    创建一个DefineSpinnerView.java文件,继承至View,然后给出如下属性:

    1. /** 
    2.  * 用于弹出的下拉框 
    3.  */  
    4. private PopupWindow pWindow = null;  
    5.   
    6. // **************************************************************************  
    7. // 这些是用来当点击一个时,根据他们之间的关系来显示下拉框中的内容  
    8. // **************************************************************************  
    9. /** 
    10.  * 祖父 
    11.  */  
    12. private DefineSpinnerView gradeParent = null;  
    13. /** 
    14.  * 父控件 
    15.  */  
    16. private DefineSpinnerView parents = null;  
    17. /** 
    18.  * 子控件 
    19.  */  
    20. private DefineSpinnerView child1 = null;  
    21. /** 
    22.  * 孙子控件 
    23.  */  
    24. private DefineSpinnerView child2 = null;  
    25.   
    26. private Context context = null;  
    27. private OptionsAdapter adapter = null; // 下拉框适配器  
    28. private List<String> datas = null; // 下拉框数据  
    29. private RelativeLayout layout = null; // 父控件  
    30. private TextView text = null; // 文本显示  
    31. private ImageView image = null; // 下拉箭头  
    32. private int p_width = -1; // 下拉框宽度  
    33. private ListView list = null; // 下拉表  

    在构造函数中,构造出一个TextView和一个ImageView控件,并将它们都添加到layout中,代码如下:

    1. TextListener lis = new TextListener();  
    2.         text = new TextView(context);  
    3.         text.setBackgroundResource(R.drawable.edit_normal);  
    4.         text.setTextColor(getResources().getColor(R.color.spinner_text));  
    5.         text.setGravity(Gravity.CENTER);  
    6.         text.setOnClickListener(lis);  
    7.         LayoutParams params1 = new LayoutParams(width, hight);  
    8.         params1.leftMargin = left;  
    9.         params1.topMargin = top;  
    10.   
    11.         image = new ImageView(context);  
    12.         image.setBackgroundResource(R.drawable.gerendang_jiantou);  
    13.         image.setOnClickListener(lis);  
    14.         if (LoginAct.MACHINE_PIXELS == IFinalConstant.XHDPI_RESOLUTION) {  
    15.             text.setTextSize(20.0f);  
    16.             LayoutParams params2 = new LayoutParams(19, 17);  
    17.             params2.topMargin = top + 15;  
    18.             params2.leftMargin = left + width - 28;  
    19.             map.put(image, params2);  
    20.         } else {  
    21.             text.setTextSize(15.0f);  
    22.             LayoutParams params2 = new LayoutParams(8, 8);  
    23.             params2.topMargin = top + 13;  
    24.             params2.leftMargin = left + width - 16;  
    25.             map.put(image, params2);  
    26.         }  
    27.   
    28.         map.put(text, params1);  

    里面涉及到一个TextListener内部类,是我们自己定义的一个类,它继承至OnClickListener接口

    1. /** 
    2.  * @author ZYJ 
    3.  *         当点击Text时,根据上一级的内容来设置下一级的内容 
    4.  */  
    5. class TextListener implements OnClickListener {  
    6.     public void onClick(View v) {  
    7.         hideSoft ();  
    8.         if (gradeParent != null && parents != null) {  
    9.             DefineSpinnerView.this.setDatas(DefineSpinnerView.this  
    10.                     .getGuxiang3(gradeParent.getText(), parents.getText()));  
    11.         }  
    12.         if (gradeParent == null && parents != null) {  
    13.             DefineSpinnerView.this.setDatas(DefineSpinnerView.this  
    14.                     .getGuxiang2(parents.getText()));  
    15.         }  
    16.         cleanText();  
    17.         changPopState(text);  
    18.     }  

    这个里面调用了一个方法changPopState,它的定义如下:

    1. /** 
    2.  * 显示或者隐藏下拉框 
    3.  * 
    4.  * @param v 
    5.  */  
    6. private void changPopState(View v) {  
    7.     if (pWindow == null) {  
    8.         popWindow(v);  
    9.         return;  
    10.     }  
    11.     if (!pWindow.isShowing()) {  
    12.         popWindow(v);  
    13.     } else {  
    14.         if (pWindow != null) {  
    15.             pWindow.dismiss();  
    16.         }  
    17.     }  
    18. }  

    这个里面又调用了一个popWindow方法,定义如下:

    1. /** 
    2.      * 初始化下拉框 
    3.      * 
    4.      * @param par 父控件 
    5.      */  
    6.     private void popWindow(final View par) {  
    7.         if (pWindow == null) {  
    8.   
    9.             // 布局文件  
    10.             View v = LayoutInflater.from(context).inflate(R.layout.list, null);  
    11.             list = (ListView) v.findViewById(R.id.list);  
    12.             list.setOnItemClickListener(new OnItemClickListener() {  
    13.                 public void onItemClick(AdapterView<?> arg0, View arg1,  
    14.                                         int arg2, long arg3) {  
    15.                     // R.String.butian代表的是“不填”  
    16.                     if (datas.get(arg2).toString().equals(context.getString(R.string.butian))) {    
    17.                         text.setText("");  
    18.                     } else {  
    19.                         text.setText(datas.get(arg2).toString()); // 将当前点击的item中的字符串显示出来  
    20.                     }  
    21.                     if (pWindow != null) { // 关闭下拉框  
    22.                         changPopState(par);  
    23.                     }  
    24.                 }  
    25.             });  
    26.             adapter = new OptionsAdapter(context, datas); // 根据数据,设置下拉框显示  
    27.             list.setAdapter(adapter);  
    28.             list.setDivider(null); // 屏蔽下拉框每个item之间的线条  
    29.             /** 
    30.              * 两种不同长度的下拉框,主要是为了适应屏幕的大小 
    31.              */  
    32.             if (p_width > 0) {  
    33.                 pWindow = new PopupWindow(v, par.getWidth(), 150);  
    34.             } else {  
    35.                 pWindow = new PopupWindow(v, par.getWidth(), 300);  
    36.             }  
    37.             pWindow.setFocusable(true);  
    38.             pWindow.setBackgroundDrawable(new BitmapDrawable());  
    39.             pWindow.setOutsideTouchable(true);  
    40.             pWindow.update();  
    41.         }  
    42.         pWindow.showAsDropDown(text);  
    43.     }  

    然后是一些细节了,提供一个TextView设置上面文字和得到上面文字的方法,设置下拉框数据的方法setDatas,如下:

    1. public void setText(String str) {  
    2.         if (text != null) {  
    3.             text.setText(str);  
    4.         }  
    5.     }  
    6.   
    7.     public void setDatas(List<String> datas) {  
    8.         this.datas = datas;  
    9.         if (adapter != null) {  
    10.             adapter.setDatas(datas);  
    11.             adapter.notifyDataSetInvalidated();  
    12.         }  
    13.     }  
    14.   
    15.     public String getText() {  
    16.         if (text != null) {  
    17.             return text.getText().toString();  
    18.         }  
    19.         LoginAct.LogW("spinner's textView is null");  
    20.         return "";  
    21.     }  
    22.   
    23.     private void cleanText() {  
    24.         if (child1 != null) {  
    25.             child1.text.setText("");  
    26.         }  
    27.         if (child2 != null) {  
    28.             child2.text.setText("");  
    29.         }  
    30.     }  

    然后添加几个关联控件的get方法:

    1. public void setChild1(DefineSpinnerView child1) {  
    2.        this.child1 = child1;  
    3.    }  
    4.   
    5.    public void setChild2(DefineSpinnerView child2) {  
    6.        this.child2 = child2;  
    7.    }  
    8.   
    9.    public void setGradeParent(DefineSpinnerView gradeParent) {  
    10.        this.gradeParent = gradeParent;  
    11.    }  
    12.   
    13.    public void setParents(DefineSpinnerView parents) {  
    14.        this.parents = parents;  
    15.    }  
    16.   
    17.    public void setP_width(int p_width) {  
    18.        this.p_width = p_width;  
    19.    }  

    接下来提供一个设置子控件和算子控件数据的方法:

    1. /** 
    2.      * @param s1 父控件中的字符串 
    3.      * @param s2 子控件中的字符串 
    4.      * @return 返回一个List<String>集合 
    5.      * @功能 通过父控件的字符串来设置子控件中的内容 
    6.      */  
    7.     private List<String> getGuxiang3(String s1, String s2) {  
    8.         List<String> dd = new ArrayList<String>();  
    9.         dd.add(context.getString(R.string.butian));  
    10.         Map<String, ArrayList<String>> mapTmp1 = MaterialView.cityMap.get(s1);  
    11.         if (mapTmp1 != null) {  
    12.             List<String> list = mapTmp1.get(s2);  
    13.             if (list != null) {  
    14.                 for (String str : list) {  
    15.                     dd.add(str);  
    16.                 }  
    17.             }  
    18.         }  
    19.         return dd;  
    20.     }  
    21.   
    22.     /** 
    23.      * @param s 字符串 
    24.      * @return 
    25.      * @author ZYJ 
    26.      * @功能 设置父亲辈的下拉框中的内容 
    27.      */  
    28.     private List<String> getGuxiang2(String s) {  
    29.         List<String> dd = new ArrayList<String>();  
    30.         dd.add(context.getString(R.string.butian));  
    31.         Map<String, ArrayList<String>> mapTmp = MaterialView.cityMap.get(s);  
    32.         if (mapTmp != null) {  
    33.             for (String str : mapTmp.keySet()) {  
    34.                 dd.add(str);  
    35.             }  
    36.         }  
    37.         return dd;  
    38.     }  

    最后提供一个隐藏软键盘的方法:

    1. private void hideSoft() {  
    2. putMethodManager imm = (InputMethodManager) context  
    3. .getSystemService(Context.INPUT_METHOD_SERVICE);  
    4. m.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT,  
    5. InputMethodManager.HIDE_NOT_ALWAYS);  

    到这里,自定义控件的代码基本上写完了;我们还要来看看下拉框中的xml布局和适配器的写法:

    xml文件:

    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    2.               xmlns:tools="http://schemas.android.com/tools"  
    3.               android:layout_width="match_parent"  
    4.               android:layout_height="match_parent"  
    5.               android:orientation="horizontal">  
    6.   
    7.     <TextView  
    8.             android:id="@+id/info"  
    9.             android:layout_width="wrap_content"  
    10.             android:layout_height="30dp"  
    11.             android:textSize="15sp"  
    12.             android:textColor="@color/spinner_text"  
    13.             android:layout_gravity="center"  
    14.             android:gravity="center"/>  
    15.   
    16. </LinearLayout>  

    然后是适配器类(OptionsAdapter),看全部代码吧:

    1. public class OptionsAdapter extends BaseAdapter {  
    2.   
    3.     private Context context = null;  
    4.     private List<String> datas = null;  
    5.   
    6.     public OptionsAdapter(Context context, List<String> d) {  
    7.         this.context = context;  
    8.         this.datas = d;  
    9.     }  
    10.   
    11.     public int getCount() {  
    12.         return datas.size();  
    13.     }  
    14.   
    15.     public Object getItem(int arg0) {  
    16.         return datas.get(arg0);  
    17.     }  
    18.   
    19.     public long getItemId(int arg0) {  
    20.         return arg0;  
    21.     }  
    22.   
    23.     /** 
    24.      * @author ZYJ 
    25.      * @功能 一个简单TextView显示 
    26.      */  
    27.     public View getView(int arg0, View arg1, ViewGroup arg2) {  
    28.         View view = LayoutInflater.from(context).inflate(R.layout.childlist,  
    29.                 null);  
    30.         TextView textStr = (TextView) view.findViewById(R.id.info);  
    31.         textStr.setText(" " + getItem(arg0).toString());  
    32.         return view;  
    33.     }  
    34.   
    35.     public void setDatas(List<String> datas) {  
    36.         this.datas = datas;  
    37.     }  
    38.   
    39. }  

    这样,上面的功能基本上都实现了,我的这个控件在我项目中是手动添加上去的,而不是定义在xml文件中的,所以也不知道定义在xml文件中能不能生效,各位尽管试试吧。

    转自:http://blog.csdn.net/a497393102/article/details/9279309

  • 相关阅读:
    深度学习之视频人脸识别系列二:人脸检测与对齐
    终极指南:构建用于检测汽车损坏的Mask R-CNN模型(附Python演练)
    数据挖掘和机器学习的面试问题
    SVM多核学习方法简介
    RookeyFrame 线上 添加Model
    RookeyFrame Bug 线上创建的DLL被删除了 模块无法删除 临时解决
    RookeyFrame Bug 编号显示 系统自动生成 的问题,有时候依旧会显示text文本框
    C# 跨域 请求带cookie
    RookeyFrame 隐藏 首次加载菜单 的伸缩动画
    RookeyFrame 加载 自定义JS
  • 原文地址:https://www.cnblogs.com/manmanlu/p/3816021.html
Copyright © 2011-2022 走看看