android实现分组字母索引显示的listview

最近项目中有一个通讯录的模块,为了使体验效果更佳,和系统通讯录一样可以分组索引,于是自己用framlayout,嵌套listview和分组索引的布局方式实现的

我的代码中,写了两个界面实现,其中一个是添加对象list,另一个是string数组用到了排序,具体逻辑也不一样,我推荐使用前者;

先贴张效果图;

下面就说下我的实现思路和具体代码:

布局文件如下:

复制代码
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="fill_parent"
 3     android:layout_height="match_parent"
 4     android:background="#ffffff"
 5     android:orientation="vertical" >
 6 
 7     <TextView
 8         android:layout_width="fill_parent"
 9         android:layout_height="wrap_content"
10         android:padding="10dp"
11         android:textColor="#000"
12         android:textSize="16sp"
13         android:text="分组索引listview列表" />
14 
15     <FrameLayout
16         android:layout_width="match_parent"
17         android:layout_height="match_parent"
18         android:background="#ffffff" >
19 
20         <ListView
21             android:id="@+id/listView1"
22             android:layout_width="match_parent"
23             android:layout_height="wrap_content" >
24         </ListView>
25 
26         <TextView
27             android:id="@+id/tv"
28             android:layout_width="60dp"
29             android:layout_height="60dp"
30             android:layout_gravity="center"
31             android:background="#f0606060"
32             android:gravity="center"
33             android:text="A"
34             android:textColor="#ffffff"
35             android:textSize="30sp" />
36 
37         <LinearLayout
38             android:id="@+id/layout"
39             android:layout_width="wrap_content"
40             android:layout_height="fill_parent"
41             android:layout_gravity="right"
42             android:background="#d7d7d7"
43             android:gravity="center"
44             android:orientation="vertical" >
45         </LinearLayout>
46     </FrameLayout>
47 
48 </LinearLayout>
复制代码

图上看到的字母索引列表,是用过动态生成的,首先需要一个存放英文字母的数组
其中,给最外面的linearlayout添加onTouch事件,滑动时获取当前滑动的是哪一个字母索引,然后在listview查找item中存在的字段显示在最前面

复制代码
 1     /** 绘制索引列表 */
 2     public void getIndexView() {
 3         LinearLayout.LayoutParams params = new LayoutParams(
 4                 LayoutParams.WRAP_CONTENT, height);
 5         // params.setMargins(10, 5, 10, 0);
 6         for (int i = 0; i < str.length; i++) {
 7             final TextView tv = new TextView(this);
 8             tv.setLayoutParams(params);
 9             tv.setText(str[i]);
10             // tv.setTextColor(Color.parseColor("#606060"));
11             // tv.setTextSize(16);
12             tv.setPadding(10, 0, 10, 0);
13             layoutIndex.addView(tv);
14             layoutIndex.setOnTouchListener(new OnTouchListener() {
15 
16                 @Override
17                 public boolean onTouch(View v, MotionEvent event)
18 
19                 {
20                     float y = event.getY();
21                     int index = (int) (y / height);
22                     if (index > -1 && index < str.length) {// 防止越界
23                         String key = str[index];
24                         if (adapter.getSelector().containsKey(key)) {
25                             int pos = adapter.getSelector().get(key);
26                             if (listView.getHeaderViewsCount() > 0) {// 防止ListView有标题栏,本例中没有。
27                                 listView.setSelectionFromTop(
28                                         pos + listView.getHeaderViewsCount(), 0);
29                             } else {
30                                 listView.setSelectionFromTop(pos, 0);// 滑动到第一项
31                             }
32                             tv_show.setVisibility(View.VISIBLE);
33                             tv_show.setText(str[index]);
34                         }
35                     }
36                     switch (event.getAction()) {
37                     case MotionEvent.ACTION_DOWN:
38                         layoutIndex.setBackgroundColor(Color
39                                 .parseColor("#606060"));
40                         break;
41 
42                     case MotionEvent.ACTION_MOVE:
43 
44                         break;
45                     case MotionEvent.ACTION_UP:
46                         layoutIndex.setBackgroundColor(Color
47                                 .parseColor("#00ffffff"));
48                         tv_show.setVisibility(View.INVISIBLE);
49                         break;
50                     }
51                     return true;
52                 }
53             });
54         }
55     }
复制代码

然后关键的地方是在adapter中
1)中间显示对应的分组字母,通过隐藏和显示的方式控制

2)遍历字母数组和当前数据源,将对应字母在adapter中的position保存起来

复制代码
package com.allen.indexablelist;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/** 实现Filterable接口,编写过滤规则 */
public class NoteBookadapter extends BaseAdapter {
    private Context ctx;
    private ViewHolder holder;
    List<NoteBookItem> list;
    Map<String, Integer> selector;//键值是索引表的字母,值为对应在listview中的位置
    /** 字母表 */
    String index[];

    public NoteBookadapter(Context context, List<NoteBookItem> list,
            String[] index) {
        this.ctx = context;
        this.list = list;    
        this.index = index;
        selector = new HashMap<String, Integer>();
        for (int j = 0; j < index.length; j++) {// 循环字母表,找出list中对应字母的位置
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).index.equals(index[j].toLowerCase()))
                    selector.put(index[j], i);
            }

        }
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return list.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return list.get(arg0);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        try {
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = LayoutInflater.from(ctx).inflate(
                        R.layout.note_item, null);
                holder.tv1 = (TextView) convertView.findViewById(R.id.tv1);
                holder.tv2 = (TextView) convertView.findViewById(R.id.tv2);
                holder.iv = (ImageView) convertView.findViewById(R.id.iv_phone);
                holder.tv3 = (TextView) convertView.findViewById(R.id.tv3);
                holder.layout = convertView.findViewById(R.id.layout);
                holder.index = (TextView) convertView
                        .findViewById(R.id.tv_index);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            // 绑定数据
            NoteBookItem item = list.get(position);
            holder.tv1.setText(item.name);
            if (item.number.equals("null"))
                holder.tv2.setText(item.mobile);
            else
                holder.tv2.setText(item.number);
            holder.tv3.setText(item.call);

            // 显示index
            String currentStr = item.index;
            // 上一项的index
            String previewStr = (position - 1) >= 0 ? list.get(position - 1).index
                    : " ";
            /**
             * 判断是否上一次的存在
             */
            if (!previewStr.equals(currentStr)) {
                holder.index.setVisibility(View.VISIBLE);
                holder.index.setText(currentStr);//中奖提示的文本显示当前滑动的字母
            } else {
                holder.index.setVisibility(View.GONE);
            }
        } catch (OutOfMemoryError e) {
            Runtime.getRuntime().gc();
        } catch (Exception ex) {
            // handler.sendEmptyMessage(CommonMessage.PARSE_ERROR);
            ex.printStackTrace();
        }
        return convertView;
    }

    class ViewHolder {
        ImageView iv;
        TextView tv1;
        TextView tv2;
        TextView tv3;
        View layout;
        /** 索引字母 */
        TextView index;
    }

    public Map<String, Integer> getSelector() {
        return selector;
    }

    public void setSelector(Map<String, Integer> selector) {
        this.selector = selector;
    }

    public String[] getIndex() {
        return index;
    }

    public void setIndex(String[] index) {
        this.index = index;
    }
}
复制代码

 最后我把代码贴上点击下载:我这种方式实现虽然跟大牛写的不一样,但是基本功能实现了就行

路漫漫其修远兮 吾将上下而求索
原文地址:https://www.cnblogs.com/hudabing/p/3079556.html