自定义控件之A-Z快速检索QuickIndexBar
2016-06-23 14:34
375 查看
---------快速检索--------------
1.应用场景:联系人,好友列表,商品等列表的快速定位和搜索
2.实现逻辑:
a.右边是自定义QuickIndexBar,它能获取触摸它的时候当前所触摸到的字母;
绘制文本x坐标: width/2;
绘制文本y坐标: 格子高度的一半 + 文本高度的一半 + position*格子高度
计算触摸点对应的字母:根据触摸点的y坐标除以cellHeight,得到的值就是字母对应的索引;
b.左边是listview,它根据当前触摸的字母,去自己列表找首字母和触摸字母相同的那个
item,然后让item放置到屏幕顶端(setSelection(position));
c.需要用到获取汉字的拼音,借助类库pinyin4j.jar实现;
QuickIndexBar:
MainActivity:
MyListAdapter:
Bean(Friend):
activity_main:
运行结果:
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>
运行结果:
相关文章推荐
- edgesForExtendedLayout属性
- UITableView默认选中第一个cell
- Android Studio Gradle Build Running 特别慢的问题探讨
- Html中value和name属性的作用及其使用介绍!
- android Gui系统之SurfaceFlinger(4)
- Count Univalue Subtrees
- 判断request是否是ajax
- (转)详解 Secure Boot 和 Winows 8 及 UEFI启动的关系
- Errors occurred during the build.
- easyui pivotgrid统计,数据加载
- Java学习笔记(16)JavaFX UI Controls and Multimedia JavaFX UI控件和多媒体
- Top K Frequent Elements
- Android初级之路--------UI控件
- UIView的xib关联问题
- ios开源框架——UITableView+FDTemplateLayoutCell优化UITableViewCell高度计算
- sql insert values 后面的值是单引号,还是没有引号问题由其表中数据格式而定
- UI控件之ScrollView(滚动条)
- sqlmap批量扫描burpsuite请求日志记录
- SQL Server 中master..spt_values的应用
- iOS 蓝牙开发 UUID不能使用 isConnected不能使用的问题解决