很多的AndroID入门程序猿来说对于AndroID自定义view,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义view上面花一些功夫,多写一些文章。
思路分析:
2、ListVIEw实现联系人列表
3、字母导航栏滑动事件处理
4、字母导航栏与中间字母的联动
5、字母导航栏与ListVIEw的联动
效果图:
首先,我们先甩出主布局文件,方便后面代码的说明
<!--?xml version="1.0" enCoding="utf-8"?--><linearlayout androID:layout_height="match_parent" androID:layout_wIDth="match_parent" androID:orIEntation="vertical" xmlns:androID="http://schemas.androID.com/apk/res/androID"> <edittext androID:background="@drawable/search_border" androID:drawableleft="@androID:drawable/ic_menu_search" androID:layout_height="wrap_content" androID:layout_wIDth="match_parent" androID:padding="8dp"> <relativelayout androID:layout_height="match_parent" androID:layout_wIDth="match_parent"> <ListvIEw androID:divIDer="@null" androID:ID="@+ID/lv" androID:layout_height="match_parent" androID:layout_wIDth="match_parent"> <textvIEw androID:background="#888888" androID:gravity="center" androID:ID="@+ID/tv" androID:layout_centerinparent="true" androID:layout_height="50dp" androID:layout_wIDth="50dp" androID:textcolor="#000000" androID:textsize="18dp" androID:visibility="gone"> <com.handsome.tulin.vIEw.navvIEw androID:ID="@+ID/nv" androID:layout_alignparentright="true" androID:layout_height="match_parent" androID:layout_margin="16dp" androID:layout_wIDth="20dp"> </com.handsome.tulin.vIEw.navvIEw></textvIEw></ListvIEw></relativelayout></edittext></linearlayout>
步骤一:分析自定义字母导航栏
思路分析:
1、我们在使用的时候把宽设置为20dp,高设置为填充父控件,所以这里获取的宽度为20dp
2、通过循环,画出竖直的字母,每画一次得重新设置一下颜色,因为我们需要一个选中的字母颜色和默认不一样
public class NavVIEw extends VIEw { private Paint textPaint = new Paint(); private String[] s = 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 choose = -1; //中间的文本 private TextVIEw tv; public NavVIEw(Context context,AttributeSet attrs) { super(context,attrs); } public NavVIEw(Context context) { super(context); } public NavVIEw(Context context,AttributeSet attrs,int defStyleAttr) { super(context,attrs,defStyleAttr); } private voID initPaint() { textPaint.setTextSize(20); textPaint.setAntiAlias(true); textPaint.setcolor(color.BLACK); } @OverrIDe protected voID onDraw(Canvas canvas) { super.onDraw(canvas); //画字母 drawText(canvas); } /** * 画字母 * * @param canvas */ private voID drawText(Canvas canvas) { //获取VIEw的宽高 int wIDth = getWIDth(); int height = getHeight(); //获取每个字母的高度 int singleHeight = height / s.length; //画字母 for (int i = 0; i < s.length; i++) { //画笔默认颜色 initPaint(); //高亮字母颜色 if (choose == i) { textPaint.setcolor(color.RED); } //计算每个字母的坐标 float x = (wIDth - textPaint.measureText(s[i])) / 2; float y = (i + 1) * singleHeight; canvas.drawText(s[i],x,y,textPaint); //重置颜色 textPaint.reset(); } }}
步骤二:ListVIEw实现联系人列表
思路分析:
1、在主Activity中,定义一个数据数组,使用工具类获取数组的第一个字母,使用Collections根据第一个字母进行排序,由于工具类有点长,就不贴出来了。
2、创建一个ListVIEw子布局,创建一个Adapter进行填充。
主布局:
public class MainActivity extends AppCompatActivity { private TextVIEw tv; private ListVIEw lv; private NavVIEw nv; private List<user> List; private UserAdapter adapter; private String[] name = new String[]{ "潘粤明","戴军","薛之谦","蓝雨","任泉","张杰","秦俊杰","陈坤","田亮","夏雨","保剑锋","陆毅","乔振宇","吉杰","郭敬明","巫迪文","欢子","井柏然","左小祖咒","段奕宏","毛宁","樊凡","汤潮","山野","陈龙","侯勇","俞思远","冯绍峰","崔健","杜淳","张翰","彭坦","柏栩栩","蒲巴甲","凌潇肃","毛方圆","武艺","耿乐","钱泳辰"}; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); initVIEw(); initData(); } private voID initVIEw() { tv = (TextVIEw) findVIEwByID(R.ID.tv); lv = (ListVIEw) findVIEwByID(R.ID.lv); nv = (NavVIEw) findVIEwByID(R.ID.nv); nv.setTextVIEw(tv); } private voID initData() { //初始化数据 List = new ArrayList<>(); for (int i = 0; i < name.length; i++) { List.add(new User(name[i],CharacterUtils.getFirstSpell(name[i]).toupperCase())); } //将拼音排序 Collections.sort(List,new Comparator<user>() { @OverrIDe public int compare(User lhs,User rhs) { return lhs.getFirstCharacter().compareto(rhs.getFirstCharacter()); } }); //填充ListVIEw adapter = new UserAdapter(this,List); lv.setAdapter(adapter); }}</user></user>
ListVIEw子布局:
<!--?xml version="1.0" enCoding="utf-8"?--><linearlayout androID:background="#ffffff" androID:layout_height="match_parent" androID:layout_wIDth="match_parent" androID:orIEntation="vertical" xmlns:androID="http://schemas.androID.com/apk/res/androID"> <textvIEw androID:background="#DBDBDA" androID:ID="@+ID/tv_firstCharacter" androID:layout_height="wrap_content" androID:layout_wIDth="match_parent" androID:padding="8dp" androID:text="A" androID:textcolor="#000000" androID:textsize="14dp"> <textvIEw androID:background="#ffffff" androID:ID="@+ID/tv_name" androID:layout_height="wrap_content" androID:layout_wIDth="match_parent" androID:padding="8dp" androID:text="张栋梁" androID:textcolor="#2196F3" androID:textsize="14dp"> </textvIEw></textvIEw></linearlayout>
Adapter:
public class UserAdapter extends BaseAdapter { private List<user> List; private User user; private LayoutInflater mInflater; private Context context; public UserAdapter(Context context,List<user> List) { this.List = List; mInflater = LayoutInflater.from(context); this.context = context; } @OverrIDe public int getCount() { return List.size(); } @OverrIDe public Object getItem(int position) { return List.get(position); } @OverrIDe public long getItemID(int position) { return position; } @OverrIDe public VIEw getVIEw(int position,VIEw convertVIEw,VIEwGroup parent) { if (convertVIEw == null) { convertVIEw = mInflater.inflate(R.layout.adapter_user,null); } VIEwHolder holder = getVIEwHolder(convertVIEw); user = List.get(position); if (position == 0) { //第一个数据要显示字母和姓名 holder.tv_firstCharacter.setVisibility(VIEw.VISIBLE); holder.tv_firstCharacter.setText(user.getFirstCharacter()); holder.tv_name.setText(user.getUsername()); } else { //其他数据判断是否为同个字母,这里使用Ascii码比较大小 if (CharacterUtils.getCnAscii(List.get(position - 1).getFirstCharacter().charat(0)) < CharacterUtils.getCnAscii(user.getFirstCharacter().charat(0))) { //后面字母的值大于前面字母的值,需要显示字母 holder.tv_firstCharacter.setVisibility(VIEw.VISIBLE); holder.tv_firstCharacter.setText(user.getFirstCharacter()); holder.tv_name.setText(user.getUsername()); } else { //后面字母的值等于前面字母的值,不显示字母 holder.tv_firstCharacter.setVisibility(VIEw.GONE); holder.tv_name.setText(user.getUsername()); } } return convertVIEw; } /** * 获得控件管理对象 * * @param vIEw * @return */ private VIEwHolder getVIEwHolder(VIEw vIEw) { VIEwHolder holder = (VIEwHolder) vIEw.getTag(); if (holder == null) { holder = new VIEwHolder(vIEw); vIEw.setTag(holder); } return holder; } /** * 控件管理类 */ private class VIEwHolder { private TextVIEw tv_firstCharacter,tv_name; VIEwHolder(VIEw vIEw) { tv_firstCharacter = (TextVIEw) vIEw.findVIEwByID(R.ID.tv_firstCharacter); tv_name = (TextVIEw) vIEw.findVIEwByID(R.ID.tv_name); } } /** * 通过字符查找位置 * * @param s * @return */ public int getSelectposition(String s) { for (int i = 0; i < getCount(); i++) { String firChar = List.get(i).getFirstCharacter(); if (firChar.equals(s)) { return i; } } return -1; }}</user></user>
步骤三:字母导航栏滑动事件处理、字母导航栏与中间字母的联动
思路分析:
1、在自定义view中重写dispatchtouchEvent处理滑动事件,最后返回true。
2、在主Activity传进来一个TextVIEw,在我们滑动的时候设置Text,松开的时候消失Text。设置Text的时候需要计算Text的位置,并且滑过多的话会出现数组越界的问题,所以我们在里面处理数组越界问题。
3、最后,提供一个接口,记录我们滑到的字母,为了后面可以和ListVIEw联动。
@OverrIDepublic boolean dispatchtouchEvent(MotionEvent event) { //计算选中字母 int index = (int) (event.getY() / getHeight() * s.length); //防止脚标越界 if (index >= s.length) { index = s.length - 1; } else if (index < 0) { index = 0; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: setBackgroundcolor(color.GRAY); //选中字母高亮 choose = index; //出现中间文字 tv.setVisibility(VISIBLE); tv.setText(s[choose]); //调用ListVIEw连动接口 if (Listener != null) { Listener.touchCharacterListener(s[choose]); } //重绘 invalIDate(); break; default: setBackgroundcolor(color.transparent); //取消选中字母高亮 choose = -1; //隐藏中间文字 tv.setVisibility(GONE); //重绘 invalIDate(); break; } return true;}public ontouchCharacterListener Listener;public interface ontouchCharacterListener { voID touchCharacterListener(String s);} public voID setListener(ontouchCharacterListener Listener) { this.Listener = Listener;} /** * 传进来一个TextVIEw * * @param tv */public voID setTextVIEw(TextVIEw tv) { this.tv = tv;}
步骤四:字母导航栏和ListVIEw的联动
思路分析:
1、我们已经通过接口传递过去了一个选择的字母,和在adapter写好了根据字母查询position的方法,这个时候只要主Activity对自定义view设置监听,判断即可。
//ListVIEw连动接口nv.setListener(new NavVIEw.ontouchCharacterListener() { @OverrIDe public voID touchCharacterListener(String s) { int position = adapter.getSelectposition(s); if (position != -1) { lv.setSelection(position); } }});
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。
总结以上是内存溢出为你收集整理的Android自定义View实现字母导航栏全部内容,希望文章能够帮你解决Android自定义View实现字母导航栏所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)