zoukankan      html  css  js  c++  java
  • 具体评论ExpandableListView显示和查询模仿QQ组列表用户信息

    在我们的项目开发过程,用户通常拥有的信息包,通过组来显示用户的信息,一时候通过一定的查询条件来显示查询后的相关用户信息。而且通过颜色选择器来设置列表信息的背景颜色。

    当中借鉴xiaanming:http://blog.csdn.net/xiaanming/article/details/12684155

    以下来看看项目执行后的效果图以及代码结构图:


    以下通过代码来实现整个效果。

    1.主界面布局activity_main.xml

    <span style="font-size:18px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin" >
    
        <Button
            android:id="@+id/my_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="生成部门列表" />
    
        <com.example.myexpandabledemo.ClearEditText
            android:id="@+id/filter_edit"
            android:layout_width="fill_parent"
            android:layout_height="60dp"
            android:layout_marginTop="10dip"
            android:background="@drawable/search_bar_edit_selector"
            android:drawableLeft="@drawable/search_bar_icon_normal"
            android:hint="搜索"
            android:singleLine="true"
            android:textSize="15.0dip" />
        <TextView
    	    android:id="@+id/no_search_result_tv"
    	    android:layout_width="match_parent"
    	    android:layout_height="wrap_content"
    	    android:text="未搜索到结果"
    	    android:visibility="gone"
    	    />
        <ExpandableListView
            android:id="@+id/my_expand_lv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
    </LinearLayout></span>
    分析:主界面主要有一个Button,一个自己定义搜索的ClearEditText,一个无查询结果的TextView,一个列表信息显示ExpandableListView。

    当中Button主要用来生成列表信息。

    2.自己定义的ClearEditText的搜索框CliearEditText.java

    <span style="font-size:18px;">package com.example.myexpandabledemo;
    import android.content.Context;
    import android.graphics.drawable.Drawable;
    import android.text.Editable;
    import android.text.TextWatcher;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnFocusChangeListener;
    import android.view.animation.Animation;
    import android.view.animation.CycleInterpolator;
    import android.view.animation.TranslateAnimation;
    import android.widget.EditText;
    
    
    public class ClearEditText extends EditText implements  
            OnFocusChangeListener, TextWatcher { 
    	/**
    	 * 删除button的引用
    	 */
        private Drawable mClearDrawable; 
     
        public ClearEditText(Context context) { 
        	this(context, null); 
        } 
     
        public ClearEditText(Context context, AttributeSet attrs) { 
        	//这里构造方法也非常重要,不加这个非常多属性不能再XML里面定义
        	this(context, attrs, android.R.attr.editTextStyle); 
        } 
        
        public ClearEditText(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
        
        
        private void init() { 
        	//获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
        	mClearDrawable = getCompoundDrawables()[2]; 
            if (mClearDrawable == null) { 
            	mClearDrawable = getResources() 
                        .getDrawable(R.drawable.emotionstore_progresscancelbtn); 
            } 
            mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight()); 
            setClearIconVisible(false); 
            setOnFocusChangeListener(this); 
            addTextChangedListener(this); 
        } 
     
     
        /**
         * 由于我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件
         * 当我们按下的位置 在  EditText的宽度 - 图标到控件右边的间距 - 图标的宽度  和
         * EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向没有考虑
         */
        @Override 
        public boolean onTouchEvent(MotionEvent event) { 
            if (getCompoundDrawables()[2] != null) { 
                if (event.getAction() == MotionEvent.ACTION_UP) { 
                	boolean touchable = event.getX() > (getWidth() 
                            - getPaddingRight() - mClearDrawable.getIntrinsicWidth()) 
                            && (event.getX() < ((getWidth() - getPaddingRight())));
                    if (touchable) { 
                        this.setText(""); 
                    } 
                } 
            } 
     
            return super.onTouchEvent(event); 
        } 
     
        /**
         * 当ClearEditText焦点发生变化的时候,推断里面字符串长度设置清除图标的显示与隐藏
         */
        @Override 
        public void onFocusChange(View v, boolean hasFocus) { 
            if (hasFocus) { 
                setClearIconVisible(getText().length() > 0); 
            } else { 
                setClearIconVisible(false); 
            } 
        } 
     
     
        /**
         * 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去
         * @param visible
         */
        protected void setClearIconVisible(boolean visible) { 
            Drawable right = visible ? mClearDrawable : null; 
            setCompoundDrawables(getCompoundDrawables()[0], 
                    getCompoundDrawables()[1], right, getCompoundDrawables()[3]); 
        } 
         
        
        /**
         * 当输入框里面内容发生变化的时候回调的方法
         */
        @Override 
        public void onTextChanged(CharSequence s, int start, int count, 
                int after) { 
            setClearIconVisible(s.length() > 0); 
        } 
     
        @Override 
        public void beforeTextChanged(CharSequence s, int start, int count, 
                int after) { 
             
        } 
     
        @Override 
        public void afterTextChanged(Editable s) { 
             
        } 
        
       
        /**
         * 设置晃动动画
         */
        public void setShakeAnimation(){
        	this.setAnimation(shakeAnimation(5));
        }
        
        
        /**
         * 晃动动画
         * @param counts 1秒钟晃动多少下
         * @return
         */
        public static Animation shakeAnimation(int counts){
        	Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
        	translateAnimation.setInterpolator(new CycleInterpolator(counts));
        	translateAnimation.setDuration(1000);
        	return translateAnimation;
        }
     
     
    }</span>

    搜索框颜色选择器:

    <span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_focused="true" android:drawable="@drawable/search_bar_edit_pressed"></item>
        <item android:state_pressed="true" android:drawable="@drawable/search_bar_edit_pressed"></item>
        <item android:drawable="@drawable/search_bar_edit_normal"></item>
    </selector></span>


    3.汉字拼音排序所须要的汉字转拼音:CharacterParser.java

    <span style="font-size:18px;">package com.example.myexpandabledemo;
    
    /**
     * Java汉字转换为拼音
     * 
     */
    public class CharacterParser {
    	private static int[] pyvalue = new int[] {-20319, -20317, -20304, -20295, -20292, -20283, -20265, -20257, -20242, -20230, -20051, -20036, -20032,
    			-20026, -20002, -19990, -19986, -19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741, -19739, -19728,
    			-19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467, -19289, -19288, -19281, -19275, -19270, -19263, -19261,
    			-19249, -19243, -19242, -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006, -19003, -18996, -18977, -18961,
    			-18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735, -18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501, -18490,
    			-18478, -18463, -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201, -18184, -18183, -18181, -18012, -17997, -17988,
    			-17970, -17964, -17961, -17950, -17947, -17931, -17928, -17922, -17759, -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692,
    			-17683, -17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427, -17417, -17202, -17185, -16983, -16970, -16942, -16915, -16733,
    			-16708, -16706, -16689, -16664, -16657, -16647, -16474, -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419,
    			-16412, -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187, -16180, -16171, -16169, -16158, -16155, -15959,
    			-15958, -15944, -15933, -15920, -15915, -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640, -15631,
    			-15625, -15454, -15448, -15436, -15435, -15419, -15416, -15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180,
    			-15165, -15158, -15153, -15150, -15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110, -15109, -14941,
    			-14937, -14933, -14930, -14929, -14928, -14926, -14922, -14921, -14914, -14908, -14902, -14894, -14889, -14882, -14873, -14871, -14857,
    			-14678, -14674, -14670, -14668, -14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379, -14368, -14355, -14353,
    			-14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137, -14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094,
    			-14092, -14090, -14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894, -13878, -13870, -13859, -13847, -13831,
    			-13658, -13611, -13601, -13406, -13404, -13400, -13398, -13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343, -13340, -13329,
    			-13326, -13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076, -13068, -13063, -13060, -12888, -12875, -12871, -12860,
    			-12858, -12852, -12849, -12838, -12831, -12829, -12812, -12802, -12607, -12597, -12594, -12585, -12556, -12359, -12346, -12320, -12300,
    			-12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831, -11798, -11781, -11604, -11589, -11536, -11358,
    			-11340, -11339, -11324, -11303, -11097, -11077, -11067, -11055, -11052, -11045, -11041, -11038, -11024, -11020, -11019, -11018, -11014,
    			-10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533, -10519, -10331, -10329, -10328, -10322, -10315, -10309,
    			-10307, -10296, -10281, -10274, -10270, -10262, -10260, -10256, -10254};
    	public static String[] pystr = new String[] {"a", "ai", "an", "ang", "ao", "ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi", "bian",
    			"biao", "bie", "bin", "bing", "bo", "bu", "ca", "cai", "can", "cang", "cao", "ce", "ceng", "cha", "chai", "chan", "chang", "chao", "che",
    			"chen", "cheng", "chi", "chong", "chou", "chu", "chuai", "chuan", "chuang", "chui", "chun", "chuo", "ci", "cong", "cou", "cu", "cuan",
    			"cui", "cun", "cuo", "da", "dai", "dan", "dang", "dao", "de", "deng", "di", "dian", "diao", "die", "ding", "diu", "dong", "dou", "du",
    			"duan", "dui", "dun", "duo", "e", "en", "er", "fa", "fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu", "ga", "gai", "gan", "gang",
    			"gao", "ge", "gei", "gen", "geng", "gong", "gou", "gu", "gua", "guai", "guan", "guang", "gui", "gun", "guo", "ha", "hai", "han", "hang",
    			"hao", "he", "hei", "hen", "heng", "hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui", "hun", "huo", "ji", "jia", "jian",
    			"jiang", "jiao", "jie", "jin", "jing", "jiong", "jiu", "ju", "juan", "jue", "jun", "ka", "kai", "kan", "kang", "kao", "ke", "ken",
    			"keng", "kong", "kou", "ku", "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo", "la", "lai", "lan", "lang", "lao", "le", "lei", "leng",
    			"li", "lia", "lian", "liang", "liao", "lie", "lin", "ling", "liu", "long", "lou", "lu", "lv", "luan", "lue", "lun", "luo", "ma", "mai",
    			"man", "mang", "mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie", "min", "ming", "miu", "mo", "mou", "mu", "na", "nai",
    			"nan", "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian", "niang", "niao", "nie", "nin", "ning", "niu", "nong", "nu", "nv", "nuan",
    			"nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao", "pei", "pen", "peng", "pi", "pian", "piao", "pie", "pin", "ping", "po", "pu",
    			"qi", "qia", "qian", "qiang", "qiao", "qie", "qin", "qing", "qiong", "qiu", "qu", "quan", "que", "qun", "ran", "rang", "rao", "re",
    			"ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui", "run", "ruo", "sa", "sai", "san", "sang", "sao", "se", "sen", "seng", "sha",
    			"shai", "shan", "shang", "shao", "she", "shen", "sheng", "shi", "shou", "shu", "shua", "shuai", "shuan", "shuang", "shui", "shun",
    			"shuo", "si", "song", "sou", "su", "suan", "sui", "sun", "suo", "ta", "tai", "tan", "tang", "tao", "te", "teng", "ti", "tian", "tiao",
    			"tie", "ting", "tong", "tou", "tu", "tuan", "tui", "tun", "tuo", "wa", "wai", "wan", "wang", "wei", "wen", "weng", "wo", "wu", "xi",
    			"xia", "xian", "xiang", "xiao", "xie", "xin", "xing", "xiong", "xiu", "xu", "xuan", "xue", "xun", "ya", "yan", "yang", "yao", "ye", "yi",
    			"yin", "ying", "yo", "yong", "you", "yu", "yuan", "yue", "yun", "za", "zai", "zan", "zang", "zao", "ze", "zei", "zen", "zeng", "zha",
    			"zhai", "zhan", "zhang", "zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", "zhua", "zhuai", "zhuan", "zhuang", "zhui",
    			"zhun", "zhuo", "zi", "zong", "zou", "zu", "zuan", "zui", "zun", "zuo"};
    	private StringBuilder buffer;
    	private String resource;
    	private static CharacterParser characterParser = new CharacterParser();
    
    	public static CharacterParser getInstance() {
    		return characterParser;
    	}
    
    	public String getResource() {
    		return resource;
    	}
    
    	public void setResource(String resource) {
    		this.resource = resource;
    	}
    
    	/** * 汉字转成ASCII码 * * @param chs * @return */
    	private int getChsAscii(String chs) {
    		int asc = 0;
    		try {
    			byte[] bytes = chs.getBytes("gb2312");
    			if (bytes == null || bytes.length > 2 || bytes.length <= 0) {
    				throw new RuntimeException("illegal resource string");
    			}
    			if (bytes.length == 1) {
    				asc = bytes[0];
    			}
    			if (bytes.length == 2) {
    				int hightByte = 256 + bytes[0];
    				int lowByte = 256 + bytes[1];
    				asc = (256 * hightByte + lowByte) - 256 * 256;
    			}
    		} catch (Exception e) {
    			System.out.println("ERROR:ChineseSpelling.class-getChsAscii(String chs)" + e);
    		}
    		return asc;
    	}
    
    	/** * 单字解析 * * @param str * @return */
    	public String convert(String str) {
    		String result = null;
    		int ascii = getChsAscii(str);
    		if (ascii > 0 && ascii < 160) {
    			result = String.valueOf((char) ascii);
    		} else {
    			for (int i = (pyvalue.length - 1); i >= 0; i--) {
    				if (pyvalue[i] <= ascii) {
    					result = pystr[i];
    					break;
    				}
    			}
    		}
    		return result;
    	}
    
    	/** * 词组解析 * * @param chs * @return */
    	public String getSelling(String chs) {
    		String key, value;
    		buffer = new StringBuilder();
    		for (int i = 0; i < chs.length(); i++) {
    			key = chs.substring(i, i + 1);
    			if (key.getBytes().length >= 2) {
    				value = (String) convert(key);
    				if (value == null) {
    					value = "unknown";
    				}
    			} else {
    				value = key;
    			}
    			buffer.append(value);
    		}
    		return buffer.toString();
    	}
    
    	public String getSpelling() {
    		return this.getSelling(this.getResource());
    	}
    
    }
    </span>
    4. 拼音比較类:PinyinComparator.java

    <span style="font-size:18px;">package com.example.myexpandabledemo;
    
    import java.util.Comparator;
    
    public class PinyinComparator implements Comparator<GroupMemberBean> {
    
    	public int compare(GroupMemberBean o1, GroupMemberBean o2) {
    		if (o1.getSortLetters().equals("@")
    				|| o2.getSortLetters().equals("#")) {
    			return -1;
    		} else if (o1.getSortLetters().equals("#")
    				|| o2.getSortLetters().equals("@")) {
    			return 1;
    		} else {
    			return o1.getSortLetters().compareTo(o2.getSortLetters());
    		}
    	}
    
    }
    </span>
    5. 显示列表信息的名字以及其拼音首字母 GrouMemberBean.java
    <span style="font-size:18px;">package com.example.myexpandabledemo;
    
    public class GroupMemberBean {
    
    	private String name;   //显示的数据
    	private String sortLetters;  //显示数据拼音的首字母
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getSortLetters() {
    		return sortLetters;
    	}
    	public void setSortLetters(String sortLetters) {
    		this.sortLetters = sortLetters;
    	}
    }
    </span>
    6.ExpandaleListView 适配器MyExpandableAdapter.java
    <span style="font-size:18px;">package com.example.myexpandabledemo;
    
    import java.util.List;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.BaseExpandableListAdapter;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class MyExpandableAdapter extends BaseExpandableListAdapter {
    
    	private Context mContext;
    	private List<GroupMemberBean> mGroup;
    	private List<List<GroupMemberBean>> mChild;
    	private LayoutInflater mInflater;
    	public MyExpandableAdapter(Context mContext,List<GroupMemberBean> mGroup,List<List<GroupMemberBean>> mChild){
    		this.mContext = mContext;
    		this.mGroup = mGroup;
    		this.mChild = mChild;
    		this.mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    	}
    	/**
    	 * 当ListView数据发生变化时,调用此方法来更新ListView
    	 * 
    	 * @param list
    	 */
    	public void updateListView(List<GroupMemberBean> mGroup,List<List<GroupMemberBean>> mChild) {
    		this.mGroup = mGroup;
    		this.mChild = mChild;
    		notifyDataSetChanged();
    	}
    	
    	@Override
    	public int getGroupCount() {
    		// TODO Auto-generated method stub
    		return mGroup.size();
    	}
    
    	@Override
    	public int getChildrenCount(int groupPosition) {
    		// TODO Auto-generated method stub
    		return mChild.get(groupPosition).size();
    	}
    
    	@Override
    	public Object getGroup(int groupPosition) {
    		// TODO Auto-generated method stub
    		return mGroup.get(groupPosition);
    	}
    
    	@Override
    	public Object getChild(int groupPosition, int childPosition) {
    		// TODO Auto-generated method stub
    		return mChild.get(groupPosition).get(childPosition);
    	}
    
    	@Override
    	public long getGroupId(int groupPosition) {
    		// TODO Auto-generated method stub
    		return groupPosition;
    	}
    
    	@Override
    	public long getChildId(int groupPosition, int childPosition) {
    		// TODO Auto-generated method stub
    		return childPosition;
    	}
    
    	@Override
    	public boolean hasStableIds() {
    		// TODO Auto-generated method stub
    		return false;
    	}
    
    	@Override
    	public View getGroupView(int groupPosition, boolean isExpanded,
    			View convertView, ViewGroup parent) {
    		// TODO Auto-generated method stub
    		GroupHolderView groupHolderView;
    		if(convertView == null){
    			groupHolderView = new GroupHolderView();
    			convertView = (View) mInflater.inflate(R.layout.activity_group, null);
    			groupHolderView.groupTv = (TextView) convertView.findViewById(R.id.my_group_tv);
    			convertView.setTag(groupHolderView);
    		}else{
    			groupHolderView = (GroupHolderView) convertView.getTag();
    		}
    		groupHolderView.groupTv.setText(mGroup.get(groupPosition).getName());
    		return convertView;
    	}
    
    	@Override
    	public View getChildView(final int groupPosition, final int childPosition,
    			boolean isLastChild, View convertView, ViewGroup parent) {
    		// TODO Auto-generated method stub
    		
    		ChildHolderView childHolderView;
    		if(convertView == null){
    			childHolderView = new ChildHolderView();
    			convertView = (View) mInflater.inflate(R.layout.activity_child, null);
    			childHolderView.childIv = (ImageView) convertView.findViewById(R.id.my_child_iv);
    			childHolderView.childTv = (TextView) convertView.findViewById(R.id.my_child_tv);
    			childHolderView.childLl = (LinearLayout) convertView.findViewById(R.id.my_child_ll);
    			convertView.setTag(childHolderView);
    		}else{
    			childHolderView = (ChildHolderView) convertView.getTag();
    		}
    		childHolderView.childTv.setText(mChild.get(groupPosition).get(childPosition).getName());
    		childHolderView.childLl.setOnClickListener(new OnClickListener(){
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				Toast.makeText(mContext, "group:" + mGroup.get(groupPosition).getName() + "->child:" + mChild.get(groupPosition).get(childPosition).getName(), Toast.LENGTH_SHORT).show();
    			}
    		});
    		
    		return convertView;
    	}
    
    	@Override
    	public boolean isChildSelectable(int groupPosition, int childPosition) {
    		// TODO Auto-generated method stub
    		return false;
    	}
    	
    	class GroupHolderView{
    		TextView groupTv;
    	}
    	
    	class ChildHolderView{
    		ImageView childIv;
    		TextView childTv;
    		LinearLayout childLl;
    	}
    
    }</span>

    分析:

    GroupHolderView:用于显示组信息

    ChildHolderView:用于显示组下成员信息。包含一个LinearLayout,一个ImageView,一个TextVIew

    private List<GroupMemberBean> mGroup; 包括组的全部List信息
    private List<List<GroupMemberBean>> mChild;包括全部的组下成员信息

    <span style="font-size:18px;">	public void updateListView(List<GroupMemberBean> mGroup,List<List<GroupMemberBean>> mChild) {
    		this.mGroup = mGroup;
    		this.mChild = mChild;
    		notifyDataSetChanged();
    	}</span>
    依据传入的mGroup,mChild来更新列表信息。

    7.GroupHolderView类所相应的activity_group.xml

    <span style="font-size:18px;"><?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" >
    
        <TextView
            android:id="@+id/my_group_tv"
            android:layout_width="wrap_content"
            android:layout_height="50dp" 
            android:paddingLeft="50dp"
            android:gravity="center_vertical"
            />
    
    </LinearLayout></span>

    8.ChildHolderView类所相应的activity_child.xml

    <span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?

    > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/my_child_ll" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/my_child_selector" android:orientation="horizontal" > <ImageView android:id="@+id/my_child_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/ic_launcher" /> <TextView android:id="@+id/my_child_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout></span>

    分析:依据android:background="@drawable/my_child_selector" 颜色选择器来设置每一个列表行(选中或正常)的背景色。

    9.颜色选择器my_child_selector.xml


    <span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?

    > <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:drawable="@color/press_color"></item> <item android:state_pressed="true" android:drawable="@color/press_color"></item> <item android:drawable="@color/normal_color"></item> </selector></span>


    10.主界面实现代码:MainActivity.java

    <span style="font-size:18px;">package com.example.myexpandabledemo;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.text.Editable;
    import android.text.TextUtils;
    import android.text.TextWatcher;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.ExpandableListView;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
    	private Button myBtn;
    	private ExpandableListView myExpandLv;
    	private ClearEditText myClearEt;
    	private TextView noSearchResultTv;
    	private MyExpandableAdapter myAdapter;
    
    	private List<GroupMemberBean> groupBeanList;
    	private List<List<GroupMemberBean>> childBeanList = new ArrayList<List<GroupMemberBean>>();
    	/**
    	 * 汉字转换成拼音的类
    	 */
    	private CharacterParser characterParser;
    	/**
    	 * 依据拼音来排列ListView里面的数据类
    	 */
    	private PinyinComparator pinyinComparator;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    
    		init();
    	}
    
    	private void init() {
    		noSearchResultTv = (TextView)this.findViewById(R.id.no_search_result_tv);
    		myExpandLv = (ExpandableListView) this.findViewById(R.id.my_expand_lv);
    
    		// 实例化汉字转拼音类
    		characterParser = CharacterParser.getInstance();
    
    		pinyinComparator = new PinyinComparator();
    
    		groupBeanList = filledData(this.getResources().getStringArray(
    				R.array.depart));
    		List<GroupMemberBean> tempOne = filledData(this.getResources()
    				.getStringArray(R.array.child_one));
    		List<GroupMemberBean> tempTwo = filledData(this.getResources()
    				.getStringArray(R.array.child_two));
    
    		// 依据a-z进行排序源数据
    		Collections.sort(groupBeanList, pinyinComparator);
    
    		Collections.sort(tempOne, pinyinComparator);
    		Collections.sort(tempTwo, pinyinComparator);
    
    		for (int i = 0; i < groupBeanList.size(); i++) {
    			if (i % 2 == 0) {
    				childBeanList.add(tempOne);
    			} else {
    				childBeanList.add(tempTwo);
    			}
    		}
    
    		//用于生成列表信息
    		myBtn = (Button) this.findViewById(R.id.my_btn);
    		myBtn.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				myAdapter = new MyExpandableAdapter(MainActivity.this,
    						groupBeanList, childBeanList);
    				myExpandLv.setAdapter(myAdapter);
    				myExpandLv.expandGroup(0);
    			}
    
    		});
    
    		myClearEt = (ClearEditText) this.findViewById(R.id.filter_edit);
    
    		myClearEt.addTextChangedListener(new TextWatcher() {
    
    			@Override
    			public void beforeTextChanged(CharSequence s, int start, int count,
    					int after) {
    				// TODO Auto-generated method stub
    
    			}
    
    			@Override
    			public void onTextChanged(CharSequence s, int start, int before,
    					int count) {
    				// TODO Auto-generated method stub
    				filterData(s.toString());
    			}
    
    			@Override
    			public void afterTextChanged(Editable s) {
    				// TODO Auto-generated method stub
    
    			}
    		});
    	}
    
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    
    		// Inflate the menu; this adds items to the action bar if it is present.
    		getMenuInflater().inflate(R.menu.main, menu);
    		return true;
    	}
    
    	@Override
    	public boolean onOptionsItemSelected(MenuItem item) {
    		// Handle action bar item clicks here. The action bar will
    		// automatically handle clicks on the Home/Up button, so long
    		// as you specify a parent activity in AndroidManifest.xml.
    		int id = item.getItemId();
    		if (id == R.id.action_settings) {
    			return true;
    		}
    		return super.onOptionsItemSelected(item);
    	}
    
    	/**
    	 * 为ListView填充数据
    	 * 
    	 * @param date
    	 * @return
    	 */
    	private List<GroupMemberBean> filledData(String[] date) {
    		List<GroupMemberBean> mSortList = new ArrayList<GroupMemberBean>();
    
    		for (int i = 0; i < date.length; i++) {
    			GroupMemberBean sortModel = new GroupMemberBean();
    			sortModel.setName(date[i]);
    			// 汉字转换成拼音
    			String pinyin = characterParser.getSelling(date[i]);
    			String sortString = pinyin.substring(0, 1).toUpperCase();
    
    			// 正則表達式。推断首字母是否是英文字母
    			if (sortString.matches("[A-Z]")) {
    				sortModel.setSortLetters(sortString.toUpperCase());
    			} else {
    				sortModel.setSortLetters("#");
    			}
    
    			mSortList.add(sortModel);
    		}
    		return mSortList;
    
    	}
    
    	/**
    	 * 依据输入框中的值来过滤数据并更新ListView
    	 * 
    	 * @param filterStr
    	 */
    	private void filterData(String filterStr) {
    		List<GroupMemberBean> groupFilterList = new ArrayList<GroupMemberBean>();
    		List<GroupMemberBean> tempFilterList;
    		List<List<GroupMemberBean>> childFilterList = new ArrayList<List<GroupMemberBean>>();
    
    		if (TextUtils.isEmpty(filterStr)) {
    			groupFilterList = groupBeanList;
    			childFilterList = childBeanList;
    			noSearchResultTv.setVisibility(View.GONE);
    		} else {
    			groupFilterList.clear();
    			childFilterList.clear();
    			for (int i = 0; i < groupBeanList.size(); i++) {
    				//标记departGroup是否增加元素
    				boolean isAddGroup = false;
    				tempFilterList = new ArrayList<GroupMemberBean>();
    				GroupMemberBean sortModel = groupBeanList.get(i);
    				String name = sortModel.getName();
    				// depart有字符直接增加
    				if (name.indexOf(filterStr.toString()) != -1
    						|| characterParser.getSelling(name).startsWith(
    								filterStr.toString())) {
    					if (!groupFilterList.contains(sortModel)) {
    						groupFilterList.add(sortModel);
    						isAddGroup = true;
    					}
    				}
    
    				for (int j = 0; j < childBeanList.get(i).size(); j++) {
    					GroupMemberBean sortChildModel = childBeanList.get(i)
    							.get(j);
    					String childName = sortChildModel.getName();
    					// child有字符直接增加,其父也增加
    					if (childName.indexOf(filterStr.toString()) != -1
    							|| characterParser.getSelling(childName)
    									.startsWith(filterStr.toString())) {
    						tempFilterList.add(sortChildModel);
    						if (!groupFilterList.contains(groupBeanList.get(i))) {
    							groupFilterList.add(groupBeanList.get(i));
    							isAddGroup = true;
    						}
    					}
    
    				}
    				Collections.sort(tempFilterList, pinyinComparator);
    				if (isAddGroup) {
    					childFilterList.add(tempFilterList);
    				}
    			}
    
    			// 依据a-z进行排序
    			Collections.sort(groupBeanList, pinyinComparator);
    		}
    
    		if (myAdapter != null) {
    			myAdapter.updateListView(groupFilterList, childFilterList);
    
    			if (TextUtils.isEmpty(filterStr)) {
    				for (int i = 0; i < groupFilterList.size(); i++) {
    					if (i == 0) {
    						myExpandLv.expandGroup(i);
    						continue;
    					}
    					myExpandLv.collapseGroup(i);
    				}
    			} else {
    				//搜索的结果所有展开
    				for (int i = 0; i < groupFilterList.size(); i++) {
    					myExpandLv.expandGroup(i);
    				}
    			}
    		}
    		
    		//假设查询的结果为0时,显示为搜索到结果的提示
    		if(groupFilterList.size() == 0){
    			noSearchResultTv.setVisibility(View.VISIBLE);
    		}else{
    			noSearchResultTv.setVisibility(View.GONE);
    		}
    	}
    }
    </span>

    分析:

    <span style="font-size:18px;">		myBtn.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				myAdapter = new MyExpandableAdapter(MainActivity.this,
    						groupBeanList, childBeanList);
    				myExpandLv.setAdapter(myAdapter);
    				myExpandLv.expandGroup(0);
    			}
    
    		});</span>
    用于生成列表信息

    <span style="font-size:18px;">private List<GroupMemberBean> filledData(String[] date) </span>
    依据 res->array定义的字符数组,转化为List<GroupMemberBean>

    <span style="font-size:18px;">private void filterData(String filterStr) {</span>
    依据查询条件更新列表信息。
    重点:1.假设查询的条件为空,直接更新列表初始状态;

    假如:filterStr = “g”;

       2.假设查询的结果为空,直接给出“未搜索到结果”提示;

       3.假设Group中包括filterStr,GroupMemberBean sortModel 直接增加groupFilterList,并标记已增加isAddGroup = true;

          假设Child中包括filterStr,定义暂时的tempFilterList,GroupMemberBean sortChildModel增加到childFilterList。假设groupFilterList不包括其父组,并将其父增加到groupFilterList。并标记已增加isAddGroup=true;

          最后假设isAddGroup=true,将tempFilterList增加到childFilterList。

       4.通过myAdapter.updateListView(groupFilterList, childFilterList),更新列表信息。


    其上为本博文的全部内容。

    源码下载:

    http://download.csdn.net/detail/a123demi/7623975


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Max History CodeForces
    Buy a Ticket CodeForces
    AC日记——字符串的展开 openjudge 1.7 35
    AC日记——回文子串 openjudge 1.7 34
    AC日记——判断字符串是否为回文 openjudge 1.7 33
    AC日记——行程长度编码 openjudge 1.7 32
    AC日记——字符串P型编码 openjudge 1.7 31
    AC日记——字符环 openjudge 1.7 30
    AC日记——ISBN号码 openjudge 1.7 29
    AC日记——单词倒排 1.7 28
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4667936.html
Copyright © 2011-2022 走看看