通讯录索引SideBarView
来源:互联网 发布:网络棋牌充值漏洞 编辑:程序博客网 时间:2024/05/01 17:42
废话不多说
首先上效果图:
要做的这样的效果 首先导入一个pinyin包
compile 'com.belerweb:pinyin4j:2.5.1'
接下来做一些准备工作吧
主页面的Xml
里面用到了自定义的 SideBarView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:poplar="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#d5d5d5"> <TextView android:id="@+id/tv_friends_toolbar" android:layout_width="match_parent" android:layout_height="52dp" android:background="#41c2fc" android:gravity="center" android:text="通讯录" android:textColor="#fff" android:textSize="20sp"/> <ListView android:id="@+id/lv_friends_listView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tv_friends_toolbar"/> <com.cooltone.demo.SideBarView android:id="@+id/sbv_friends_bar" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tv_friends_toolbar" android:layout_marginBottom="5dp" android:layout_marginTop="5dp" poplar:additionalTipOffset="40dp" poplar:fontColor="#6e6e6e" poplar:maxBezierHeight="150dp" poplar:maxBezierWidth="180dp" poplar:maxFontSize="60" poplar:minFontSize="32" poplar:tipFontColor="#41c2fc" poplar:tipFontSize="72" poplar:widthOffset="15dp"/> <TextView android:id="@+id/tv_friends_center" android:layout_width="100dp" android:layout_height="100dp" android:layout_below="@id/tv_friends_toolbar" android:layout_centerInParent="true" android:background="@drawable/sidebar_background" android:gravity="center" android:text="A" android:textColor="#fff" android:textSize="36sp" android:visibility="gone"/></RelativeLayout>
上面包红没关系啊 一步步来,记得一会自定义View 要换包名。接下来是listView 条目 布局
<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/tv_friend_title" android:layout_width="match_parent" android:layout_height="20dp" android:background="#919191" android:gravity="center_vertical" android:paddingLeft="20dp" android:text="A" android:textSize="14sp"/> <TextView android:id="@+id/tv_friend_name" android:layout_width="match_parent" android:layout_height="60dp" android:background="#fff" android:gravity="center_vertical" android:paddingLeft="20dp" android:text="宋江" android:textColor="#00f" android:textSize="16sp"/></LinearLayout>接下来什么呢 ,在drawable文件下 建一个背景吧 sidebar_background
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <!-- 通讯录 --> <corners android:radius="25dp"/> <solid android:color="#66000000"/></shape>
接下来就是重要人物出场了
建 SideBarView 继承 View 写我们的索引控件
里面的东西自己想研究下的话, 可以自己研究,本人也不是很懂,用了贝塞尔曲线
/** * 作者:CoolTone * 描述:右侧导航栏字母列表 */public class SideBarView extends View { private OnTouchLetterChangedListener mListener; public interface OnTouchLetterChangedListener { void onTouchLetterChanged(String letter); } public void setOnTouchLetterChangedListener(OnTouchLetterChangedListener listener) { this.mListener = listener; } // 向右偏移多少画字符, default 30 float mWidthOffset = 30.0f; // 最小字体大小 int mMinFontSize = 24; // 最大字体大小 int mMaxFontSize = 48; // 提示字体大小 int mTipFontSize = 52; // 提示字符的额外偏移 float mAdditionalTipOffset = 20.0f; // 贝塞尔曲线控制的高度 float mMaxBezierHeight = 150.0f; // 贝塞尔曲线单侧宽度 float mMaxBezierWidth = 240.0f; // 贝塞尔曲线单侧模拟线量 int mMaxBezierLines = 32; // 列表字符颜色 int mFontColor = 0xffffffff; // 提示字符颜色 int mTipFontColor = 0xffd33e48; private final String[] ConstChar = {"#", "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"}; int mChooseIndex = -1; Paint mPaint = new Paint(); PointF mTouch = new PointF(); PointF[] mBezier1; PointF[] mBezier2; float mLastOffset[] = new float[ConstChar.length]; // 记录每一个字母的x方向偏移量, 数字<=0 PointF mPointF = new PointF(); Scroller mScroller; boolean mAnimating = false; float mAnimationOffset; boolean mHideAnimation = false; int mAlpha = 255; Handler mHideWaitingHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { mHideAnimation = true; mAnimating = false; SideBarView.this.invalidate(); return; } super.handleMessage(msg); } }; public SideBarView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initData(context, attrs); } public SideBarView(Context context, AttributeSet attrs) { super(context, attrs); initData(context, attrs); } public SideBarView(Context context) { super(context); initData(null, null); } private void initData(Context context, AttributeSet attrs) { if (context != null && attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FancyIndexer, 0, 0); mWidthOffset = a.getDimension(R.styleable.FancyIndexer_widthOffset, mWidthOffset); // 最小 mMinFontSize = a.getInteger(R.styleable.FancyIndexer_minFontSize, mMinFontSize); // 最大 mMaxFontSize = a.getInteger(R.styleable.FancyIndexer_maxFontSize, mMaxFontSize); mTipFontSize = a.getInteger(R.styleable.FancyIndexer_tipFontSize, mTipFontSize); mMaxBezierHeight = a.getDimension(R.styleable.FancyIndexer_maxBezierHeight, mMaxBezierHeight); mMaxBezierWidth = a.getDimension(R.styleable.FancyIndexer_maxBezierWidth, mMaxBezierWidth); mMaxBezierLines = a.getInteger(R.styleable.FancyIndexer_maxBezierLines, mMaxBezierLines); mAdditionalTipOffset = a.getDimension(R.styleable.FancyIndexer_additionalTipOffset, mAdditionalTipOffset); // 颜色 mFontColor = a.getColor(R.styleable.FancyIndexer_fontColor, mFontColor); // 提示颜色 mTipFontColor = a.getColor(R.styleable.FancyIndexer_tipFontColor, mTipFontColor); a.recycle(); } mScroller = new Scroller(getContext()); mTouch.x = 0; mTouch.y = -10 * mMaxBezierWidth; mBezier1 = new PointF[mMaxBezierLines]; mBezier2 = new PointF[mMaxBezierLines]; calculateBezierPoints(); } @Override protected void onDraw(Canvas canvas) { // 控件宽高 int height = getHeight(); int width = getWidth(); // 单个字母高度 float singleHeight = height / (float) ConstChar.length; int workHeight = 0; if (mAlpha == 0) return; mPaint.reset(); int saveCount = 0; if (mHideAnimation) { saveCount = canvas.save(); canvas.saveLayerAlpha(0, 0, width, height, mAlpha, Canvas.ALL_SAVE_FLAG); } for (int i = 0; i < ConstChar.length; i++) { mPaint.setColor(mFontColor); mPaint.setAntiAlias(true); float xPos = width - mWidthOffset; float yPos = workHeight + singleHeight / 2; // float adjustX = adjustXPos( yPos, i == mChooseIndex ); // 根据当前字母y的位置计算得到字体大小 int fontSize = adjustFontSize(i, yPos); mPaint.setTextSize(fontSize); // 添加一个字母的高度 workHeight += singleHeight; // 绘制字母 drawTextInCenter(canvas, ConstChar[i], xPos + ajustXPosAnimation(i, yPos), yPos); // 绘制的字母和当前触摸到的一致, 绘制红色被选中字母 if (i == mChooseIndex) { mPaint.setColor(mTipFontColor); mPaint.setFakeBoldText(true); mPaint.setTextSize(mTipFontSize); yPos = mTouch.y; float pos = 0; if (mAnimating || mHideAnimation) { pos = mPointF.x; yPos = mPointF.y; } else { pos = xPos + ajustXPosAnimation(i, yPos) - mAdditionalTipOffset; mPointF.x = pos; mPointF.y = yPos; } drawTextInCenter(canvas, ConstChar[i], pos, yPos); } mPaint.reset(); } if (mHideAnimation) { canvas.restoreToCount(saveCount); } } /** * @param canvas 画板 * @param string 被绘制的字母 * @param xCenter 字母的中心x方向位置 * @param yCenter 字母的中心y方向位置 */ private void drawTextInCenter(Canvas canvas, String string, float xCenter, float yCenter) { Paint.FontMetrics fm = mPaint.getFontMetrics(); float fontHeight = mPaint.getFontSpacing(); float drawY = yCenter + fontHeight / 2 - fm.descent; if (drawY < -fm.ascent - fm.descent) drawY = -fm.ascent - fm.descent; if (drawY > getHeight()) drawY = getHeight(); mPaint.setTextAlign(Paint.Align.CENTER); canvas.drawText(string, xCenter, drawY, mPaint); } private int adjustFontSize(int i, float yPos) { // 根据水平方向偏移量计算出一个放大的字号 float adjustX = Math.abs(ajustXPosAnimation(i, yPos)); int adjustSize = (int) ((mMaxFontSize - mMinFontSize) * adjustX / mMaxBezierHeight) + mMinFontSize; return adjustSize; } /** * x 方向的向左偏移量 * * @param i 当前字母的索引 * @param yPos y方向的初始位置 * @return */ private float ajustXPosAnimation(int i, float yPos) { float offset; if (this.mAnimating || this.mHideAnimation) { // 正在动画中或在做隐藏动画 offset = mLastOffset[i]; if (offset != 0.0f) { offset += this.mAnimationOffset; if (offset > 0) offset = 0; } } else { // 根据当前字母y方向位置, 计算水平方向偏移量 offset = adjustXPos(yPos); // 当前触摸的x方向位置 float xPos = mTouch.x; float width = getWidth() - mWidthOffset; width = width - 60; // 字母绘制时向左偏移量 进行修正, offset需要是<=0的值 if (offset != 0.0f && xPos > width) offset += (xPos - width); if (offset > 0) offset = 0; mLastOffset[i] = offset; } return offset; } private float adjustXPos(float yPos) { float dis = yPos - mTouch.y; // 字母y方向位置和触摸时y值坐标的差值, 距离越小, 得到的水平方向偏差越大 if (dis > -mMaxBezierWidth && dis < mMaxBezierWidth) { // 在2个贝赛尔曲线宽度范围以内 (一个贝赛尔曲线宽度是指一个山峰的一边) // 第一段 曲线 if (dis > mMaxBezierWidth / 4) { for (int i = mMaxBezierLines - 1; i > 0; i--) { // 从下到上, 逐个计算 if (dis == -mBezier1[i].y) // 落在点上 return mBezier1[i].x; // 如果距离dis落在两个贝塞尔曲线模拟点之间, 通过三角函数计算得到当前dis对应的x方向偏移量 if (dis > -mBezier1[i].y && dis < -mBezier1[i - 1].y) { return (dis + mBezier1[i].y) * (mBezier1[i - 1].x - mBezier1[i].x) / (-mBezier1[i - 1].y + mBezier1[i].y) + mBezier1[i].x; } } return mBezier1[0].x; } // 第三段 曲线, 和第一段曲线对称 if (dis < -mMaxBezierWidth / 4) { for (int i = 0; i < mMaxBezierLines - 1; i++) { // 从上到下 if (dis == mBezier1[i].y) // 落在点上 return mBezier1[i].x; // 如果距离dis落在两个贝塞尔曲线模拟点之间, 通过三角函数计算得到当前dis对应的x方向偏移量 if (dis > mBezier1[i].y && dis < mBezier1[i + 1].y) { return (dis - mBezier1[i].y) * (mBezier1[i + 1].x - mBezier1[i].x) / (mBezier1[i + 1].y - mBezier1[i].y) + mBezier1[i].x; } } return mBezier1[mMaxBezierLines - 1].x; } // 第二段 峰顶曲线 for (int i = 0; i < mMaxBezierLines - 1; i++) { if (dis == mBezier2[i].y) return mBezier2[i].x; // 如果距离dis落在两个贝塞尔曲线模拟点之间, 通过三角函数计算得到当前dis对应的x方向偏移量 if (dis > mBezier2[i].y && dis < mBezier2[i + 1].y) { return (dis - mBezier2[i].y) * (mBezier2[i + 1].x - mBezier2[i].x) / (mBezier2[i + 1].y - mBezier2[i].y) + mBezier2[i].x; } } return mBezier2[mMaxBezierLines - 1].x; } return 0.0f; } @Override public boolean dispatchTouchEvent(MotionEvent event) { final int action = event.getAction(); final float y = event.getY(); final int oldmChooseIndex = mChooseIndex; final OnTouchLetterChangedListener listener = mListener; final int c = (int) (y / getHeight() * ConstChar.length); switch (action) { case MotionEvent.ACTION_DOWN: if (this.getWidth() > mWidthOffset) { if (event.getX() < this.getWidth() - mWidthOffset) return false; } mHideWaitingHandler.removeMessages(1); mScroller.abortAnimation(); mAnimating = false; mHideAnimation = false; mAlpha = 255; mTouch.x = event.getX(); mTouch.y = event.getY(); if (oldmChooseIndex != c && listener != null) { if (c > 0 && c < ConstChar.length) { listener.onTouchLetterChanged(ConstChar[c]); mChooseIndex = c; } } invalidate(); break; case MotionEvent.ACTION_MOVE: mTouch.x = event.getX(); mTouch.y = event.getY(); invalidate(); if (oldmChooseIndex != c && listener != null) { if (c >= 0 && c < ConstChar.length) { listener.onTouchLetterChanged(ConstChar[c]); mChooseIndex = c; } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mTouch.x = event.getX(); mTouch.y = event.getY(); mScroller.startScroll(0, 0, (int) mMaxBezierHeight, 0, 500); mAnimating = true; postInvalidate(); break; } return true; } @Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { if (mAnimating) { float x = mScroller.getCurrX(); mAnimationOffset = x; } else if (mHideAnimation) { mAlpha = 255 - mScroller.getCurrX(); } invalidate(); } else if (mScroller.isFinished()) { if (mAnimating) { mHideWaitingHandler.sendEmptyMessage(1); } else if (mHideAnimation) { mHideAnimation = false; this.mChooseIndex = -1; mTouch.x = -10000; mTouch.y = -10000; } } } /** * 计算出所有贝塞尔曲线上的点 * 个数为 mMaxBezierLines * 2 = 64 */ private void calculateBezierPoints() { PointF mStart = new PointF(); // 开始点 PointF mEnd = new PointF(); // 结束点 PointF mControl = new PointF(); // 控制点 // 计算第一段红色部分 贝赛尔曲线的点 // 开始点 mStart.x = 0.0f; mStart.y = -mMaxBezierWidth; // 控制点 mControl.x = 0.0f; mControl.y = -mMaxBezierWidth / 2; // 结束点 mEnd.x = -mMaxBezierHeight / 2; mEnd.y = -mMaxBezierWidth / 4; mBezier1[0] = new PointF(); mBezier1[mMaxBezierLines - 1] = new PointF(); mBezier1[0].set(mStart); mBezier1[mMaxBezierLines - 1].set(mEnd); for (int i = 1; i < mMaxBezierLines - 1; i++) { mBezier1[i] = new PointF(); mBezier1[i].x = calculateBezier(mStart.x, mEnd.x, mControl.x, i / (float) mMaxBezierLines); mBezier1[i].y = calculateBezier(mStart.y, mEnd.y, mControl.y, i / (float) mMaxBezierLines); } // 计算第二段蓝色部分 贝赛尔曲线的点 mStart.y = -mMaxBezierWidth / 4; mStart.x = -mMaxBezierHeight / 2; mControl.y = 0.0f; mControl.x = -mMaxBezierHeight; mEnd.y = mMaxBezierWidth / 4; mEnd.x = -mMaxBezierHeight / 2; mBezier2[0] = new PointF(); mBezier2[mMaxBezierLines - 1] = new PointF(); mBezier2[0].set(mStart); mBezier2[mMaxBezierLines - 1].set(mEnd); for (int i = 1; i < mMaxBezierLines - 1; i++) { mBezier2[i] = new PointF(); mBezier2[i].x = calculateBezier(mStart.x, mEnd.x, mControl.x, i / (float) mMaxBezierLines); mBezier2[i].y = calculateBezier(mStart.y, mEnd.y, mControl.y, i / (float) mMaxBezierLines); } } /** * 贝塞尔曲线核心算法 * * @param start * @param end * @param control * @param val * @return 公式及动图, 维基百科: https://en.wikipedia.org/wiki/B%C3%A9zier_curve * 中文可参考此网站: http://blog.csdn.net/likendsl/article/details/7852658 */ private float calculateBezier(float start, float end, float control, float val) { float t = val; float s = 1 - t; float ret = start * s * s + 2 * control * s * t + end * t * t; return ret; }}之后来,当然是善后啦 因为里面会包红呀!
接下来在values里面创建attrs文件
<!-- 通讯录 --> <declare-styleable name="FancyIndexer"> <attr name="widthOffset" format="dimension"/> <attr name="minFontSize" format="integer"/> <attr name="maxFontSize" format="integer"/> <attr name="tipFontSize" format="integer"/> <attr name="maxBezierHeight" format="dimension"/> <attr name="maxBezierWidth" format="dimension"/> <attr name="maxBezierLines" format="integer"/> <attr name="additionalTipOffset" format="dimension"/> <attr name="fontColor" format="color"/> <attr name="tipFontColor" format="color"/> </declare-styleable>
做完这些估计就不会包红了吧! 因为我这写完了没有什么红 所以我也记不清了!
这里因为要给好友列表排序 当然少不了拼音 和 实体类
FriendEntity实体类
/** * 作者: CoolTone * 描述: 好友列表实体类 */public class FriendEntity implements Comparable<FriendEntity> { private String name; private String pinyin; public FriendEntity() { } @Override public int compareTo(FriendEntity another) { return pinyin.compareTo(another.pinyin); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPinyin() { return pinyin; } public void setPinyin(String pinyin) { this.pinyin = pinyin; } @Override public String toString() { return "FriendEntity{" + "name='" + name + '\'' + ", pinyin='" + pinyin + '\'' + '}'; }}
对于上面要说一句 不要忘了 很重要哦!排序用的
@Override public int compareTo(FriendEntity another) { return pinyin.compareTo(another.pinyin); }接下来 PinyinUtil 帮助类
/** * 作者: CoolTone * 描述: 通讯录 拼音 帮助类 */public class PinyinUtil { /** * 根据汉字获取对应的拼音 * * @param str * @return */ public static String getPinyin(String str) { // 设置输出配置 HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); // 设置大写 format.setCaseType(HanyuPinyinCaseType.UPPERCASE); // 设置不需要音调 format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); StringBuilder sb = new StringBuilder(); // 获取字符数组 char[] charArray = str.toCharArray(); for (int i = 0; i < charArray.length; i++) { char c = charArray[i]; if (Character.isWhitespace(c)) { // 如果是空格, 跳过当前的循环 continue; } if (c > 128 || c < -127) { // 可能是汉字 try { // 根据字符获取对应的拼音 String s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0]; sb.append(s); } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } } else { // ~!@#$%^&*()_+{}|:"<>?\/1234567890 // 不需要转换, 直接添加 // 根据字符获取对应的拼音 sb.append(c); } } return sb.toString(); }}这个工具里面有注释就不多说了!
接下来是Adapter的工具类 因为本人比较喜欢用ListView 所以这个父类的Adapter 很有用
/** * 作者: CoolTone * 描述: 父类Adapter */public abstract class SecondAdapter<T> extends BaseAdapter { private List<T> mData; // 数据信息 private LayoutInflater mInflater;// 填充布局 private Context mContext; // 上下文 public SecondAdapter(Context context) { mData = new ArrayList<>(); mInflater = LayoutInflater.from(context); mContext = context; } @Override public int getCount() { return mData.size(); } @Override public T getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } public List<T> getData() { return mData; } public LayoutInflater getInflater() { return mInflater; } public Context getContext() { return mContext; } /** * 添加集合 */ public void addAll(List<T> data) { mData.addAll(data); notifyDataSetChanged(); } /** * 清除集合 */ public void clear() { mData.clear(); notifyDataSetChanged(); }}然后就是写 FriendAdapter 主要赋值嘛
这里面要做一些逻辑处理:
比如判断是否是拼音,是否拼音的第一位等等
/** * 作者: CoolTone * 描述: 数据Adapter */public class FriendAdapter extends SecondAdapter<FriendEntity> { public FriendAdapter(Context context) { super(context); } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = getInflater().inflate(R.layout.item_friend, null); } ItemViewHolder holder = (ItemViewHolder) convertView.getTag(); if (holder == null) { holder = new ItemViewHolder(convertView); convertView.setTag(holder); } holder.bindView(position); return convertView; } class ItemViewHolder { private final TextView mName; private final TextView mTitle; public ItemViewHolder(View itemView) { mName = ((TextView) itemView.findViewById(R.id.tv_friend_name)); mTitle = (TextView) itemView.findViewById(R.id.tv_friend_title); } public void bindView(int position) { FriendEntity friend = getData().get(position); String pinyin = friend.getPinyin(); if (!pinyin.isEmpty()) { String s = String.valueOf(pinyin.charAt(0)); if ((s.charAt(0) <= 'Z' && s.charAt(0) >= 'A') || (s.charAt(0) <= 'z' && s.charAt(0) >= 'a')) { oneYesLetter(position, friend, s); } else { oneNoLetter(position, friend, s); } } } // 第一位是否是字母 Y private void oneYesLetter(int position, FriendEntity friend, String currentLetter) { String indexStr = null; if (position == 0) { // 如果是第一位 indexStr = currentLetter; } else { // 获取上一个拼音 String preLetter = getData().get(position - 1).getPinyin().charAt(0) + ""; if (!TextUtils.equals(currentLetter, preLetter)) { indexStr = currentLetter; // 当跟上一个不同时, 赋值, 显示 } } mTitle.setVisibility(indexStr == null ? View.GONE : View.VISIBLE); mTitle.setText(indexStr); mName.setText(friend.getName()); } // 第一位是否是字母 N private void oneNoLetter(int position, FriendEntity friend, String currentLetter) { String indexStr = null; if (position == 0) { // 如果是第一位 indexStr = currentLetter; } mTitle.setVisibility(indexStr == null ? View.GONE : View.VISIBLE); mTitle.setText("#"); mName.setText(friend.getName()); } }}
这就完了! 但是还有写主程序呀!你逗我
/** * 作者: CoolTone * 描述: 好友列表 */public class MainActivity extends AppCompatActivity implements SideBarView.OnTouchLetterChangedListener { private ArrayList<FriendEntity> mFriends; private FriendAdapter mAdapter; private ListView mListView; private SideBarView mSideView; private TextView mLetter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); setListener(); } private void setListener() { mSideView.setOnTouchLetterChangedListener(this); } private void initData() { mFriends = new ArrayList<>(); mAdapter = new FriendAdapter(this); mListView.setAdapter(mAdapter); String[] names = new String[]{"逗霸最伟大", "鬧夠了就去吃藥", "破灭等于拥有", "贪恋剧情小丑", "若隐若现", "我叫意志力", "龍飛鳳舞", "别拿爱情说宿命", "青春帅气先森", "年华仅是无效信", "年华仅是无效信", "中国好同桌", "折磨", "马子大", "不哭的理由", "唱歌跑调那叫范", "爱4太给力", "你与寂寞有染",}; for (int i = 0; i < names.length; i++) { FriendEntity friend = new FriendEntity(); friend.setName(names[i]); friend.setPinyin(PinyinUtil.getPinyin(names[i])); mFriends.add(friend); } Collections.sort(mFriends); // 这里千万不能忘 mAdapter.addAll(mFriends); mAdapter.notifyDataSetChanged(); } private void initView() { mListView = ((ListView) findViewById(R.id.lv_friends_listView)); mSideView = ((SideBarView) findViewById(R.id.sbv_friends_bar)); mLetter = ((TextView) findViewById(R.id.tv_friends_center)); } @Override public void onTouchLetterChanged(String letter) {// showLetter(letter); if (!mFriends.isEmpty()) { for (int i = 0; i < mFriends.size(); i++) { FriendEntity friend = mFriends.get(i); String s = String.valueOf(friend.getPinyin().charAt(0)); if (TextUtils.equals(s, letter)) { // 匹配成功, 中断循环, 跳转到i位置 mListView.setSelection(i); break; } } } }// /**// * 显示字母提示// *// * @param letter// */// protected void showLetter(String letter) {// mLetter.setVisibility(View.VISIBLE);// mLetter.setText(letter);//// // 取消掉刚刚所有的演示操作// mHandler.removeCallbacksAndMessages(null);// mHandler.postDelayed(new Runnable() {// @Override// public void run() {// // 隐藏// mCenter.setVisibility(View.GONE);// }// }, 500);// }}
嗯哼大功告成了吧! 反正我已经晕了 应该没有丢下东西才对
注意事项:好友列表数据 在给Adapter 添加数据之前千万不要忘了 Collections.sort(); 排序
for (int i = 0; i < names.length; i++) { FriendEntity friend = new FriendEntity(); friend.setName(names[i]); friend.setPinyin(PinyinUtil.getPinyin(names[i])); mFriends.add(friend);}Collections.sort(mFriends); // 这里千万不能忘mAdapter.addAll(mFriends);mAdapter.notifyDataSetChanged();
Demo下载地址:http://download.csdn.net/detail/qq_35352552/9797827
1 0
- 通讯录索引SideBarView
- 高仿微信通讯录,解决SideBarView下标越界问题
- android 通讯录+首字母索引
- 通讯录 之 快速索引
- 自定义通讯录字母索引
- 自定义通讯录索引
- UITableView 类似通讯录的索引
- 通讯录侧滑索引菜单
- AddressBook通讯录右边索引条
- android 通讯录侧边快速索引
- Android首字母索引排序通讯录
- Android 自定义 View 实现通讯录字母索引(仿微信通讯录)
- Android 自定义 View 实现通讯录字母索引(仿微信通讯录)
- android仿微信通讯录字母索引控件
- Android ListView字母索引(仿微信通讯录列表)
- 通讯录索引条的功能实现
- 通讯录联系人,带右边索引案例
- 【笔记】通讯录使用侧栏字母索引
- 大数据 hadoop2.6.0 高可用集群搭建(HA集群搭建)--亲测可用,入门必备
- jsp 9大内置对象
- Android Study之图解配置adb
- webstorm使用破解
- 【解决】SecureCRT 中文乱码问题
- 通讯录索引SideBarView
- 简单的Gulp配置
- Android学习<第一节:初始Android>
- Win7:修改注册表来更改“桌面”、“我的文档”、“收藏夹”的位置
- bat处理中添加%errorlevel%在进程的后面获取进程退出码
- 哪门编程语言工资最高?YouWorth和StackOverFlow的数据来说话
- 登陆验证(过滤器)
- C/C++精度问题
- python变量赋值(可变与不可变)