带索引栏的listview,在android开发非常普遍,方便用户进行字母索引,就像微信通讯录这样:

  今天,我们就从零到一实现这个具有索引栏的listview.

  怎么实现这个控件了,我们应当梳理出一个思路。

  ①首先应当将字母的索引栏继承与一个控件,通过ondraw方法将字母画出来。

  ②然后我们应该监听这个字母控件的ontouch事件,来判断用户到底是按了那个字母。

  ③就是实现这个索引栏与listview的联动,就是将listview滑动到按下字母的位置。

  大体流程图如下:

  有了前面铺垫,我们引出本文重头戏——代码。

  首先,索引栏这个控件如何将字母绘制在控件上的代码:

    /**
* 侧边栏显示字母
*/
private String[] words = { "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) {
// TODO Auto-generated method stub
super.onDraw(canvas);
int height = getHeight();// 获取对应高度
int width = getWidth(); // 获取对应宽度
int singleHeight = height / words.length;// 获取每一个字母的高度 for (int i = 0; i < words.length; i++) {
paint.setColor(Color.rgb(33, 65, 98));
// paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setAntiAlias(true);
paint.setTextSize(20f);
// 选中的状态
if (isdown) {
paint.setColor(Color.parseColor("#ffffff"));
//paint.setFakeBoldText(true);
}
// x坐标等于中间-字符串宽度的一半.
float xPos = width / 2 - paint.measureText(words[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(words[i], xPos, yPos, paint);
paint.reset();// 重置画笔
}
}

  通过上述的代码,我们可以得出以下的结论:将要绘制的字母以从上到下的顺序绘制在一个指定区域,每个字母的x坐标是一样的,x坐标即为控件宽度一半。如果当前字母选中的话,就高亮显示。思路如图所示:

  紧接着,就来到第二步,确定用户到底点击是那个字母,代码如下:

/**
* 处理触摸事件的方法
* 用户按下时候,整个控件背景变化
* 根据按下y坐标 判断究竟用户按下那个字母
* 当前字母高亮显示 将其字母显示listview中央
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int action = event.getAction();
final float y = event.getY();// 点击y坐标
final int oldChoose = choose;
final ITouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * words.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
switch (action) {
case MotionEvent.ACTION_UP:
isdown=false;
setBackgroundResource(android.R.color.transparent);
choose = -1;//
invalidate();
if (textViewDialog != null) {
textViewDialog.setVisibility(View.INVISIBLE);
}
break; default:
isdown=true;
setBackgroundResource(R.color.sidebar_bg_color);
if (oldChoose != c) {
if (c >= 0 && c < words.length) {
if (listener != null) {
listener.OnTouchingLetterChanged(words[c]);
}
if (textViewDialog != null) {
textViewDialog.setText(words[c]);
textViewDialog.setVisibility(View.VISIBLE);
} choose = c;
invalidate();
}
}
break;
}
return true;
}

  通过上述的代码,我们可以这样总结:当用户按下的时候,整个控件背景发生变化,根据用户按下的y坐标来确定用户究竟是按下那个字母,并且将按下字母显示屏幕的中央,效果图如下:

  最终,将listview 移动到按下字母相应位置,代码如下:

/**
* 根据用户点击那个字母将listview移动到相应位置
*/
sidebar.setOnTouchingLetterChangedListener(new ITouchingLetterChangedListener() { @Override
public void OnTouchingLetterChanged(String cString) {
int position = -1;
if (cString.length() > 0) {
position = myAdapter.getPositionForSection(cString
.charAt(0));
}
if (position != -1) {
listview.setSelection(position);
} else if (cString.contains("#")) {
listview.setSelection(0);
}
}
});

  连篇累牍说了这么多,控件大功告成的效果为:

  源代码地址为:

  http://pan.baidu.com/s/1dDMDjhR

玩转android自定义控件二——自定义索引栏listview的更多相关文章

  1. 老猪带你玩转android自定义控件二——自定义索引栏listview

    带索引栏的listview,在android开发非常普遍,方便用户进行字母索引,就像微信通讯录这样: 今天,我们就从零到一实现这个具有索引栏的listview. 怎么实现这个控件了,我们应当梳理出一个 ...

  2. Android自定义控件之自定义ViewGroup实现标签云

    前言: 前面几篇讲了自定义控件绘制原理Android自定义控件之基本原理(一),自定义属性Android自定义控件之自定义属性(二),自定义组合控件Android自定义控件之自定义组合控件(三),常言 ...

  3. Android自定义控件之自定义组合控件

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  4. Android自定义控件之自定义组合控件(三)

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  5. 老猪带你玩转android自定义控件一——打造最简单viewpagerindicator

    viewpagerindicator,既使用viewpager翻页时候,标题的指示条随着改变的控件,是常用android控件之一,几乎所有的新闻类APP中都有使用.如下图所示: 今天,我们将从0到1实 ...

  6. android自定义控件(4)-自定义水波纹效果

    一.实现单击出现水波纹单圈效果: 照例来说,还是一个自定义控件,观察这个效果,发现应该需要重写onTouchEvent和onDraw方法,通过在onTouchEvent中获取触摸的坐标,然后以这个坐标 ...

  7. android自定义控件(3)-自定义当前按钮属性

    那么还是针对我们之前写的自定义控件:开关按钮为例来说,在之前的基础上,我们来看看有哪些属性是可以自定义的:按钮的背景图片,按钮的滑块图片,和按钮的状态(是开还是关),实际上都应该是可以在xml文件中直 ...

  8. android 自定义控件二之仿QQ长按删除

    自定义Dialog 1.先上个效果图:

  9. android自定义控件(五) 自定义组合控件

    转自http://www.cnblogs.com/hdjjun/archive/2011/10/12/2209467.html 代码为自己编写 目标:实现textview和ImageButton组合, ...

随机推荐

  1. 以太坊go-ethereum客户端JSON-RPC API调用(一)

    前几篇博客主要介绍了go-ethereum客户端不同环境的搭建,今天这篇博客是建立在前几排博客的基础上.当搭建完成之后,我们可以通过各种方式与节点进行交互(JavaScript Console.JSO ...

  2. 如何使用OpenSSL工具生成根证书与应用证书

    如何使用OpenSSL工具生成根证书与应用证书 一.步骤简记 // 生成顶级CA的公钥证书和私钥文件,有效期10年(RSA 1024bits,默认) openssl req -new -x509 -d ...

  3. 环状序列(UVa1584)

    题目具体描述见:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_prob ...

  4. Nodejs JSON.parse()无法解析ObjectID和ISODate的问题

    一个早上搞清楚了一个问题,关于Nodjes JSON.parse()方法只能解析字符串.布尔值.数字等,但不能解析ObjectID及ISODate的值 原因:<How to handle Obj ...

  5. Socket 异步

    摘要: System.Net.Sockets.Sockte 类有一组增强功能,提供可供专用的高性能套接字应用程序使用的可选异步模式,SocketAsyncEventArgs 类就是这一组增强功能的一部 ...

  6. 洛谷P2812 校园网络[数据加强版] [Tarjan]

    题目传送门 校园网络 题目背景 浙江省的几所OI强校的神犇发明了一种人工智能,可以AC任何题目,所以他们决定建立一个网络来共享这个软件.但是由于他们脑力劳动过多导致全身无力身体被♂掏♂空,他们来找你帮 ...

  7. java getenv getProperties区别

    网上很多使用的是getProperties.说获得系统变量,但是其实不正确.getProperties中所谓的"system properties"其实是指"java s ...

  8. C和指针之学习笔记(4)

    第9章 字符串 字符串的输入与输出 int  ch;  char strings[80];  FILE *input; (1)scanf(“%c”,&ch);   printf(“%c \n” ...

  9. FastReport.Net使用:[7]打印空白行

    方法一:使用子报表的最少数据行属性 1.以前面的[简单报表一]为例,右键“数据区”在右键菜单中选择“Add Child Band”菜单添加子报表. 2.为原报表添加一列[序号],使用系统变量中的行号( ...

  10. 颓废选手在 Ubuntu/Noilinux 下的生存指北

    颓废选手在 Ubuntu/Noilinux 下的生存指北 Hint: 这里的 "#" 都是假注释,复制的时候记得删除 一些基本的生存命令 ctrl + alt + t #调出终端 ...