Android 仿美团大众字母索引实现

来源:互联网 发布:centos6开放3306端口 编辑:程序博客网 时间:2024/04/28 04:04

android字母索引流程:

  界面步骤:
  1、初始化右侧字母的高度以及大小
  2、回执索引列表,并为列表当中的字母设置监听事件

业务逻辑步骤:
   1、先从服务器读取我的好友列表
   2、将好友的名字转换为拼音,并取得首字母,按照字母大小进行排序。装载联系人非字母为首的数组。保存到selector HashMap当中。键为联系人的字母的开头,值为联系人在这个集合里面的下标
   3、取得返回数据装载到适配器里面去 

会用到的第三方库:pinyin4j.jar :http://download.csdn.net/detail/q908555281/9296197
 

布局文件:

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" ><!-- 这个用来显示联系人的列表 -->    <ListView        android:id="@+id/listview_news_friends"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="@drawable/comment_background"        android:cacheColorHint="#00000000"        android:divider="@null"        android:fadingEdge="none"        android:scrollbars="none" >    </ListView><!-- 这个用来显示右侧字母栏的布局 -->    <LinearLayout        android:id="@+id/lilayout_news_friends"        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:layout_gravity="right"        android:background="#d7d7d7"        android:gravity="center"        android:orientation="vertical" >    </LinearLayout>    <!-- 这个用来显示点击字母后,屏幕中间出现的字母提示 -->    <TextView        android:id="@+id/tv_news_friends_letter"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center"        android:background="@color/white"        android:gravity="center"        android:paddingBottom="@dimen/px_20"        android:paddingLeft="@dimen/px_30"        android:paddingRight="@dimen/px_30"        android:paddingTop="@dimen/px_20"        android:text="A"        android:textColor="@color/common_text_input"        android:textSize="@dimen/text_size_25"        android:visibility="gone" /></FrameLayout>


主类:

import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.List;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import android.annotation.SuppressLint;import android.content.Intent;import android.graphics.Color;import android.os.AsyncTask;import android.os.Bundle;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.view.ViewGroup;import android.view.ViewTreeObserver;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.LinearLayout;import android.widget.LinearLayout.LayoutParams;import android.widget.ListView;import android.widget.TextView;import com.lidroid.xutils.ViewUtils;import com.lidroid.xutils.view.annotation.ViewInject;import com.slife.gopapa.R;import com.slife.gopapa.activity.news.ContactsActivity;import com.slife.gopapa.adapter.FriendsAdapter;import com.slife.gopapa.application.MyApplication;import com.slife.gopapa.common.APPConstants;import com.slife.gopapa.dao.JArrayErrorDao;import com.slife.gopapa.dao.impl.JArrayErrorDaoImpl;import com.slife.gopapa.database.DBConstants;import com.slife.gopapa.http.MyHttpClient;import com.slife.gopapa.model.ContactsPerson;import com.slife.gopapa.util.ChineseTransferUtils;/*** @ClassName: FriendsFragment * @Description: 我的好友界面*  界面步骤:*  1、初始化右侧字母的高度以及大小*  2、回执索引列表,并为列表当中的字母设置监听事件* * 业务逻辑步骤:* 1、先从服务器读取我的好友列表*   2、将好友的名字转换为拼音,并取得首字母,按照字母大小进行排序。装载联系人非字母为首的数组。保存到selector HashMap当中。键为联系人的字母的开头,值为联系人在这个集合里面的下标*   *   3、取得返回数据装载到适配器里面去 * @author 菲尔普斯* @date 2015-3-26 下午5:12:37 * */public class FriendsFragment extends Fragment {@ViewInject(R.id.listview_news_friends)private ListView listView; // 联系人列表@ViewInject(R.id.tv_news_friends_letter)private TextView txCenter; // 显示在中间的字母@ViewInject(R.id.lilayout_news_friends)private LinearLayout layoutIndex;private HashMap<String, Integer> selector = new HashMap<String, Integer>();// 存放含有索引字母的位置private static final String[] indexStr = { "☆", "A", "B", "C", "D", "E","F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R","S", "T", "U", "V", "W", "X", "Y", "Z", "#" };// 右边的字母private List<ContactsPerson> newPersons = new ArrayList<ContactsPerson>();// 对联系人进行转换成拼音private int height;// 字体高度private boolean flag = false;// 选中标签private FriendsAdapter adapter;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_friends, container,false);ViewUtils.inject(this, view);View headView = inflater.inflate(R.layout.view_friends_headview, null);listView.addHeaderView(headView);initOverload();initListView();return view;}private void initListView() {adapter = new FriendsAdapter(getActivity(), newPersons);listView.setAdapter(adapter);new GetFriendListTask().execute();listView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {if(position==0){startActivity(new Intent(getActivity(),ContactsActivity.class));}}});}/** * @Title: initOverload * @Description: 初始化右侧字母栏高度 * @param * @return void * @throws */private void initOverload() {// 这是获取屏幕宽高的监听器ViewTreeObserver observer = layoutIndex.getViewTreeObserver();observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {public boolean onPreDraw() {if (!flag) {// 获取每个字母的高度height = layoutIndex.getMeasuredHeight() / indexStr.length;getIndexView();flag = true;}return true;}});}/** * @Title: getIndexView * @Description: 绘制索引列表(字母列表的监听事件) * @param * @return void * @throws */public void getIndexView() {LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, height);for (int i = 0; i < indexStr.length; i++) {final TextView tv = new TextView(this.getActivity());// 右侧字母索引tv.setLayoutParams(params);tv.setText(indexStr[i]);// 右侧字母tv.setPadding(10, 0, 10, 0);tv.setTextSize(12);tv.setTextColor(Color.parseColor("#3E75A9"));layoutIndex.addView(tv);// 设置右侧索引布局的触摸监听器layoutIndex.setOnTouchListener(new OnTouchListener() {@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouch(View v, MotionEvent event) {float y = event.getY();int index = (int) (y / height);if (index > -1 && index < indexStr.length) {// 防止越界String key = indexStr[index];if (selector.containsKey(key)) {int pos = selector.get(key);// 将ListView的item移动到点击相应字母if (listView.getHeaderViewsCount() > 0) {// 防止ListView有标题栏,本例中没有。listView.setSelectionFromTop(pos + listView.getHeaderViewsCount(), 0);} else {listView.setSelectionFromTop(pos, 0);// 滑动到第一项}txCenter.setVisibility(View.VISIBLE);txCenter.setText(indexStr[index]);} else {txCenter.setVisibility(View.VISIBLE);txCenter.setText(indexStr[index]);}}switch (event.getAction()) {case MotionEvent.ACTION_DOWN:layoutIndex.setBackgroundColor(Color.parseColor("#606060"));txCenter.setVisibility(View.VISIBLE);break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:layoutIndex.setBackgroundColor(Color.parseColor("#00ffffff"));txCenter.setVisibility(View.GONE);break;}return true;}});}}/*** @ClassName: GetFriendListTask * @Description: 取得我的好友列表* @author 菲尔普斯* @date 2015-3-26 下午5:13:45 * */class GetFriendListTask extends AsyncTask<Void, Void, String[]> {@Overrideprotected String[] doInBackground(Void... params) {return MyHttpClient.postDataToService(getActivity(),APPConstants.URL_HOSTNAME+ APPConstants.URL_FRIENDS_LISTSAPP2,MyApplication.tokenApp2, new String[] { "user_account" },new String[] { MyApplication.preferences.getString(DBConstants.USER_ACCOUNT, "") }, null,null);}@Overrideprotected void onPostExecute(String[] result) {super.onPostExecute(result);JArrayErrorDaoImpl.resolveJson(getActivity(), result,new JArrayErrorDao() {@Overridepublic void disposeJsonArray(JSONArray array) {if (array != null && array.length() > 0) {for (int i = 0; i < array.length(); i++) {try {JSONObject obj = array.getJSONObject(i);ContactsPerson info = new ContactsPerson();info.setUser_account(obj.optString("friend_user_account"));info.setExtend_user_account(obj.optString("friend_extend_user_account"));info.setUser_nickname(obj.optString("user_nickname"));info.setUser_logo(obj.getString("user_logo_200"));info.setName(obj.optString("user_nickname"));newPersons.add(info);} catch (JSONException e) {e.printStackTrace();}}layoutIndex.setBackgroundColor(Color.parseColor("#00ffffff"));// 设置背景颜色txCenter.setVisibility(View.GONE); initPinyin();}}@Overridepublic void disponseJsonArrayFinish() {// TODO Auto-generated method stub}});}}/*** @Title: getPinyin* @Description: 获取每个人的拼音的首字母,并setPinyinName为这个首字母。然后将集合进行排序。再将集合里面的每个首字母和Position的位置存放到selector对象当中* @param * @return void* @throws */@SuppressLint("DefaultLocale")private void initPinyin(){for(int i=0;i<newPersons.size();i++){String name=newPersons.get(i).getUser_nickname();if(name!=null&&!"".equals(name)){String pinyin=ChineseTransferUtils.getPingYin(name);newPersons.get(i).setPinyinName((pinyin.substring(0, 1)).toUpperCase());}}Collections.sort(newPersons); //对联系人进行排序从A-Z(根据pinyinName)for(int j=0;j<indexStr.length;j++){for(int i=0;i<newPersons.size();i++){if(newPersons.get(i).getPinyinName().equals(indexStr[j])){if(!selector.containsKey(indexStr[j])){selector.put(indexStr[j], i);}}else{if(!selector.containsKey("#")){selector.put("#", i);}}}}adapter.notifyDataSetChanged();}}


字母处理工具类:

import java.util.Arrays;import java.util.List;import java.util.TreeSet;import com.slife.gopapa.model.ContactsPerson;import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;/**** * @ClassName: ChineseTransferUtils * @Description: 汉字与拼音以及首字母转换的助手类(pingyin4j的处理) * @author 菲尔普斯 * @date 2015-2-2 上午9:59:21 *  */public class ChineseTransferUtils {/** * @Title: getPingYin * @Description: 得到 汉字的全部拼音 * @param @param src 要转换的对象 * @param @return * @return String * @throws */public static String getPingYin(String src) {char[] stringCharArray = null;stringCharArray = src.toCharArray();String[] stringArray = new String[stringCharArray.length];HanyuPinyinOutputFormat outputFormat = new HanyuPinyinOutputFormat();// 设置输出格式outputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);outputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);outputFormat.setVCharType(HanyuPinyinVCharType.WITH_V);String preString = "";int t0 = stringCharArray.length;try {for (int i = 0; i < t0; i++) {// 判断是否为汉字字符if (java.lang.Character.toString(stringCharArray[i]).matches("[\\u4E00-\\u9FA5]+")) {stringArray = PinyinHelper.toHanyuPinyinStringArray(stringCharArray[i], outputFormat);preString += stringArray[0];} else {preString += java.lang.Character.toString(stringCharArray[i]);}}return preString;} catch (BadHanyuPinyinOutputFormatCombination e1) {e1.printStackTrace();}return preString;}/** * @Title: getHeadChar * @Description: 得到首字母 * @param @param str * @param @return * @return String * @throws */public static String getHeadChar(String str) {String convert = "";char word = str.charAt(0);String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);if (pinyinArray != null) {convert += pinyinArray[0].charAt(0);} else {convert += word;}return convert.toUpperCase();}/** * @Title: getPinYinHeadChar * @Description: 得到中文首字母缩写 * @param @param str * @param @return * @return String * @throws */public static String getPinYinHeadChar(String str) {String convert = "";for (int j = 0; j < str.length(); j++) {char word = str.charAt(j);String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);if (pinyinArray != null) {convert += pinyinArray[0].charAt(0);} else {convert += word;}}return convert.toUpperCase();}/** * @Title: sortIndex * @Description: 字母排序。获取排序后的新数据 * @param @param persons * @param @return * @return String[] * @throws */public static String[] sortIndex(List<ContactsPerson> contacts) {TreeSet<String> set = new TreeSet<String>();String a = null;// 获取初始化数据源中的首字母,添加到set中for (ContactsPerson person : contacts) {String pre = ChineseTransferUtils.getPinYinHeadChar(person.getName()).substring(0, 1);if (65 <= pre.charAt(0) && pre.charAt(0) <= 90 || 97 <= pre.charAt(0) && pre.charAt(0) <= 122) {set.add(pre);} else {set.add("!");}}// 新数组的长度为原数据加上set的大小(set内部已经按字母大小排序,将set里的数据装载到数组中以便往后调用系统拷贝方法)String[] names = new String[contacts.size() + set.size()];int i = 0;for (String string : set) {names[i] = string;i++;}String[] pinYinNames = new String[contacts.size()];for (int j = 0; j < contacts.size(); j++) {contacts.get(j).setPinyinName(a = ChineseTransferUtils.getPingYin(contacts.get(j).getName().toString()));pinYinNames[j] = a + "&^-@";}// 将原数据拷贝到新数据中(将pinYinNames数组中的元素从0下标开始复制元素到names数组)// src:源数组; srcPos:源数组要复制的起始位置; dest:目的数组; destPos:目的数组放置的起始位置;// length:复制的长度。 注意:src and dest都必须是同类型或者可以进行转换类型的数组.System.arraycopy(pinYinNames, 0, names, set.size(), pinYinNames.length);// 复制后自动按照首字母排序Arrays.sort(names, String.CASE_INSENSITIVE_ORDER);// 这个方法得到的数组不是以A为开头的,所以下面的方法就是重新排布用户名的顺序/**************** 重新排布用户名的顺序开始 ************************/String[] newNames = new String[names.length + 1];// 装载以A为首的数组String[] postNames = new String[names.length];// 装载非字母为首的数组int k = 0;int postCount = 0;int temp = 0;for (String pre : names) {if (65 <= pre.charAt(0) && pre.charAt(0) <= 90 || 97 <= pre.charAt(0) && pre.charAt(0) <= 122) {// 字母开头的数组newNames[k] = names[temp];k++;temp++;} else {// 非字母开头的数组postNames[postCount] = names[postCount];temp = ++postCount;}}// 将非字母开头的数组加到字母开头数组的后面for (int j = 0; j < postCount; j++, k++) {newNames[k] = postNames[j];}temp = 0;// 防止数组中有nullfor (String pew : newNames) {if (pew != null)postNames[temp++] = pew;}/**************** 重新排布用户名的顺序结束 ************************/return postNames;}}

最后的实体类:因为实体类需要进行排序,所以重写compareTo方法

import java.io.Serializable;/** * @ClassName: ContactsPerson * @Description: 我的好友实体类和通讯录实体类公用 通讯录联系人的实体类 ,以及好友请求列表的实体类 *  *               status 联系人状态 -2 : 不是手机号 -1 : 是手机但是没有注册啪啪,可邀请 0 : *               是手机且已经注册啪啪,不可添加为好友 1 : 是手机且已经注册啪啪,可添加为好友 2 : 是手机且已经注册啪啪,已经是好友 * @author 菲尔普斯 * @date 2015-1-4 下午2:15:48 *  */public class ContactsPerson implements Serializable,Comparable<ContactsPerson> {/** * @Fields serialVersionUID : TODO(用一句话描述这个变量表示什么) */private static final long serialVersionUID = -8839670785761661380L;public String name;// 中文名public String pinyinName;// 拼音的名字public String phone; // 电话号码public String status;// 是不是好友(状态,默认-1,代表是还未处理)public String user_account; // 啪啪号public String extend_user_account; // 聊天账号public String user_nickname; // 用户昵称public String user_logo; // 用户头像public ContactsPerson() {super();}public ContactsPerson(String name) {super();this.name = name;}public ContactsPerson(String name, String pinyinName) {super();this.name = name;this.pinyinName = pinyinName;}public ContactsPerson(String name, String pinyinName, String phone) {super();this.name = name;this.pinyinName = pinyinName;this.phone = phone;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPinyinName() {return pinyinName;}public void setPinyinName(String pinyinName) {this.pinyinName = pinyinName;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public String getStatus() {return status;}public void setStatus(String status) {this.status = status;}public String getUser_account() {return user_account;}public void setUser_account(String user_account) {this.user_account = user_account;}public String getExtend_user_account() {return extend_user_account;}public void setExtend_user_account(String extend_user_account) {this.extend_user_account = extend_user_account;}public String getUser_nickname() {return user_nickname;}public void setUser_nickname(String user_nickname) {this.user_nickname = user_nickname;}public String getUser_logo() {return user_logo;}public void setUser_logo(String user_logo) {this.user_logo = user_logo;}@Overridepublic int compareTo(ContactsPerson another) {char a=this.getPinyinName().charAt(0);char b=another.getPinyinName().charAt(0);if(Integer.valueOf(a)>Integer.valueOf(b)){return 1;}else{return -1;}}}



0 0
原创粉丝点击