今天和同学用微信聊天,觉得微信联系人右边的字母快速索引挺方便快捷的。高大上。。。。
于是就想着自己也弄一个
首先,这个肯定是一个自定义控件,需要自己绘制A-Z等字母,其次需要自己处理触摸或点击事件
对于自定义控件,首先是确定尺寸。对于高度,直接match_parent,对于宽度,我的处理是不论测量的widthMeasureSpec是多少,统一规定为高度的27分之一(27个字母)。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
height = heightSpecSize;
width = heightSpecSize/COUNT ;
//由VIEW的getdefaultsize源码可知,宽或高都按照EXACTLY处理。因此只需要处理宽度即可
setMeasuredDimension(width,heightSpecSize);
}
然后是在画布上画出字母。对于画出字母的相关知识,可以参考AigoStudio的自定义控件系列<a target=_blank href="http://blog.csdn.net/column/details/androidcustomview.html">http://blog.csdn.net/column/details/androidcustomview.html</a>
这里对字母的画法,最浪费时间,需要把字母恰当的放置,还是比较头疼的。于是乎,上网搜了一下相关文章,还真不少,可惜都比较死板,把textsize直接设置成一个魔数。呃,给跪了。。。,
放弃借鉴,自己重新设计了布局画法。首先是需要得到padding,再根据padding计算可以使用的区域。有了可使用的长和宽,就可以根据字母的数量计算每一个字母可以占用的长度和宽度。
<pre name="code" class="html"> @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// TODO: consider storing these as member variables to reduce
// allocations per draw cycle.
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
int paddingRight = getPaddingRight();
int paddingBottom = getPaddingBottom();
int contentWidth = getWidth() - paddingLeft - paddingRight;
int contentHeight = getHeight() - paddingTop - paddingBottom;
float mSpWidth = DispayUtils.px2sp(mContext, contentWidth);
//float px = DispayUtils.dip2px(mContext, height / mSTR.length());
//float sp = DispayUtils.px2sp(mContext, px);
//canvas.rotate(90, px / 2, px / 2);
mTextPaint.setTextSize(contentWidth);//mSpWidth
mTextPaint.setColor(Color.BLACK);
//
//mTextWidth = mTextPaint.measureText(mSTR.substring(0,1));
//Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
//mTextHeight = fontMetrics.bottom;
int length = mSTR.length();
space = contentHeight/length;
// Draw the text.
for (int i = 0;i<length ;i++) {
mTextWidth = mTextPaint.measureText(mSTR.substring(i,i+1));
canvas.drawText(mSTR.substring(i, i + 1),
paddingLeft + (contentWidth - mTextWidth)/2,
paddingTop + space*(i+1),
mTextPaint);
}
}
最后当然是设计触摸事件。在微信上,字母索引是可以响应触摸滑动的,因此可以不用点击事件,直接上onTouchEvent。微信的字母控件在手中刚触摸到屏幕的时候和滑动的时候都会进行索引操作。因此,只需要对down和move事件进行处理
<pre name="code" class="html">@Override
public boolean onTouchEvent(MotionEvent event) {
//int x = (int)event.getX();
int y = (int)event.getY();
if (event.getAction() == MotionEvent.ACTION_MOVE ||event.getAction() == MotionEvent.ACTION_DOWN){
int position = (int)((y-getPaddingTop()-getPaddingBottom())/space);
//Toast.makeText(mContext,""+mSTR.substring(position,position+1),Toast.LENGTH_SHORT).show();
// LogUtils.log_e(mSTR.substring(position,position+1));
mFloatingButton.setText(mSTR.substring(position,position+1));
mFloatingButton.setVisibility(VISIBLE);
return true;
}else {
mFloatingButton.setVisibility(INVISIBLE);
}
return super.onTouchEvent(event);
}
对于使用过该功能的人来说,可能记得当触摸索引控件的时候,屏幕的中间还有一个透明的悬浮按钮显示当前触摸到的字母。要是有悬浮按钮等悬浮控件,那就需要windowmanager来帮忙了。闲话不多说,直接上代码,至于原理,大家可以去CSDN上找。
private void addFloatingButton(){
mFloatingButton = new Button(mContext);
mFloatingButton.setText("floating");
lp = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,0,0, PixelFormat.TRANSPARENT);
lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
lp.gravity = Gravity.CENTER;
lp.x = 30;
lp.y = 50;
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
wm.addView(mFloatingButton,lp);
mFloatingButton.setVisibility(View.INVISIBLE);
}
大功告成!!!!