前言
如图所示,侧边栏字母索引其实是一个Button类的按钮,点击该按钮上的某个字母,lietView会立刻跳转到对应的那一个字母的组,该效果通过重写Button类来实现.
需求分析
1.字母的绘制
需要将26个大写字母和‘#’,‘?’两个特殊字母按照固定的间隔绘制到按钮上。
2.点击按钮的功能
点击按钮是能够判断出选中的是哪个字母,并在列表上作出相应的显示。同时有弹窗提示。
3.点击按钮时的绘制
点击按钮时有颜色、字体的变化效果,松开按钮后又回复原样。
技术分析
重写onDraw函数,可以自定义按钮的绘制,在通过invalidate函数的调用,打到重绘的效果。
重写dispatchTouchEvent函数,自定义按钮的Down,Up事件的处理逻辑。
声明一个OnTouchSideButtonListener接口,带有两个回调函数,分别是onTouchSideButtonDown,onTouchSideButtonUP函数,在DOWN和UP事件的时候调用。
在Activity类里边实现上述这两个回调函数,把对列表显示的相关操作封装到这两个回调函数里。
实现过程
重写onDraw
1.getHeight(),getWidth()函数来获取按钮的宽和高,并计算出字母的间隔
2.paint实例来设置文字的相关样式属性
3.isTouch变量来判断当前是否按钮被点击
4.canvas实例真正决定了实行重绘
代码:
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
int height = getHeight();
int width = getWidth();
int interval = height / (assort.length+1);//上下字母之间的间隔
for (int i = 0, length = assort.length; i < length; i++) {
paint.setTextSize(39);
// 抗锯齿
paint.setAntiAlias(true);
// 默认粗体
//paint.setTypeface(Typeface.DEFAULT_BOLD);
// 白色
if(!isTouch){//没有触摸的时候-->字体为半透明的黑色
paint.setColor(Color.argb(51, 0, 0, 0));
//paint.setColor(Color.alpha(150));
}else{
paint.setColor(Color.alpha(0));//透明度为0,即不透明
paint.setColor(Color.WHITE);
}
if (i == selectIndex) {
// 被选择的字母改变颜色和粗体
paint.setColor(Color.WHITE);
paint.setFakeBoldText(true);
paint.setTextSize(43);
}
// 计算字母的X坐标
float xPos = width / 2 - paint.measureText(assort[i]) / 2;
// 计算字母的Y坐标
float yPos = interval * i + interval;
canvas.drawText(assort[i], xPos, yPos, paint);
paint.reset();
}
}
声明接口OnTouchSideButtonListener
public interface OnTouchSideButtonListener {
public void onTouchSideButtonDown(String selectedChar);
public void onTouchSideButtonUP();
}
同时声明一个接口对象和提供设置方法
// 字母监听器
private OnTouchSideButtonListener onTouch;
//实例化接口
public void setOnTouchSideButtonListener
(OnTouchSideButtonListener onTouch) {
this.onTouch = onTouch;
}
重写dispatchTouchEvent
1.根据event.getY()来获取点击的y轴坐标,并判断哪个字母被选中
2.如果是ACTION_DOWN事件,设置选中的字母下标,并调用 onTouchSideButtonDown函数
3.如果是ACTION_MOVE事件,更新选中的字母下表,并调用onTouchSideButtonDown函数
4.如果是ACTION_UP事件,重置相关信息,并调用onTouchSideButtonUP函数。
5.最后调用invalidate函数进行重绘。
6.Return 要返回true,这样才能截获后续的MOVE和UP事件。
代码:
public boolean dispatchTouchEvent(MotionEvent event) {
//改变背景色
setBackgroundColor(Color.argb(224, 143, 141, 140));
// TODO Auto-generated method stub
float y = event.getY();
//获得点击字母的下标,通过点击事件的坐标来计算出点击的字母
int index = (int) (y / getHeight() * assort.length);
if (index >= 0 && index < assort.length) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// 如果滑动改变
if (selectIndex != index) {
selectIndex = index;
if (onTouch != null) {
//这个方法的代码在MainActivity里面实现了
onTouch.onTouchSideButtonDown(assort[selectIndex]);
}
}
break;
case MotionEvent.ACTION_DOWN:
//屏幕被按下
isTouch=true;
selectIndex = index;
if (onTouch != null) {
//这个方法是在OnTouchAssortListener接口定义的方法
//它的具体代码在MainActivity里面实现
onTouch.onTouchSideButtonDown(assort[selectIndex]);
//onTouch.on
}
break;
case MotionEvent.ACTION_UP:
isTouch=false;
setBackgroundResource(R.color.none);
//
if (onTouch != null) {
onTouch.onTouchSideButtonUP();
}
selectIndex = -1;
break;
}
} else {
selectIndex = -1;
if (onTouch != null) {
onTouch.onTouchSideButtonUP();
}
}
invalidate();//重绘
return true;
}
实现回调函数
1.onTouchSideButtonDown函数在DOWM事件时调用,起到的作用是(1)让列表显示选中的那个字母的组;(2)弹窗显示选中的字母。
2.onTouchSideButtonUP函数在UP事件时调用,让弹窗消失。
代码:
sideButton.setOnTouchSideButtonListener(new OnTouchSideButtonListener(){
//侧边栏按钮的监听函数
<span style="white-space:pre"> </span>//弹窗的布局文件
<span style="white-space:pre"> </span>View layoutView=LayoutInflater.from(Mp3ListActivity.this)
.inflate(R.layout.alert_dialog_menu_layout, null);
<span style="white-space:pre"> </span>//弹窗的字
TextView text =(TextView) layoutView.findViewById(R.id.content);
//弹窗
PopupWindow popupWindow ;
//接口要实现的两个方法
@Override
public void onTouchSideButtonDown(String selectedChar) {
// TODO Auto-generated method stub
<span style="white-space:pre"> </span>int index=adapter.getHelper().getHashList().indexOfKey(selectedChar);
if(index!=-1)
{
//显示选中的Group
eListView.setSelectedGroup(index);;
}
if(popupWindow!=null){
text.setText(selectedChar);
}
else
{
popupWindow = new PopupWindow(layoutView,
160, 160,false);
// 显示在Activity的根视图中心
popupWindow.showAtLocation(getWindow().getDecorView(),Gravity.CENTER, 0, 0);
}
text.setText(selectedChar);
}
@Override
public void onTouchSideButtonUP() {
// TODO Auto-generated method stub
if(popupWindow!=null)
popupWindow.dismiss();
popupWindow=null;
}
});
}
代码模块结构图
跟之前的和在一起,就有如下图: