快速集成android实现listview的字母A-Z排序,界面侧边字母索引

来源:互联网 发布:notepad 安装sql插件 编辑:程序博客网 时间:2024/06/11 10:00

 转载请标明出处


Android手机字母A-Z排序侧边索引是非常常见的功能,在此提供快速集成框架.教你用Android studio工具一分钟搞定这个效果.

实现效果:

以及点击F跳转效果



第一步库包导入实现拼音检索功能



-------拼音检索详细见:

compile 'com.github.promeg:tinypinyin:1.0.0'// ~80KB同步后后面会下载80k的文件,就可以使用

-------测试一下:

public void go1(View view){//按钮go1点击测试
String str="界面侧边ABc字母检索";
for (char c:str.toCharArray()){
System.out.println("检索返回:"+Pinyin.toPinyin(c));//如果c为汉字,则返回大写拼音;如果c不是汉字,则返回String.valueOf(c)
System.out.println("如果c为汉字,则返回true,否则返回false:"+Pinyin.isChinese(c));
}
}
结果效果:
  
第二步构建代码:
1.适配器LvRithtItemAdapter类
public class LvRightItemAdapter extends BaseAdapter {    private List<DataEntity> mEntities;    private Activity context;    private LayoutInflater layoutInflater;    public LvRightItemAdapter(Activity context,List<DataEntity> entities) {        this.context = context;        this.mEntities = entities;        this.layoutInflater = LayoutInflater.from(context);    }    @Override    public int getCount() {        return mEntities.size();    }    @Override    public DataEntity getItem(int position) {        return mEntities.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        if (convertView == null) {            convertView = layoutInflater.inflate(R.layout.lv_right_item, parent,false);            ViewHolder viewHolder = new ViewHolder();            viewHolder.tvLvRightItem = (TextView) convertView.findViewById(R.id.tv_lv_right_item);            convertView.setTag(viewHolder);        }        initializeViews((DataEntity)getItem(position), (ViewHolder) convertView.getTag());        return convertView;    }    private void initializeViews(DataEntity entity, ViewHolder holder) {        //TODO implement        holder.tvLvRightItem.setText(String.valueOf(entity.getChar_First()));    }    protected class ViewHolder {        private TextView tvLvRightItem;    }}


2.自定义MyExpandAdapter代码(这个类只是把没用到的ExpandableListAdapter复写方法存放在这):

public abstract class MyExpandAdapter implements ExpandableListAdapter{    //用抽象方法把下拉子菜单的不用的方法集中在这里,方便观看    //抽象出接口,回调方法,用方法继承就可以定义子菜单    @Override    public void registerDataSetObserver(DataSetObserver observer) {    }    @Override    public void unregisterDataSetObserver(DataSetObserver observer) {    }    @Override    public Object getGroup(int groupPosition) {        return null;    }    @Override    public Object getChild(int groupPosition, int childPosition) {        return null;    }    @Override    public long getGroupId(int groupPosition) {        return 0;    }    @Override    public long getChildId(int groupPosition, int childPosition) {        return 0;    }    @Override    public boolean hasStableIds() {        return false;    }   @Override    public boolean isChildSelectable(int groupPosition, int childPosition) {        return false;    }    @Override    public boolean areAllItemsEnabled() {        return false;    }    @Override    public boolean isEmpty() {        return false;    }    @Override    public void onGroupExpanded(int groupPosition) {    }    @Override    public void onGroupCollapsed(int groupPosition) {    }    @Override    public long getCombinedChildId(long groupId, long childId) {        return 0;    }    @Override    public long getCombinedGroupId(long groupId) {        return 0;    }}


3.精简的下拉子菜单自定义SimpleExpAdapter适配器类
public class SimpleExpAdapter extends MyExpandAdapter{    private List<DataEntity> mDataEntities;   //列表数据存放的集合    private Activity mActivity;    private LayoutInflater mLayoutInflater;  //布局渲染成一个view    public SimpleExpAdapter(List<DataEntity> dataEntities, Activity activity){        mDataEntities = dataEntities;        mActivity = activity;        mLayoutInflater=mActivity.getLayoutInflater();    }    @Override    public int getGroupCount() {        return mDataEntities.size();    }    @Override    public int getChildrenCount(int groupPosition) {        return mDataEntities.get(groupPosition).getDatas().size();    }    @Override    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {        ViewHolder viewHolder=null;        if (convertView==null){            viewHolder=new ViewHolder();            convertView=mLayoutInflater.inflate(R.layout.exlv_item_group,parent,false);            viewHolder.mTextView= (TextView) convertView.findViewById(R.id.tv_exlv_group);            convertView.setTag(viewHolder);        }else {            viewHolder= (ViewHolder) convertView.getTag();        }        viewHolder.mTextView.setText(String.valueOf(mDataEntities.get(groupPosition).getChar_First()));//适配器设置列表数据        return convertView;    }    @Override    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {        ViewHolder viewHolder=null;        if (convertView==null){            viewHolder=new ViewHolder();            convertView=mLayoutInflater.inflate(R.layout.exlv_item_child,parent,false);            viewHolder.mTextView= (TextView) convertView.findViewById(R.id.tv_exlv_child);            convertView.setTag(viewHolder);        }else{            viewHolder= (ViewHolder) convertView.getTag();        }        viewHolder.mTextView.setText(mDataEntities.get(groupPosition).getDatas().get(childPosition));        return convertView;    }    class ViewHolder{//item放置的控件        TextView mTextView;    }}

4.数据逻辑控制dao包:
public class DataDao {    private List<DataEntity> mDataEntities=new ArrayList<>();    public void add(String data){        char data_first=data.toUpperCase().charAt(0);   //将首个字母转换为大写字母        if (Pinyin.isChinese(data_first)){   //如果首个字母是中文,则获取汉字首个字母的大写            data_first= Pinyin.toPinyin(data_first).charAt(0);        }        //确保取得大写的唯一首字母,然后继续执行        for (DataEntity dataEntity:mDataEntities){            if (dataEntity.isSameFirst(data_first)){                dataEntity.addData(data);                return;            }        }        DataEntity dataEntity=new DataEntity();        dataEntity.setChar_First(data_first);        dataEntity.addData(data);        mDataEntities.add(dataEntity);        Collections.sort(mDataEntities);   }    public List<DataEntity> getDataEntities() {        System.out.println(mDataEntities.toString());        return mDataEntities;    }}
5.封装列表数据类:
public class DataEntity implements Comparable<DataEntity>{    private char mChar_First;   //定义首字母    private List<String> mDatas=new ArrayList<>();   public  boolean isSameFirst(char des){//判断是否与传入的des相等        return des==this.mChar_First;    }    public void addData(String data){        mDatas.add(data);        Collections.sort(mDatas);  //排列首字母相同的列表数据        System.out.println(mDatas.toString());    }    @Override    public int compareTo(DataEntity another) {        return this.mChar_First-another.getChar_First();    }    public List<String> getDatas() {  //存放同首字母的列表数据        return mDatas;    }   public char getChar_First() {        return mChar_First;    }    public void setChar_First(char char_First) {        mChar_First = char_First;    }   @Override    public String toString() {        return "DataEntity{" +                "mChar_First=" + mChar_First +                ", mDatas=" + mDatas +                '}';    }}
6显示的activity界面类(数据直接在addlistdatas()方法中添加):
public class MainActivity extends AppCompatActivity {    ExpandableListView mExlv;    DataDao mDataDao=new DataDao();    ListView mLvRight; //右侧的字母栏    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        addListdatas();//填充列表假数据测试,失败经验:数据不能再setadapter之后进行        initListener();   }    public void initListener(){        mExlv.setAdapter(new SimpleExpAdapter(mDataDao.getDataEntities(), this));        //全都展开不能回缩        for (int i = 0; i < mDataDao.getDataEntities().size(); i++) {            mExlv.expandGroup(i);        }        mExlv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {            @Override            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {                return true;            }        });        mLvRight.setAdapter(new LvRightItemAdapter(this,mDataDao.getDataEntities()));        mLvRight.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                mExlv.setSelectedGroup(position);            }        });    }    public void initView(){        mExlv= (ExpandableListView) findViewById(R.id.exlv);        mLvRight= (ListView) findViewById(R.id.lv_right);    }//    public void go1(View view){   //字母检索//        String str="界面侧边ABc字母检索";//        for (char c:str.toCharArray()){//            System.out.println("检索返回:"+Pinyin.toPinyin(c));//如果c为汉字,则返回大写拼音;如果c不是汉字,则返回String.valueOf(c)//            System.out.println("如果c为汉字,则返回true,否则返回false:"+Pinyin.isChinese(c));//        }//    }    public void addListdatas(){        mDataDao.add("拜拜这是b");        mDataDao.add("啊啊这是a");        mDataDao.add("啧啧这是z");        mDataDao.add("烦烦这是f");        mDataDao.add("哥哥这是g");        mDataDao.add("哈哈这是h");        mDataDao.add("看看这是k");        mDataDao.add("啊拜这是ab");        for(int i='a';i<'z';i++){            if (i=='e'||i=='h'){                continue;            }            mDataDao.add((char) i + "1");            mDataDao.add((char) i + "2");            mDataDao.add((char) i + "3");        }        for (int i = 'A'; i <= 'Z'; i++) {            if (i == 'E' || i == 'H') {                continue;            }            mDataDao.add((char) i + "1");            mDataDao.add((char) i + "2");            mDataDao.add((char) i + "3");        }   }
第三步xml界面的构建:

1.activity界面的实现:
<RelativeLayout    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"    tools:context=".ui.MainActivity">    <ExpandableListView        android:id="@+id/exlv"        android:groupIndicator="@null"        android:layout_width="match_parent"        android:layout_height="match_parent"        />    <ListView        android:id="@+id/lv_right"        android:layout_width="20dp"        android:divider="@null"        android:layout_alignParentRight="true"        android:layout_height="match_parent"></ListView></RelativeLayout>
2.exlv_item_child自定义适配器布局(可以根据自己想法更改界面显示)
<TextView android:id="@+id/tv_exlv_child"          xmlns:android="http://schemas.android.com/apk/res/android"          android:layout_width="match_parent"          android:layout_height="50dp"          android:background="#bbb"          android:gravity="center_vertical"          android:paddingLeft="15dp"          android:textSize="12sp"></TextView>
3.exlv_item_group自定义适配器布局(可以根据自己想法更改界面显示)
<TextView android:id="@+id/tv_exlv_group"          xmlns:android="http://schemas.android.com/apk/res/android"          android:layout_width="match_parent"          android:layout_height="20dp"          android:background="#fff"          android:gravity="center_vertical"          android:paddingLeft="15dp"          android:textSize="12sp"></TextView>
4.lv_right_item自定义listview适配器布局(可以根据自己想法更改界面显示)
<TextView    android:id="@+id/tv_lv_right_item"    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="20dp"    android:background="#00ffffff"    android:gravity="center"    android:textSize="12sp"></TextView>


最后原理总结:
-----原理解析
概括:字符串放入 集合 中进行排序
分层结构:
                                        A:  a开头名字数据   子菜单名字(字符串排序:Collections.sort( 数据));
所有数据(如电话名字)     B:b开头名字数据 子菜单名字(字符串排序:Collections.sort( 数据));
                                      C:  c开头数据数据 子菜单名字(字符串排序:Collections.sort( 数据));
.....
在ASll码表中字母大小写位置

-----------implement方法构建精简的下拉子菜单适配器.

注意:用抽象类的方法,让我们想要的适配器实现需要的复写的方法

--------列表数据形式:



1 0