自定义View之快速索引栏的实现"/>
自定义View之快速索引栏的实现
侧拉索引:音乐APP,即时通讯,电商选择城市,短信验证选择城市都有这个类型的自定义控件 实现步骤:1.绘制A-Z的字母列表(自绘式自定义控件)快速索引栏1.继承View,覆写构造方法,初始化画笔2.在OnDrawer方法里绘制字符3.在OnMesure方法里测量高度4.在OnTouchEvent事件知道用户具体按住了哪个字母5.定义抽象方法,实现监听回调2.响应触摸事件3.提供监听回调4.获取汉字的拼音,首字母5.根据拼音排序6.根据首字母分组7.把监听回调和ListView结合起来当前首字母A上面空的,直接设置数据,判断当前字母与上一个字母是否一致,来确定是显示还是隐藏.1.自定义View 首先这里去除了标题 在Style<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
public class MyQuickIndex extends View { private Paint paint; private int measuredHeight; private float spaceHeight; private int measuredWidth; private int lastIndex=-1; public MyQuickIndex(Context context) { this(context, null); } public MyQuickIndex(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyQuickIndex(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //初始化画笔 initPainter(); } private void initPainter() { paint = new Paint(); //设置风格 paint.setStyle(Paint.Style.STROKE); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔加粗 paint.setTypeface(Typeface.DEFAULT_BOLD); //设置画笔颜色 paint.setColor(Color.WHITE); paint.setTextSize(30); } //准备的数据 //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" }; @Override protected void onDraw(Canvas canvas) { //遍历字母数组,计算坐标,进行绘制 for (int i = 0; i < LETTERS.length; i++) { String letter = LETTERS[i]; //计算X轴坐标 float x = measuredWidth * 0.5f - paint.measureText(letter) * 0.5f; float y = spaceHeight * 0.5f + paint.measureText(letter) * 0.5f+i*spaceHeight; canvas.drawText(letter, x,y, paint); } } //获取控件的宽高 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //得到控件宽度 高度 measuredWidth = getMeasuredWidth(); measuredHeight = getMeasuredHeight();//既是控件宽度也是单元格宽度 //单元格的高度 spaceHeight = measuredHeight *1.0f / LETTERS.length; } @Override public boolean onTouchEvent(MotionEvent event) { switch(event.getAction()){ //计算用户按到哪个 字母 case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: //得到当前的Y float y = event.getY(); //得到是第几个indxt int currentIndex = (int) (y / spaceHeight); //判断不是点击同一个字母 if(currentIndex!=lastIndex){ if(currentIndex>=0 && currentIndex<LETTERS.length) { String letter = LETTERS[currentIndex]; Util_Toast.showToast(getContext(),letter); //重新赋值 lastIndex=currentIndex; } } break; default: break; } return true; }}
2.吐司工具类xml引用public class Util_Toast {private static Toast toast;public static void showToast(Context context ,String msg){if (toast ==null){toast=Toast.makeText(context, "", Toast.LENGTH_SHORT);}toast.setText(msg);toast.show();}}
///分割
1.自定义接口 在MainActivity里进行吐司public class MyQuickIndex extends View {private Paint paint;private int measuredHeight;private float spaceHeight;private int measuredWidth;public MyQuickIndex(Context context) {this(context, null);}public MyQuickIndex(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyQuickIndex(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//初始化画笔 initPainter();}private void initPainter() {paint = new Paint();//设置风格 paint.setStyle(Paint.Style.STROKE);//设置抗锯齿 paint.setAntiAlias(true);//设置画笔加粗 paint.setTypeface(Typeface.DEFAULT_BOLD);//设置画笔颜色 paint.setColor(Color.WHITE);paint.setTextSize(30);}//准备的数据 //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" };@Override protected void onDraw(Canvas canvas) {//遍历字母数组,计算坐标,进行绘制 for (int i = 0; i < LETTERS.length; i++) {String letter = LETTERS[i];//计算X轴坐标 float x = measuredWidth * 0.5f - paint.measureText(letter) * 0.5f;float y = spaceHeight * 0.5f + paint.measureText(letter) * 0.5f+i*spaceHeight;canvas.drawText(letter, x,y, paint);}}//获取控件的宽高 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//得到控件宽度 高度 measuredWidth = getMeasuredWidth();measuredHeight = getMeasuredHeight();//既是控件宽度也是单元格宽度 //单元格的高度 spaceHeight = measuredHeight *1.0f / LETTERS.length;}@Override public boolean onTouchEvent(MotionEvent event) {super.onTouchEvent(event);if(mOntouchListener!=null){mOntouchListener.onTouchEvent(this,event,spaceHeight,LETTERS);}return true;}private OntouchListener mOntouchListener;public interface OntouchListener{void onTouchEvent(MyQuickIndex myQuickIndex,MotionEvent event,float spaceHeight,final String[] LETTERS);}public void setmOntouchListener(OntouchListener mOntouchListener) {this.mOntouchListener = mOntouchListener;} }MainActivitypublic class MainActivity extends AppCompatActivity {private MyQuickIndex mQuickIndex;private int lastIndex=-1;/** * View decorView = getWindow().getDecorView(); * int option = View.SYSTEM_UI_FLAG_FULLSCREEN; * decorView.setSystemUiVisibility(option); * ActionBar actionBar = getSupportActionBar(); * actionBar.hide(); * 隐藏状态栏 * * @param savedInstanceState */ @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); // requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main);initView();mQuickIndex.setmOntouchListener(new MyQuickIndex.OntouchListener() {@Override public void onTouchEvent(MyQuickIndex myQuickIndex, MotionEvent event, float spaceHeight, String[] LETTERS) {switch(event.getAction()){//计算用户按到哪个 字母 case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE://得到当前的Y float y = event.getY();//得到是第几个indxt int currentIndex = (int) (y / spaceHeight);//判断不是点击同一个字母 if(currentIndex!=lastIndex){if(currentIndex>=0 && currentIndex<LETTERS.length) {String letter = LETTERS[currentIndex];Util_Toast.showToast(MainActivity.this,letter);//重新赋值 lastIndex=currentIndex;}}break;default:break;}}});}private void initView() {mQuickIndex = (MyQuickIndex) findViewById(R.id.quickIndex);} }
/****************以上仅仅是右边栏的实现************************/
左边栏的实现思路
1.拼音四级的pinyin4j的工具类
public class Util_Pinyin {public static String getPinyin(String string){HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();//不要音标 format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);char[] chars = string.toCharArray();StringBuilder sb = new StringBuilder();for (int i = 0; i < chars.length; i++) {char c = chars[i];//如果是空格,跳过当前循环 if(Character.isWhitespace(c)){continue;}//如果不是汉字,直接拼写 if(c>-128 && c<127){sb.append(c);}else{//是汉字 name我们就获取拼音 try {String s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];sb.append(s);} catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {badHanyuPinyinOutputFormatCombination.printStackTrace();}}}return sb.toString();} }
//TinyPinyin直接使用就可以了 示例代码
String strResource="你 好dasdasdas扣罚款就派送啊啊搜集"; StringBuilder sb=new StringBuilder() ; char[] chars = strResource.toCharArray(); for (int i = 0; i <chars.length ; i++) {char aChar = chars[i];if(Character.isWhitespace(aChar)){continue;}String s = Pinyin.toPinyin(aChar);sb.append(s); } System.out.println(sb);//输出结果带字母dasdasdas
/*************或者用PinYin的判断String strResource="你 好dasdasdas扣罚款就派送啊啊搜集";StringBuilder sb=new StringBuilder() ;char[] chars = strResource.toCharArray();for (int i = 0; i <chars.length ; i++) {char aChar = chars[i]; // if(Character.isWhitespace(aChar)){ // continue; // } if(Pinyin.isChinese(aChar)){String s = Pinyin.toPinyin(aChar);sb.append(s);}}System.out.println(sb);//不带
//适配器public class MyAdapter extends BaseAdapter {private List<Bean> list;private Context context;public MyAdapter(List<Bean> list, Context context) {this.list = list;this.context = context;}@Override public int getCount() {return list.size();}@Override public Object getItem(int i) {return null;}@Override public long getItemId(int i) {return 0;}@Override public View getView(int i, View view, ViewGroup viewGroup) {ViewHolder holder;if(view==null){holder=new ViewHolder();view=view.inflate(context,R.layout.item,null);holder.tvIndex=view.findViewById(R.id.tv_index);holder.tvName=view.findViewById(R.id.tv_name);view.setTag(holder);}else{holder= (ViewHolder) view.getTag();}Bean bean = list.get(i);//当前首字母 String currentStr = bean.getPinyin().charAt(0) + "";String indexStr=null;//如果是第一个名字直接显示 if(i==0){indexStr=currentStr;}else{//判断当前首字母和上一个条目的首字母是否一致,不一致时显示完整item界面 String lastStr = list.get(i - 1).getPinyin().charAt(0) + "";//判断俩个参数是否一致,不一致时就执行赋值的逻辑 if(!TextUtils.equals(lastStr,currentStr)){//不一致时直接赋值indexStr indexStr=currentStr;}}holder.tvIndex.setText(indexStr);holder.tvName.setText(bean.getName());//做一个判断 如果不一致显示出来 如果一致则隐藏 不等于空说明走了赋值逻辑 说明与当前不一样 是第一次出现 holder.tvIndex.setVisibility(indexStr != null ? View.VISIBLE:View.GONE);return view;}static class ViewHolder{TextView tvIndex,tvName;} }//MainActivitypublic class MainActivity extends AppCompatActivity implements MyQuickIndex.OntouchListener, View.OnClickListener {private MyQuickIndex mQuickIndex;private int lastIndex = -1;public static final String[] NAMES = new String[]{"宋江", "卢俊义", "吴用","公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深","武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘","雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍"," 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪","魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方","郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充","李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿","陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩","周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立","李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜","时迁", "段景柱", "小凡哥"};private List<Bean> persons;private ListView mLv;private RelativeLayout mActivityMain;/** * View decorView = getWindow().getDecorView(); * int option = View.SYSTEM_UI_FLAG_FULLSCREEN; * decorView.setSystemUiVisibility(option); * ActionBar actionBar = getSupportActionBar(); * actionBar.hide(); * 隐藏状态栏 */ @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); // requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main);initView();mQuickIndex.setmOntouchListener(this);//准备数据 persons = new ArrayList<>();//排序 findAndSortData(persons);//适配数据 MyAdapter myAdapter = new MyAdapter(persons, this);mLv.setAdapter(myAdapter);}private void findAndSortData(List<Bean> persons) {for (int i = 0; i < NAMES.length; i++) {String name = NAMES[i];Bean bean = new Bean(name);persons.add(bean);}Collections.sort(persons);}private void initView() {mQuickIndex = (MyQuickIndex) findViewById(R.id.quickIndex);mLv = (ListView) findViewById(R.id.lv);mQuickIndex.setOnClickListener(this);mActivityMain = (RelativeLayout) findViewById(R.id.activity_main);}@Override public void onTouchEvent(MyQuickIndex myQuickIndex, MotionEvent event, float spaceHeight, String[] LETTERS) {switch (event.getAction()) {//计算用户按到哪个 字母 case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE://得到当前的Y float y = event.getY();//得到是第几个indxt int currentIndex = (int) (y / spaceHeight);//判断不是点击同一个字母 if (currentIndex != lastIndex) {if (currentIndex >= 0 && currentIndex < LETTERS.length) {String letter = LETTERS[currentIndex];Util_Toast.showToast(MainActivity.this, letter);for (int i = 0; i < persons.size(); i++) {String s = persons.get(i).getPinyin().charAt(0) + "";if(s.equals(letter)){mLv.setSelection(i);break;}}//重新赋值 lastIndex = currentIndex;}}break;default:break;}}@Override public void onClick(View v) {switch (v.getId()) {case R.id.quickIndex:break;}} }//Xml item<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"><TextView android:id="@+id/tv_index" android:layout_width="match_parent" android:layout_height="40dp" android:background="#666666" android:gravity="center_vertical" android:paddingLeft="15dp" android:text="A" android:textColor="#FFFFFF" android:textSize="18sp" /><TextView android:id="@+id/tv_name" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center_vertical" android:paddingLeft="15dp" android:text="宋江" android:textSize="22sp" /></LinearLayout>//MainXml<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="" xmlns:tools="" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" ><ListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent"></ListView><com.example.administrator.view_suoyin.MyQuickIndex android:layout_width="30dp" android:id="@+id/quickIndex" android:layout_height="match_parent" android:background="#006aff" android:layout_alignParentRight="true" /> </RelativeLayout>
更多推荐
自定义View之快速索引栏的实现
发布评论