自定义View实现侧边索引
来源:互联网 发布:淘宝开店实名未认证 编辑:程序博客网 时间:2024/05/17 22:36
*侧边索引:音乐APP,即时通讯,电商选择城市,短信验证选择城市等都有自定义控件 * 实现步骤: * 1>.绘制 A - Z 的的字母列表(自绘式自定义控件) * 2>.响应触摸时间 * 3>.提供监听回调 * 4>.获取汉子拼音(首字母) pinyin4J 通过汉字得到拼音,只能一个字符一个字符去转换 * 5>.根据拼音排序 * 6>.根据首字母分组 * 7>.把监听回调和ListView结合起来* 绘制 A - Z 的的字母列表(自绘式自定义控件)* author:(Administrator)* function: 快速索引栏实现思路 * 1.继承View,覆写构造方法,初始化画笔. * 2.在OnDrawer方法里绘制字符. * 3.在OnMeasure方法里测量高度. * 4.在OntouchEven时间知道用户具体按住哪个字母. * 5.定义抽象方法,实现监听回调. *public class QuickIndexBar extends View{ private Paint mPaint; //A.要绘制的内容 private static final String[] LETTERS = new String[]{ "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 int mCellWidth; private float mCellheight; private float mY; private int mCurrentIndext; public QuickIndexBar(Context context) { this(context,null); } public QuickIndexBar(Context context, AttributeSet attrs) { this(context,attrs,0); } public QuickIndexBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context,attrs,defStyleAttr); // 初始化画笔 initPaint(); } private void initPaint() { // 创建一个抗锯齿的画笔 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); // 画笔文本加粗 mPaint.setTypeface(Typeface.DEFAULT_BOLD); // 颜色 mPaint.setColor(Color.WHITE); mPaint.setTextSize(25); } /** * * @param canvas 完成侧拉索引 */ @Override protected void onDraw(Canvas canvas) { //遍历了二十六个字母,进行坐标计算,才能进行绘制 for (int i = 0; i < LETTERS.length; i++){ // 从数组中取字母(根据I) String letter = LETTERS[i]; float x = mCellWidth * 0.5f - mPaint.measureText(letter) * 0.5f; float y = mCellheight * 0.5f + mPaint.measureText(letter) * 0.5f + i * mCellheight; canvas.drawText(letter,x, y,mPaint); } } /** * 完成侧拉索引的测量 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 获取控件的宽高 int mHeight = getMeasuredHeight(); mCellWidth = getMeasuredWidth(); // 获取单元格的高度,由自定义控件总高度,除以所有字母占用的高度 mCellheight = mHeight * 1.0f / LETTERS.length; } // 记录用户上一次按下的位置,以便进行判断这一次所按住的位置,是否,还是上一次的位置如果是,不做任何处理 private int lastIndex = -1; /** * 重写onTouchEvent触摸事件,返回值为True,方有效果 * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ // 获取被点击到的字母索引 case MotionEvent.ACTION_DOWN: // 按下时回调 case MotionEvent.ACTION_HOVER_MOVE: // 移动时回调 mY = event.getY(); System.out.println("Y值"+ mY); mCurrentIndext = (int) (mY / mCellheight); System.out.println("按住了第"+ mCurrentIndext +"单元格"); // 为了防止一个字母按住,不停的重复调用,进行判断,判断是否还是按着上一个字母,是的话,不做任何处理,提高性能; if(mCurrentIndext != lastIndex){ // 为了防止角标越界 if(mCurrentIndext >= 0 && mCurrentIndext < LETTERS.length){ String letter = LETTERS[mCurrentIndext]; if(mOnLetterUpdateListener != null){ mOnLetterUpdateListener.onLetterUpdate(letter); } //ToastUtil.showToast(getContext(),letter); lastIndex = mCurrentIndext; } } break; } return true; } /** * 定义接口 */ public interface OnLetterUpdateListener{ void onLetterUpdate(String letter); } /** * 定义接口的对象 */ private OnLetterUpdateListener mOnLetterUpdateListener; /** * 暴露方法,让外界传过来一个实现接口类的对象 */ public void setOnLetterUpdateListener(OnLetterUpdateListener onLetterUpdateListener){ mOnLetterUpdateListener = onLetterUpdateListener; }}activity_main.xml:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.administrator.customview.UI.QuickIndexBar android:id="@+id/bar" android:layout_width="30dp" android:layout_height="match_parent" android:background="#28f" android:layout_alignParentRight="true" /> <ListView android:layout_toLeftOf="@id/bar" android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent"></ListView></RelativeLayout>*获取汉子拼音(首字母) pinyin4J 通过汉字得到拼音,只能一个字符一个字符去转换(需要(创建工具类)
pinyin4J Jar包 下载地址: http://download.csdn.net/download/ghqzww/9936504)
public class PinYinUtil { public static String getPinYin(String string){ HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); //不要音标 format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); //设置转换出大写字母 format.setCaseType(HanyuPinyinCaseType.UPPERCASE); char[] array = string.toCharArray(); StringBuilder builder = new StringBuilder(); for (int x = 0; x < array.length; x++){ char c = array[x]; // 如果是空格,就跳过循环 if(Character.isWhitespace(c)){ continue; } // 如果不是汉字,直接拼写 if(c > -128 && c < 127){ builder.append(c); }else { try { // 获取某个字符的拼音,可以获取到多音字 String s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0]; builder.append(s); } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) { badHanyuPinyinOutputFormatCombination.printStackTrace(); } } } return builder.toString(); }}
* 创建一个类,存放数据public class Cheeses { public static final String[] NAMES = new String[]{"宋江", "卢俊义", "吴用", "公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深", "武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘", "雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍", " 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪", "魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方", "郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充", "李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿", "陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩", "周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立", "李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜", "时迁", "段景柱", "高会全"};}
* 吐司的工具类(使用Java代码在Main方法 Bar 的接口中使用) (可不写/自定义View中已经做好)// 吐司的工具类public class ToastUtil { private static Toast sToast; public static void showToast(Context context,String msg){ if(sToast == null){ sToast = Toast.makeText(context, "", Toast.LENGTH_SHORT); } sToast.setText(msg); sToast.show(); }}* 接着来撸 MainActivity 中代码@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 取消该Demo的toolbar requestWindowFeature(Window.FEATURE_NO_TITLE); View decorView = getWindow().getDecorView(); int option = View.SYSTEM_UI_FLAG_FULLSCREEN; decorView.setSystemUiVisibility(option); ActionBar actionBar = getSupportActionBar(); actionBar.hide(); setContentView(R.layout.activity_main); final QuickIndexBar bar = (QuickIndexBar) findViewById(R.id.bar); // D.View 层 mListView = (ListView)findViewById(R.id.listview); // D.model 层 person = new ArrayList<>(); // D.填充并排列顺序 fillAndSortData(person); // D.controller层 设置适配器 mListView.setAdapter(new HaoHanAdapter(person,this)); bar.setOnLetterUpdateListener(new QuickIndexBar.OnLetterUpdateListener() { @Override public void onLetterUpdate(String letter) { // Java 代码的吐司 ToastUtil.showToast(MainActivity.this,letter); // 将 ListView 和 自定义View 相关联 for (int x = 0; x < person.size(); x++){ String l = person.get(x).getPinyin().charAt(0) + ""; if(TextUtils.equals(letter,l)){ // 找到第一个首字母是letter条目 mListView.setSelection(x); break; } } } }); } private void fillAndSortData(ArrayList<HaoHanBang> person) { // 填充 for (int i = 0; i < Cheeses.NAMES.length; i++){ String name = Cheeses.NAMES[i]; person.add(new HaoHanBang(name)); } // 排序 Collections.sort(person); }}
* 创建适配器,为ListView适配数据/** * date:2017/8/15 * author:高会全(Administrator) * function: * 完成效果使用的是,判断当前首字母和上一个条目的首字母是否一致,,不一致时,就显示全部界面,一致时,隐藏第一个界面 */public class HaoHanAdapter extends BaseAdapter { private ArrayList<HaoHanBang> person = new ArrayList<>(); private Context mContext; public HaoHanAdapter(ArrayList<HaoHanBang> person, Context context) { this.person = person; this.mContext = context; } @Override public int getCount() { return person.size(); } @Override public View getView(int position, View conertview, ViewGroup viewGroup) { View view; if(conertview == null){ view = View.inflate(mContext,R.layout.item,null); }else { view = conertview; } TextView tv_index = (TextView) view.findViewById(R.id.tv_index); TextView tv_name = (TextView) view.findViewById(R.id.tv_name); HaoHanBang haohan = person.get(position); String currentStr = haohan.getPinyin().charAt(0) + ""; System.out.println("000000000000000000000000000"+currentStr); String indexStr = null; //如果是第一个名字,直接显示 if(position == 0){ indexStr = currentStr; }else { // 判断当前首字母是否和上一个首字母是否一致,不一致时显示完整item选项; String lastStr = person.get(position - 1).getPinyin().charAt(0) + ""; // 判断两个参数是否一致,不一致执行赋值逻辑 if(!TextUtils.equals(lastStr,currentStr)){ // 不一致时赋值indexStr indexStr = currentStr; } } tv_index.setVisibility(indexStr != null ?View.VISIBLE : View.GONE); tv_index.setText(currentStr); tv_name.setText(haohan.getName()); return view; } @Override public Object getItem(int i) { return null; } @Override public long getItemId(int i) { return 0; }}
* ListView 适配器的 Bean 类public class HaoHanBang implements Comparable<HaoHanBang>{ private String name; private String pinyin; public HaoHanBang(String name){ this.name = name; this.pinyin = PinYinUtil.getPinYin(name); } public String getName() { return name; } public String getPinyin() { return pinyin; } @Override public int compareTo(HaoHanBang haoHanBang) { return this.pinyin.compareTo(haoHanBang.pinyin); }}
阅读全文
0 0
- 自定义View实现侧边索引
- 自定义View,实现侧边索引
- 自定义View:快速索引实现
- 自定义View实现索引效果
- 自定义侧边快速索引栏
- 安卓之自定义view实现索引
- Android 自定义View-实现快速索引
- Android自定义View实现字母索引条
- 自定义View 实现字母快速索引控件
- Android自定义View之侧边栏初探
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
- 自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
- 索引之LinearLayout侧边栏+listview实现
- Android实现侧边栏按字母索引
- 侧边索引
- 自定义索引view
- 语义分割相关总结
- 融合大数据能力,解决在存量时代下的力分之困
- Activity 的Window创建过程
- screenX / Y,clientX / Y和pageX / Y之间有什么区别?
- Python批量监控主机内存/CPU利用率/磁盘/网络等信息
- 自定义View实现侧边索引
- 各种激活函数(Activation Function)
- 我的CUDA学习之旅3——图像灰度化、灰度直方图统计
- RecyclerView优雅的添加Header和Footer
- c#中将Html中table表格替换成数组
- 15.1-全栈Java笔记:Java事件模型是什么?事件控制的过程有哪几步??
- 中钰睿泓分享:设计LOGO的思路和流程
- C# Random 生成不重复随机数
- list遍历效能测试和list分割