android自定义View之3D索引效果
效果图:
我的小霸王太卡了。
最近工作比较忙,今天搞了一下午才搞出来这个效果,这种效果有很多种实现方式,最常见的应该是用贝塞尔曲线实现的。今天我们来看另一种不同的实现方式,只需要用到 canvas.scale(),有没有很好奇是怎么实现的呢。
首先来说一下思路,只要有了思路剩下的就是往里面套代码了。
通过观察上面的效果图我们发现可以把右边的字母分为三种类型
1、 手指没触摸的地方显示正常的样式
2、手指触摸的位置 显示最大且完全不透明
3、手指触摸位置的上下附近位置 有放大且有透明度变化
对这个效果有了直观的认识后,我们就可以在ondraw里面根据不同的条件来分别画出这三种状态,这里主要难理解的就是这些条件。这需要结合代码看下。
so 我们开始撸码吧,
1、先初始化一些需要的变量
private void init(Context context) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.GRAY);
mLetters = context.getResources().getStringArray(R.array.letter_list);
mPaint.setTextAlign(Paint.Align.CENTER);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mDensity = getContext().getResources().getDisplayMetrics().density;
setPadding(0,dip2px(20),0,dip2px(20));
}
private int dip2px(int dipPx){
return (int)(dipPx*mDensity+0.5);
}
相信上面这些应该没什么难度吧。
另外把一些需要的宽高属性赋值一下,因为下面会用到它们
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHeight = h - getPaddingTop() - getPaddingBottom();
mWidth = w - dip2px(16);
mLetterHeight = mHeight / mLetters.length;
int textSize = (int)(mLetterHeight*0.7);
mPaint.setTextSize(textSize);
mIsDownRect.set(w-dip2px(32),0,w,h);
}
这里主要就是mIsDownRect这个要注意一下它是索引列表的范围,但是我们并不需要画出它。
2、在ontouch方法中对触摸事件进行必要的处理
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
mIsBeingDragger = false;
float initDownY = event.getY();
if(!mIsDownRect.contains(event.getX(),event.getY())){
return false;
}
mInitDownY = initDownY;
break;
case MotionEvent.ACTION_MOVE:
float y = event.getY();
float diff = Math.abs(y - mInitDownY);
if(diff>mTouchSlop&&!mIsBeingDragger){
mIsBeingDragger = true;
}
if(mIsBeingDragger){
mY = y;
float moveY = y - getPaddingTop();
int chartIndex = (int) (moveY / mHeight * mLetters.length);//获取索引位置的index
if(mChoose!=chartIndex){
if(chartIndex>=0&&chartIndex<mLetters.length) {
if (slidViewListener != null) {
Log.i("lly","chartIndex = "+chartIndex);
slidViewListener.onChange(mLetters[chartIndex]);
}
mChoose = chartIndex;
}
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mIsBeingDragger = false;
mChoose = -1;
invalidate();
break;
}
return true;
}
这里面也很简单,首先当手指按下时记录下按下位置的Y坐标,然后判断按下的位置是否在索引列表的区域范围内(索引的区域在初始化赋值的时候已经确定过了)如果不在就没必要执行下去了 直接返回false即可,
然后在手指移动的时候判断下是否是在移动是的话就把mIsBeingDragger置为true,如果mIsBeingDragger为true说明正在移动 ,这时候就计算出当前手指所在的索引位置,并通过回调方式通知外面当前的位置,最后把索引位置赋给全局变量mChoose,并刷新UI。
手指抬起时进行一些复位操作。
以上就是ontouch的全部方法。
3、在ondraw方法里面画出索引字母
这里要画出那三种类型的字母索引,我们先从简单的来
float lettersPos= mLetterHeight*(i+1)+getPaddingTop(); //下一个字母的Y值坐标
float diffY; // Y 方向的偏移量
float diffX;//X 方向的偏移量
float diff;//缩放比例
if (mChoose == i&&i!=0&&i!=mLetters.length-1) {
diff = 2.2f;
diffX=0f;
diffY=0f;
}
mChoose 是在ontouch中我们记录的索引位置,当上面条件成立时说明当前就是选中的字母,这时候让它缩放比例最大,偏移量我们会在下面统一处理。
接下来处理不是选中的情况
float distanseDiff = Math.abs((mY - lettersPos)/mHeight);//计算手指触摸位置的上下附近位置
float maxPos = distanseDiff * 7;//乘7是因为这个系数太小了需要给他一个放大
if(distanseDiff<0.174){
diff = 2.2f - maxPos;
}else {
diff = 1f;
}
if(!mIsBeingDragger){
diff =1;
}
diffX = maxPos * 50;
if(mY>lettersPos){
diffY = maxPos*50;
}else {
diffY = - maxPos*50;
}
这里主要就是那个缩放系数比较难算 需要多试下。
X Y方向的偏移量如下图
这些都计算好后就可以画了
canvas.save();
canvas.scale(diff,diff,mWidth*1.2f+diffX,lettersPos+diffY);
if(diff ==1){
mPaint.setAlpha(255);
mPaint.setTypeface(Typeface.DEFAULT);
}else {
int alpha = (int) (255*(1-Math.min(0.9,diff -1)));
if(mChoose == i){
alpha = 255;
}
mPaint.setAlpha(alpha);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
Log.i("lly","mLetters["+i+"] = " +mLetters[i] );
canvas.drawText(mLetters[i],mWidth,lettersPos,mPaint);
canvas.restore();
可以发现canvas.scale(diff,diff,mWidth*1.2f+diffX,lettersPos+diffY); 这一句才是整个自定义view的关键 它前两个参数是x轴和y轴的缩放系数,后两个参数是x轴和y轴的锚点,我主要是试出来的,这两个参数比较难理解,还需要多家学习。到这里就已经实现了我们最上面的效果了。
android自定义View之3D索引效果的更多相关文章
- Android 自定义view实现水波纹效果
http://blog.csdn.net/tianjian4592/article/details/44222565 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了 ...
- android自定义view实现progressbar的效果
一键清理是很多Launcher都会带有的功能,其效果也比较美观.实现方式也许有很多中,其中常见的是使用图片drawable来完成的,具体可以参考这篇文章:模仿实现360桌面水晶球式的一键清理特效.本文 ...
- Android自定义View——刮刮卡效果
想要红包的实现效果的可以关注我的博客,仿饿了么红包 下层图片:我们的红包的图片 上层图片:有两部分 一部分是灰色背景 一部分是拥有透明度为0,并且模式为交集的画笔 使用滑动监听,滑动时,用透明度为0的 ...
- Android自定义View 画弧形,文字,并增加动画效果
一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类 B ...
- Android自定义View(LimitScrollerView-仿天猫广告栏上下滚动效果)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53303872 本文出自:[openXu的博客] 1分析 2定义组合控件布局 3继承最外层控件 ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- Android自定义View和控件之一-定制属于自己的UI
照例,拿来主义.我的学习是基于下面的三篇blog.前两是基本的流程,第三篇里有比较细致的绘制相关的属性.第4篇介绍了如何减少布局层次来提高效率. 1. 教你搞定Android自定义View 2. 教你 ...
- Android自定义View(CustomCalendar-定制日历控件)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/54020386 本文出自:[openXu的博客] 目录: 1分析 2自定义属性 3onMeas ...
- 简单说说Android自定义view学习推荐的方式
这几天比较受关注,挺开心的,嘿嘿. 这里给大家总结一下学习自定义view的一些技巧. 以后写自定义view可能不会写博客了,但是可以开源的我会把源码丢到github上我的地址:https://git ...
随机推荐
- requests+xpath+map爬取百度贴吧
# requests+xpath+map爬取百度贴吧 # 目标内容:跟帖用户名,跟帖内容,跟帖时间 # 分解: # requests获取网页 # xpath提取内容 # map实现多线程爬虫 impo ...
- filter过滤器与map映射
filter过滤器 >>> list(filter(None,[0,1,2,True,False])) [1, 2, True] filter的作用就是后面的数据按照前面的表达式运算 ...
- 关于手机APP开发的一些常见误解
移动应用不适用于小型企业和创业公司 如果你想要开发一款移动APP,那么在前期开发一种偏见的态度并不是一个好主意.如果你认为移动APP只有跨国公司和大企业创业者才会去开发,那么你可能错过了成功的捷径.而 ...
- [LeetCode] Remove Boxes 移除盒子
Given several boxes with different colors represented by different positive numbers. You may experie ...
- [JSOI2007]麻将
Description 麻将是中国传统的娱乐工具之一.麻将牌的牌可以分为字牌(共有东.南.西.北.中.发.白七种)和序数 牌(分为条子.饼子.万子三种花色,每种花色各有一到九的九种牌),每种牌各四张. ...
- [HNOI2012]排队
题目描述 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的) 输入输 ...
- [NOI2005]寿司晚宴
题目描述 为了庆祝NOI的成功开幕,主办方为大家准备了一场寿司晚宴.小G和小W作为参加NOI的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了n−1种不同的寿司,编号1,2,3,⋯,n-1 ...
- 【LSGDOJ1383】修改回文 dp
题目描述 为了跟踪所有的牛,农夫JOHN在农场上装了一套自动系统. 他给了每一个头牛一个电子牌号 当牛走过这个系统时,牛的名字将被自动读入. 每一头牛的电子名字是一个长度为M (1 <= M & ...
- NOIP2014-10-30模拟赛
T1:逗比三角形 [题目描述] 小J是一名OI退役滚粗文化课选手,他十分喜欢做题,尤其是裸题.他现在有一个二维盒子和一些二维三角形,这个盒子拥有无限的高度和L的宽度.而且他的三角形也都是一些锐角三角形 ...
- 2015 多校联赛 ——HDU5371(manacher + 枚举)
Sample Input 1 10 2 3 4 4 3 2 2 3 4 4 Sample Output Case #1: 9 要求找出一段数字. 将其分成3部分,第①和第②部分成回文字串,第②和第 ...