带索引栏的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. 运行级别(run level)

    inittab是很多linux版本的启动脚本.Linux在完成核内引导以后,就开始运行init程序,它的进程号是1,是所有其他进程的起点.init需要读取/etc/inittab,该文件告诉init在 ...

  2. 父元素的mousedown事件上父元素的mousedown事件上的offsetX和offsetY错误的offsetX和offsetY错误

    https://stackoverflow.com/questions/35360704/wrong-offsetx-and-offsety-on-mousedown-event-of-parent- ...

  3. js求区间随机数

    function rnd(n, m){ var random = Math.round(Math.random()*(m-n)+n); return random; }

  4. lr_start_transaction/lr_end_transaction事物组合

    lr_start_transaction/lr_end_transaction事物组合 总结一下: lr_start_transaction与lr_end_transaction 为使用最多的事物创造 ...

  5. AOSP编译

    AOSP编译 1 编译环境Win10系统安装VMplayer14,主机16G内存,I3-4170 ,虚拟机ubuntu-16.04.1-desktop-amd64,12G内存. 2 软件安装sudo ...

  6. SSH 公私钥的基本使用

    SSH 公私钥的基本使用 创建密钥 使用 ssh-keygen 生成公私钥 在终端敲入 ssh-keygen 命令,一路一直按回车下去,会把密钥文件放置在默认路径,也就是 ~/.ssh/ 路径下,并且 ...

  7. 编译PHP并与Ngnix整合

    nginx本身不能处理PHP,它只是个web服务器,当接收到请求后,如果是php请求,则发给php解释器处理,并把结果返回给客户端. nginx一般是把请求发fastcgi管理进程处理,fascgi管 ...

  8. 429.N叉树的层次遍历

    给定一个 N 叉树,返回其节点值的层序遍历. (即从左到右,逐层遍历). 例如,给定一个 3叉树 : 返回其层序遍历: [ [1], [3,2,4], [5,6] ] 说明: 树的深度不会超过 100 ...

  9. 八皇后--python代码

    迭代和递归方法的运用 import random def prettyprint(solution): #图形化处理数据 def line(pos,length=len(solution)): #单行 ...

  10. 2017/11/20 Leetcode 日记

    2017/11/14 Leetcode 日记 442. Find All Duplicates in an Array Given an array of integers, 1 ≤ a[i] ≤ n ...