android ListView根据字母排序和定位----支持混合排序

先看看图片效果,我的是来源于网上资料的改进,希望帮助对这方面有需要的的朋友

直接上图上代码,就不解释了,最底部有代码下载链接,想要的童鞋就去下吧

下载地址:http://download.csdn.net/detail/touchsnow/5349469

实现的功能:混合字符串处理  中英文排序   右侧悬浮栏   顶部名称提示栏   滚动悬浮提示



               




一 右侧字母表工具

package com.zuo.quickaction;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;


/**
 * 右侧字母表,快速定位
 *
 * @author zuo
 * @email 782287169@qq.com
 */
public class QuickLocationRightTool extends View
{
    private String[] b = null;


    public void setB(String[] b)
    {
        this.b = b;
    }


    OnTouchingLetterChangedListener onTouchingLetterChangedListener;


    int choose = -1;
    Paint paint = new Paint();
    boolean showBkg = false;


    public QuickLocationRightTool(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }


    public QuickLocationRightTool(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }


    public QuickLocationRightTool(Context context)
    {
        super(context);
    }


    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        if (showBkg) {
            canvas.drawColor(Color.parseColor("#10000000"));
        }


        int height = getHeight();
        int width = getWidth();
        int singleHeight = height / b.length;
        for (int i = 0; i < b.length; i++) {
            paint.setColor(Color.BLACK);
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            paint.setAntiAlias(true);
            if (i == choose) {
                paint.setColor(Color.parseColor("#3399ff"));
                paint.setFakeBoldText(true);
            }
            float xPos = width / 2 - paint.measureText(b[i]) / 2;
            float yPos = singleHeight * i + singleHeight;
            canvas.drawText(b[i], xPos, yPos, paint);
            paint.reset();
        }


    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent event)
    {
        final int action = event.getAction();
        final float y = event.getY();
        final int oldChoose = choose;
        final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
        final int c = (int) (y / getHeight() * b.length);    //字母位置


        switch (action) {
            case MotionEvent.ACTION_DOWN:
                showBkg = true;
                if (oldChoose != c && listener != null) {
                    if (c > 0 && c <= b.length) { //如果第一个字母是#,无效点击的话,条件变为c>0
                        listener.onTouchingLetterChanged(b[c]);
                        choose = c;                  //处理重复
                        invalidate();
                    }
                }


                break;
            case MotionEvent.ACTION_MOVE:
                if (oldChoose != c && listener != null) {
                    if (c > 0 && c <= b.length) {  //如果第一个字母是#,无效点击的话,条件变为c>0
                        listener.onTouchingLetterChanged(b[c]);
                        choose = c;
                        invalidate();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                showBkg = false;
                choose = -1;
                invalidate();
                break;
        }
        return true;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        return super.onTouchEvent(event);
    }


    public void setOnTouchingLetterChangedListener(
            OnTouchingLetterChangedListener onTouchingLetterChangedListener)
    {
        this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
    }


    public interface OnTouchingLetterChangedListener
    {
        public void onTouchingLetterChanged(String s);
    }


}
二 分组排序的列表适配器
package com.zuo.quickaction;

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

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zuo
 *         列表适配器
 */
public class QuickLocationListAdapter extends BaseAdapter
{
    private LayoutInflater layoutInflater;
    private OnClickListener onClickListener;
    private String[] stringArr;
    private Map<String, String> map = new HashMap<String, String>();

    public QuickLocationListAdapter(Context context, String[] arr, OnClickListener listener, Map<String, String> map)
    {
        layoutInflater = LayoutInflater.from(context);
        this.onClickListener = listener;
        stringArr = arr;
        this.map = map;
    }

    public int getCount()
    {
        return stringArr == null ? 0 : stringArr.length;
    }

    public Object getItem(int position)
    {
        if (stringArr != null) {
            String string = map.get(stringArr[position]);
            return string;
        }
        return null;
    }

    public long getItemId(int position)
    {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder holder = null;
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.list_item, null);
            holder = new ViewHolder();
            holder.firstCharHintTextView = (TextView) convertView
                    .findViewById(R.id.text_first_char_hint);
            holder.nameTextView = (TextView) convertView.findViewById(R.id.text_website_name);
            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.nameTextView.setText(map.get(stringArr[position]));
        int idx = position - 1;
        char previewChar = idx >= 0 ? stringArr[idx].charAt(0) : ' ';  //前一个字符
        char currentChar = stringArr[position].charAt(0);                //当前字符
        if (currentChar != previewChar) {                                     //如果不相等时显示
            if (isWord(currentChar)) {
                if (position != 0) {
                    holder.firstCharHintTextView.setVisibility(View.VISIBLE);
                }
                else {
                    holder.firstCharHintTextView.setVisibility(View.GONE);
                }
                holder.firstCharHintTextView.setText(String.valueOf(currentChar));
            }
            else {
                if (isWord(previewChar)) {
                    holder.firstCharHintTextView.setVisibility(View.VISIBLE);
                    holder.firstCharHintTextView.setText("*");
                }
                else {
                    holder.firstCharHintTextView.setVisibility(View.GONE);
                }
            }
        }
        else {
            holder.firstCharHintTextView.setVisibility(View.GONE);
        }
        return convertView;
    }

    public final class ViewHolder
    {
        public TextView firstCharHintTextView;
        public TextView nameTextView;
    }

    public boolean isWord(char c)
    {
        Pattern pattern = Pattern.compile("^[A-Za-z]+$");
        Matcher isNum = pattern.matcher(String.valueOf(c));
        if (!isNum.matches()) {
            return false;
        }
        else {
            return true;
        }
    }
}

三 主函数

package com.zuo.quickaction;

import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.*;
import android.widget.AdapterView.OnItemClickListener;
import com.zuo.quickaction.QuickLocationRightTool.OnTouchingLetterChangedListener;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zuowen
 * @time 2013.05.08
 * @email 782287169@qq.com
 * <p/>
 * 混合字符串处理  中英文排序   右侧悬浮栏   顶部名称提示栏   滚动悬浮提示
 */
public class QuickLocationMainActivity extends Activity implements ListView.OnScrollListener,
        OnItemClickListener, android.view.View.OnClickListener
{
    private QuickLocationRightTool letterListView;
    private Handler handler;
    private DisapearThread disapearThread;
    private int scrollState;
    private QuickLocationListAdapter quickLocationListAdapter;
    private ListView listMain;
    private TextView txtOverlay, title;
    private WindowManager windowManager;

    private String[] stringArr = {"ai", "zuo", "wn", "g黄真伊", "he河智苑", "@", "&&*(*", "한국 친구를 찾아요", "?", "擬好",
            "上饶", "厦门", "深圳", "武林", "text1", "+*())*&%$^", "11112", "6666", "898和",
            "阿拉伯", "阿镇", "下午", "责打", "浙江", "浙江", "阿布", "北京", "北城", "成", "城市", "123a", "234b", "678c", "得", "额",
            "方", "搞", "广州", "黄石", "黄冈", "杭州", "上海", "武林"};

    private String[] stringArr3 = new String[0];
    private ArrayList arrayList = new ArrayList();
    private ArrayList arrayList2 = new ArrayList();
    private ArrayList arrayList3 = new ArrayList();
    private Map<String, String> map = new HashMap<String, String>();


    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        for (int i = 0; i < stringArr.length; i++) {
            String pinyin = converterToPinYin(stringArr[i]);
            arrayList.add(pinyin);                                 //此列表增加拼音
            Collections.sort(arrayList, new MixComparator());
            if (!arrayList2.contains(pinyin.substring(0, 1)) && isWord(pinyin.substring(0, 1))) {
                arrayList2.add(pinyin.substring(0, 1));        //此列表添加拼音首字母
                Collections.sort(arrayList2, new MixComparator());
            }
            map.put(pinyin, stringArr[i]);
        }
        stringArr = (String[]) arrayList.toArray(stringArr);

        arrayList3.add("#");                                     //此列表添加不规则字符
        for (int i = 0; i < arrayList2.size(); i++) {
            String string = (String) arrayList2.get(i);
            arrayList3.add(string.toUpperCase());       //toUpperCase大写字母
        }
        arrayList3.add("*");

        stringArr3 = (String[]) arrayList3.toArray(stringArr3); // 得到右侧英文字母列表
        letterListView = (QuickLocationRightTool) findViewById(R.id.rightCharacterListView);
        letterListView.setB(stringArr3);
        letterListView.setOnTouchingLetterChangedListener(new LetterListViewListener());

        textOverlayout();

        // 初始化ListAdapter
        quickLocationListAdapter = new QuickLocationListAdapter(this, stringArr, this, null);
        listMain = (ListView) findViewById(R.id.listInfo);
        listMain.setOnItemClickListener(this);
        listMain.setOnScrollListener(this);
        listMain.setAdapter(quickLocationListAdapter);
        disapearThread = new DisapearThread();
    }

    /**
     * 滚到悬浮字母
     */
    public void textOverlayout()
    {
        handler = new Handler();
        //顶部悬浮
        title = (TextView) findViewById(R.id.list_title);
        // 初始化首字母悬浮提示框
        txtOverlay = (TextView) LayoutInflater.from(this).inflate(
                R.layout.popup_char, null);
        txtOverlay.setVisibility(View.INVISIBLE);
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                PixelFormat.TRANSLUCENT);
        windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        windowManager.addView(txtOverlay, lp);
    }

    /**
     * 右侧导航条点击列表滚动指定位置
     */
    public class LetterListViewListener implements
            OnTouchingLetterChangedListener
    {
        public void onTouchingLetterChanged(final String s)
        {
            int num = 0;
            for (int i = 0; i < stringArr.length; i++) {
                if ("a".equals(s) || "#".equals(s)) {      //顶部
                    num = 0;
                }
                else if ("*".equals(s)) {                      //底部
                    num = stringArr.length;
                }
                else if (isWord(stringArr[i].substring(0, 1)) && (character2ASCII(stringArr[i].substring(0, 1)) < (character2ASCII(s) + 32))) {
                    num += 1;                                     //首先判断是字母,字母的ascll值小于s是,滚动位置+1;如果有10个数据小于s,就滚到10处
                }

            }
            if (num < 2) {
                listMain.setSelectionFromTop(num, 0);
            }
            else {
                listMain.setSelectionFromTop(num, 5);    //留点间隔
            }
        }
    }

    /**
     * 滚动处理
     * @param view
     * @param firstVisibleItem
     * @param visibleItemCount
     * @param totalItemCount
     */
    public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount)
    {
        title.setVisibility(View.VISIBLE);
        if (firstVisibleItem != 0) {
            title.setText(map.get(stringArr[firstVisibleItem]));
        }
        else {
            title.setText("a");
        }
        title.setText(map.get(stringArr[firstVisibleItem]));
        txtOverlay.setText(String.valueOf(stringArr[firstVisibleItem].charAt(0)));// 泡泡文字以第一个可见列表为准

    }

    public void onScrollStateChanged(AbsListView view, int scrollState)
    {
        this.scrollState = scrollState;
        if (scrollState == ListView.OnScrollListener.SCROLL_STATE_IDLE) {
            handler.removeCallbacks(disapearThread);
            // 提示延迟1.0s再消失
            boolean bool = handler.postDelayed(disapearThread, 1000);
        }
        else {
            txtOverlay.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 列表点击
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    public void onItemClick(AdapterView<?> parent, View view, int position,
                            long id)
    {
        String personalName = map.get(stringArr[position]);
        Toast.makeText(QuickLocationMainActivity.this, personalName, 1).show();
    }

    public void onClick(View view)
    {

    }

    private class DisapearThread implements Runnable
    {
        public void run()
        {
            // 避免在1.5s内,用户再次拖动时提示框又执行隐藏命令。
            if (scrollState == ListView.OnScrollListener.SCROLL_STATE_IDLE) {
                txtOverlay.setVisibility(View.INVISIBLE);
            }
        }
    }

    public void onDestroy()
    {
        super.onDestroy();
        txtOverlay.setVisibility(View.INVISIBLE);
        title.setVisibility(View.INVISIBLE);
        windowManager.removeView(txtOverlay);
    }


    /**
     * 汉语拼音转换工具
     *
     * @param chinese
     * @return
     */
    public String converterToPinYin(String chinese)
    {
        String pinyinString = "";
        char[] charArray = chinese.toCharArray();
        // 根据需要定制输出格式,我用默认的即可
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        try {
            // 遍历数组,ASC码大于128进行转换
            for (int i = 0; i < charArray.length; i++) {
                if (charArray[i] > 128) {
                    // charAt(0)取出首字母
                    if (charArray[i] >= 0x4e00 && charArray[i] <= 0x9fa5) {    //判断是否中文
                        pinyinString += PinyinHelper.toHanyuPinyinStringArray(
                                charArray[i], defaultFormat)[0].charAt(0);
                    }
                    else {                          //不是中文的打上未知,所以无法处理韩文日本等等其他文字
                        pinyinString += "?";
                    }
                }
                else {
                    pinyinString += charArray[i];
                }
            }
            return pinyinString;
        }
        catch (BadHanyuPinyinOutputFormatCombination e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 把单个英文字母或者字符串转换成数字ASCII码
     *
     * @param input
     * @return
     */
    public static int character2ASCII(String input)
    {
        char[] temp = input.toCharArray();
        StringBuilder builder = new StringBuilder();
        for (char each : temp) {
            builder.append((int) each);
        }
        String result = builder.toString();
        return Integer.parseInt(result);
    }

    /**
     * 混合排序工具
     */
    public class MixComparator implements Comparator<String>
    {
        public int compare(String o1, String o2)
        {
            // 判断是否为空""
            if (isEmpty(o1) && isEmpty(o2))
                return 0;
            if (isEmpty(o1))
                return -1;
            if (isEmpty(o2))
                return 1;
            String str1 = "";
            String str2 = "";
            try {
                str1 = (o1.toUpperCase()).substring(0, 1);
                str2 = (o2.toUpperCase()).substring(0, 1);
            }
            catch (Exception e) {
                System.out.println("某个str为\" \" 空");
            }
            if (isWord(str1) && isWord(str2)) {               //字母
                return str1.compareTo(str2);
            }
            else if (isNumeric(str1) && isWord(str2)) {     //数字字母
                return 1;
            }
            else if (isNumeric(str2) && isWord(str1)) {
                return -1;
            }
            else if (isNumeric(str1) && isNumeric(str2)) {       //数字数字
                if (Integer.parseInt(str1) > Integer.parseInt(str2)) {
                    return 1;
                }
                else {
                    return -1;
                }
            }
            else if (isAllWord(str1) && (!isAllWord(str2))) {      //数字字母  其他字符
                return -1;
            }
            else if ((!isAllWord(str1)) && isWord(str2)) {
                return 1;
            }
            else {
                return 1;
            }
        }
    }

    /**
     * 判断空
     *
     * @param str
     * @return
     */
    private boolean isEmpty(String str)
    {
        return "".equals(str.trim());
    }

    /**
     * 判断数字
     *
     * @param str
     * @return
     */
    public boolean isNumeric(String str)
    {
        Pattern pattern = Pattern.compile("^[0-9]*$");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        else {
            return true;
        }
    }

    /**
     * 判读字母
     *
     * @param str
     * @return
     */
    public boolean isWord(String str)
    {
        Pattern pattern = Pattern.compile("^[A-Za-z]+$");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        else {
            return true;
        }
    }

    /**
     * 判断字母数字混合
     *
     * @param str
     * @return
     */
    public boolean isAllWord(String str)
    {
        Pattern pattern = Pattern.compile("^[A-Za-z0-9]+$");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        else {
            return true;
        }
    }

}
四 xml文件



list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/list_item_parent_layout"
        >
  <TextView
          android:id="@+id/text_first_char_hint"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textSize="18dp"
          android:padding="5dp"
          android:background="#e1e1e1"
          android:textColor="#f00"
          android:visibility="gone">
  </TextView>

  <LinearLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="horizontal"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content">
    <LinearLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_weight="1">

      <TextView
              android:id="@+id/text_website_name"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:textColor="@android:color/black"
              android:textSize="14dp"
              android:singleLine="true"
              android:padding="8dp"
              android:text="android"
              />
    </LinearLayout>
    <View
            android:id="@+id/divider"
            android:background="#ccc"
            android:focusable="false"
            android:clickable="false"
            android:longClickable="false"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"
            android:layout_width="1dp"
            android:layout_height="fill_parent"
            android:gravity="center_vertical"
            />
  </LinearLayout>
</LinearLayout>
 
   main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:orientation="vertical"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
        >
  <TextView
          android:id="@+id/list_title"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textSize="18dp"
          android:padding="5dp"
          android:background="#e1e1e1"
          android:textColor="#f00"
          android:text="a"
          android:layout_alignParentTop="true"
          android:visibility="gone">
  </TextView>


  <ListView android:id="@+id/listInfo"
            android:layout_below="@id/list_title"
            android:focusable="true"
            android:layout_weight="1.0"
            android:layout_height="match_parent"
            android:layout_width="fill_parent"
            android:scrollbars="none"
            android:cacheColorHint="#00000000"
            android:background="#fff"
          >
  </ListView>


    <com.zuo.quickaction.QuickLocationRightTool
            android:id="@+id/rightCharacterListView"
            android:background="#08000000"
            android:layout_width="20dip"
            android:layout_height="fill_parent"
            android:layout_alignParentRight="true"/>


</RelativeLayout>


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值