自定义控件之A-Z快速检索QuickIndexBar
来源:互联网 发布:商城建站java 编辑:程序博客网 时间:2024/05/01 12:36
---------快速检索--------------
1.应用场景:联系人,好友列表,商品等列表的快速定位和搜索
2.实现逻辑:
a.右边是自定义QuickIndexBar,它能获取触摸它的时候当前所触摸到的字母;
绘制文本x坐标: width/2;
绘制文本y坐标: 格子高度的一半 + 文本高度的一半 + position*格子高度
计算触摸点对应的字母:根据触摸点的y坐标除以cellHeight,得到的值就是字母对应的索引;
b.左边是listview,它根据当前触摸的字母,去自己列表找首字母和触摸字母相同的那个
item,然后让item放置到屏幕顶端(setSelection(position));
c.需要用到获取汉字的拼音,借助类库pinyin4j.jar实现;
QuickIndexBar:
/* * @Copyright (c) tianchenglin * @Author TCL * @Date 2016.6.22 */package com.study.tcl.quickindex.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/** * Created by TCL on 2016/6/22. */public class QuickIndexBar extends View { private String[] indexArr = {"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 Paint mPaint; private int mWidth; private int mHeight; float mSingleLetterHeight; private onTouchLetterListener mOnTouchLetterListener;//按住哪个字符的监听 private int mLastLetterIndex = -1;//最后一次按住的字符 public QuickIndexBar(Context context) { super(context); init(); } public QuickIndexBar(Context context, AttributeSet attrs) { super(context, attrs); init(); } public QuickIndexBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public void setOnTouchLetterListener(onTouchLetterListener onTouchLetterListener) { mOnTouchLetterListener = onTouchLetterListener; } private void init() { mPaint = new Paint(); mPaint.setAntiAlias(true);//抗锯齿 mPaint.setTextSize(20); mPaint.setTextAlign(Paint.Align.CENTER);//设置文本的起点是文字边框底边的中心 } @Override protected void onDraw(Canvas canvas) { for (int i = 0; i < indexArr.length; i++) { float xPosition = mWidth / 2;//要画的x坐标// float yPosition = mSingleLetterHeight * i + mSingleLetterHeight;//要画的y坐标 //y坐标 = 单个字符高度/2+文本高度/2+第几个字符 float yPosition = mSingleLetterHeight / 2 + mPaint.measureText(indexArr[i], 0, 1) / 2 + i * mSingleLetterHeight;// //字符按下变色// if (i == mLastLetterIndex) {// mPaint.setColor(Color.TRANSPARENT);// canvas.drawText(indexArr[i], xPosition, yPosition, mPaint);// } mPaint.setColor(i == mLastLetterIndex ? Color.WHITE : Color.RED); canvas.drawText(indexArr[i], xPosition, yPosition, mPaint); } super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: this.setBackgroundColor(Color.BLUE); float y = event.getY(); int index = (int) (y / mSingleLetterHeight);//得到字符对应的索引 if (mLastLetterIndex != index) { //安全性检查 if (index >= 0 && index < indexArr.length) { if (mOnTouchLetterListener != null) { mOnTouchLetterListener.onTouchLetter(indexArr[index]); } } Log.i("index", index + ""); Log.i("letter", indexArr[index]); } mLastLetterIndex = index; break; case MotionEvent.ACTION_UP: this.setBackgroundColor(Color.WHITE); //重置 mLastLetterIndex = -1; break; } invalidate();//引起重绘 return true;//自己处理 } public interface onTouchLetterListener { void onTouchLetter(String letter); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = getMeasuredWidth();//获取QuickIndexBar宽度 mHeight = getMeasuredHeight();//获取QuickIndexBar高度 mSingleLetterHeight = getMeasuredHeight() * 1f / indexArr.length;//获取一个字符所占高度 }}
MainActivity:
/* * @Copyright (c) tianchenglin * @Author TCL * @Date 2016.6.22 */package com.study.tcl.quickindex;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.util.Log;import android.view.View;import android.view.Window;import android.widget.ListView;import android.widget.TextView;import com.study.tcl.quickindex.adapter.MyListAdapter;import com.study.tcl.quickindex.domain.Friend;import com.study.tcl.quickindex.utils.PinYinUtils;import com.study.tcl.quickindex.view.QuickIndexBar;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class MainActivity extends Activity { private QuickIndexBar mQuickIndexBar; private ListView mListView; private List<Friend> friends; private TextView mCurrentLetter; private Handler mHandler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); mQuickIndexBar = (QuickIndexBar) findViewById(R.id.quickIndexBar); mListView = (ListView) findViewById(R.id.listView); mCurrentLetter = (TextView) findViewById(R.id.currentLetter); //1.准备数据 fillList(); //2.对集合进行排序 Collections.sort(friends); //3.设置adapter mListView.setAdapter(new MyListAdapter(this, friends)); mQuickIndexBar.setOnTouchLetterListener(new QuickIndexBar.onTouchLetterListener() { @Override public void onTouchLetter(String letter) {// Log.e("letter", letter); //根据当前触摸的字母,去集合中找哪个item for (int i = 0; i < friends.size(); i++) { String firstLetter = friends.get(i).getPinyin().charAt(0) + ""; if (letter.equals(firstLetter)) { //将当前item放到屏幕顶端 mListView.setSelection(i); break;//找到第一个就行了 } } //显示当前显示的字母 mCurrentLetter.setVisibility(View.VISIBLE); mCurrentLetter.setText(letter); //先移除之前的任务 mHandler.removeCallbacksAndMessages(null); mHandler.postDelayed(new Runnable() { @Override public void run() { mCurrentLetter.setVisibility(View.GONE); } }, 1500); } }); Log.e("pinyin", PinYinUtils.getPinYin("田成琳")); } private void fillList() { friends = new ArrayList<Friend>(); // 虚拟数据 friends.add(new Friend("李伟")); friends.add(new Friend("张三")); friends.add(new Friend("阿三")); friends.add(new Friend("阿四")); friends.add(new Friend("段誉")); friends.add(new Friend("段正淳")); friends.add(new Friend("张三丰")); friends.add(new Friend("陈坤")); friends.add(new Friend("林俊杰1")); friends.add(new Friend("陈坤2")); friends.add(new Friend("王二a")); friends.add(new Friend("林俊杰a")); friends.add(new Friend("张四")); friends.add(new Friend("林俊杰")); friends.add(new Friend("王二")); friends.add(new Friend("王二b")); friends.add(new Friend("赵四")); friends.add(new Friend("杨坤")); friends.add(new Friend("赵子龙")); friends.add(new Friend("杨坤1")); friends.add(new Friend("李伟1")); friends.add(new Friend("宋江")); friends.add(new Friend("宋江1")); friends.add(new Friend("李伟3")); }}
MyListAdapter:
/* * @Copyright (c) tianchenglin * @Author TCL * @Date 2016.6.23 */package com.study.tcl.quickindex.adapter;import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;import com.study.tcl.quickindex.R;import com.study.tcl.quickindex.domain.Friend;import com.study.tcl.quickindex.utils.PinYinUtils;import java.util.List;/** * Created by TCL on 2016/6/23. */public class MyListAdapter extends BaseAdapter { private List<Friend> mFriends; private Context mContext; public MyListAdapter(Context context, List<Friend> friends) { mFriends = friends; mContext = context; } @Override public int getCount() { return mFriends.size(); } @Override public Object getItem(int position) { return mFriends.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = View.inflate(mContext, R.layout.adapter_friend, null); holder = new ViewHolder(); holder.tv_letter = (TextView) convertView.findViewById(R.id.tv_letter); holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } Friend friend = mFriends.get(position); String currentWord = PinYinUtils.getPinYin(friend.getName()).charAt(0) + "";//此处注意异常 if (position > 0) { //获取上一个item首字母 String lastWord = mFriends.get(position - 1).getPinyin().charAt(0) + ""; //拿当前的首字母和上一个比较 if (currentWord.equals(lastWord)) { //说明首字母相同 holder.tv_letter.setVisibility(View.GONE); } else { holder.tv_letter.setVisibility(View.VISIBLE); holder.tv_letter.setText(currentWord); } } else { holder.tv_letter.setVisibility(View.VISIBLE); holder.tv_letter.setText(currentWord); } holder.tv_name.setText(friend.getName()); return convertView; } static class ViewHolder { TextView tv_letter; TextView tv_name; }}PinyinUtils:
/* * @Copyright (c) tianchenglin * @Author TCL * @Date 2016.6.23 */package com.study.tcl.quickindex.utils;import android.text.TextUtils;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.exception.BadHanyuPinyinOutputFormatCombination;/** * Created by TCL on 2016/6/23. */public class PinYinUtils { /** * 获取文字拼音,会消耗一定资源,不应该被频繁调用 * * @param chinese * @return */ public static String getPinYin(String chinese) { if (!TextUtils.isEmpty(chinese)) { //1.由于只能对单个汉子进行转化,所以需要将字符串转化成字符数组,然后对每个字符进行转化,最后拼接 char[] chars = chinese.toCharArray(); StringBuilder sb = new StringBuilder(); HanyuPinyinOutputFormat hanyuPinyinOutputFormat = new HanyuPinyinOutputFormat(); hanyuPinyinOutputFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);//设置转化的拼音是大写字母 hanyuPinyinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);//没有声调// hanyuPinyinOutputFormat.setVCharType(); for (int i = 0; i < chars.length; i++) { //2.过滤空格 if (Character.isSpaceChar(chars[i])) { continue; } //3.判断是否是汉字,汉字占两个字节,一个字节范围是-128~127 if (chars[i] > 127) { //可能是汉字 try { String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(chars[i], hanyuPinyinOutputFormat); if (pinyinArray != null) { sb.append(pinyinArray[0]);//取第0个 } else { //没有找到拼音,可能不是汉字,则忽略 } } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) { badHanyuPinyinOutputFormatCombination.printStackTrace(); //说明转化失败,不是汉字,则忽略 } } else { //这些字符能排序,不能获取拼音 sb.append(chars[i]); } } return sb.toString(); } return null; }}
Bean(Friend):
/* * @Copyright (c) tianchenglin * @Author TCL * @Date 2016.6.23 */package com.study.tcl.quickindex.domain;import com.study.tcl.quickindex.utils.PinYinUtils;/** * Created by TCL on 2016/6/23. */public class Friend implements Comparable<Friend> { private String name; private String pinyin; public Friend(String name) { this.name = name; //一开始就设置好拼音 setPinyin(PinYinUtils.getPinYin(name)); } 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 int compareTo(Friend another) { return getPinyin().compareTo(another.getPinyin()); }}
activity_main:
<?xml version="1.0" encoding="utf-8"?><!-- ~ @Copyright (c) tianchenglin ~ @Author TCL ~ @Date 2016.6.22 --><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="com.study.tcl.quickindex.MainActivity"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> <!--android:background="#B51421"--> <com.study.tcl.quickindex.view.QuickIndexBar android:id="@+id/quickIndexBar" android:layout_width="30dp" android:layout_height="match_parent" android:layout_alignParentRight="true"> </com.study.tcl.quickindex.view.QuickIndexBar> <TextView android:id="@+id/currentLetter" android:layout_width="100dp" android:layout_height="100dp" android:layout_centerInParent="true" android:background="@drawable/bg" android:gravity="center" android:textColor="#ffffff" android:visibility="gone" android:textSize="50dp"/></RelativeLayout>
运行结果:
0 0
- 自定义控件之A-Z快速检索QuickIndexBar
- 自定义控件之快速索引QuickIndexBar
- 安卓 简单的 联系人快速检索控件QuickIndexBar实现
- 快速检索(一)之自定义快速检索QiuckIndexBar控件
- Android自定义控件之实现快速检索
- 自定义控件--快速检索
- Android快速索引条控件QuickIndexBar
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
- 自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
- 自定义View的尝试-A到Z快速搜索sideBar
- Android自定义控件---联系人列表A-Z排序
- Android自定义控件---联系人列表A-Z排序
- 自定义拼音检索控件
- Android之联系人A~Z快速索引效果
- Android自定义控件--A~Z列表侧边栏索引控件及相关开源实现源码分析
- android实现A-Z排序和检索的功能
- Json简介
- Nginx 模块自主开发二:Nginx的类型命名封装
- [LeetCode]problem 77. Combinations
- string 的简单实现
- mac tool
- 自定义控件之A-Z快速检索QuickIndexBar
- Android中线程那些事儿
- 整数划分
- Material Design Library系列之CoordinatorLayout
- Google 的开源技术protobuf 简介与例子
- [LeetCode]problem 148. Sort List
- JVM内部结构
- 网络请求框架
- Leetcode 131 Palindrome Partitioning