自定义View--你要掌握的基本知识

来源:互联网 发布:2d游戏美工 编辑:程序博客网 时间:2024/05/22 17:06

View的基础知识

注1:本文内容纯作者手打原创,如需转载请注明出处。

注2:作者目前在找工作,初级安卓工程师的水平如有需要的请留言或私信,万分感谢。

开篇

作为android中承担可视化功能的控件,虽然View不是四大组件,不过它的作用有时候可比四大组件更重要,android官方给我盟提供了很多的基础控件,不过很多时候这些控件无法满足欧文们的需求,因此,我们需要根据现有的需求,结合基础控件来自定义View实现我们想要的功能,不过在自定义View之前,先要对View的基础知识有一定的了解才可以。在此特别感谢徐宜生先生的书,对于View方面的知识讲的十分到位,获益匪浅,特此感谢,(怎么感觉我不是在写博客,像是在买书啊?)

参数基础

在自定义View的时候通常都会需要获得View的当前坐标啊,移动距离啊等,对于View的获得当前参数的方式有很多,先看下图,之后在一一说明。

图片来自徐宜生先生的书《Android群英传》

通过上图我们可以清楚明了的知道对于view的各种get方法所获得的值所代表的含义,中间的圆点指的是事件的触摸点。上图中的方法我就不解释了,说几个图中没有的。

从Android3.0开始View增加了几个额外的参数:x,y,translationX,translationY,其中x,y是指View的左上角坐标,translationX与translationY是指View的左上角相对于父容器的偏移量,这几个参数也都是相对于父容器,并且translationX与translationY默认是0。

x=left+translationX;

y=top+translationY;

需要关注的是在View的平移过程中或者滑动过程中(分具体的滑动实现),top和left是指原始的左上角位置信息,其值不会发生改变,而x,y,translationX,translationY发生改变。

事件托管

MotionEvent,可以参考我之前写的博客android中事件分发机制 ,这里就不多说了。

TouchSlop在之前的文章中出现过,在这里简单的介绍一下,TouchSlop是系统能够识别出的被认为是滑动的最小距离,就是说,当手指在屏幕上滑动的时候,如果两次滑动的距离小于这个常量值,系统就不认为你在进行滑动操作。通常我们可以用一下代码来获得这个参数

 ViewConfiguration.get(getApplicationContext()).getScaledTouchSlop();

其中需要一个Context对象。

事件处理帮助类:
VelocityTracker 速度追踪者,用于追踪手指在滑动过程中的速度,包括水平方向和竖直放量两种,使用方式:

 @Overridepublic boolean onTouchEvent(MotionEvent event) {    //创建对象    VelocityTracker velocityTracker=VelocityTracker.obtain();    //添加事件    velocityTracker.addMovement(event);    //设置计算时间    velocityTracker.computeCurrentVelocity(1000);    //获得轴向速度    int xVelocity= (int) velocityTracker.getXVelocity();    int yVelocity= (int) velocityTracker.getYVelocity();    //重置并回收    velocityTracker.clear();    velocityTracker.recycle();}

需要注意的有两点,一是在获得速度之前要先调用设置计算时间的方法,二是速度的计算是终止位置减去起始位置之后再除以时间,所以速度可以为负值。最后记得清一下,回收。

GestureDetector 手势处理者。用于辅助检测用户的单击,滑动,长按,双击等行为。使用方式也不复杂,主要就是明白和熟悉对应的接口就可以。

public boolean onTouchEvent(MotionEvent event) {    GestureDetector gestureDetector=new GestureDetector(this, new GestureDetector.OnGestureListener() {        //手指触摸屏幕的一瞬间,由一个ACTION_DOWN触发        @Override        public boolean onDown(MotionEvent e) {            return false;        }        //手指触摸屏幕,尚未松开或拖动。        @Override        public void onShowPress(MotionEvent e) {        }        //手指(轻轻触摸屏幕后)松开,伴随着一个ACTION_UP事件        //单击行为        @Override        public boolean onSingleTapUp(MotionEvent e) {            return false;        }        //手指按下并拖动,由一个ACTION_DOEN和多个ACTION_MOVE触发,        //拖动行为        @Override        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {            return false;        }        //用户长久地按住屏幕不放,长按行为        @Override        public void onLongPress(MotionEvent e) {        }        //用户按下屏幕,快速滑动松开,由一个DOWN,多个MOVE,一个UP事件触发        //快速滑动行为        @Override        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {            return false;        }    });    gestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {        //严格意义上的单击行为,在执行了此方法之后不可能在跟着一个单击行为        //就是只可能是单击行为,不可能是双击中的一次单击行为。        @Override        public boolean onSingleTapConfirmed(MotionEvent e) {            return false;        }        //双击,由两次连续的点击组成,不能与onSingleTapConfirmed共存        //注意可能会出现重复执行onSingleTapUp单击事件的情况。(猜测)        @Override        public boolean onDoubleTap(MotionEvent e) {            return false;        }        //表示发生了双击行为,在双击的期间都会触发此方法        @Override        public boolean onDoubleTapEvent(MotionEvent e) {            return false;        }    });    gestureDetector.setContextClickListener(new GestureDetector.OnContextClickListener() {        //在上下文在被点击的时候调用(API23)        @Override        public boolean onContextClick(MotionEvent e) {            return false;        }    });    boolean consume=gestureDetector.onTouchEvent(event);    return consume;

代码中已经把每个方法的回调时机和所代表的行为都进行了注释,应该都能看懂,一共有三个接口我们可以去实现,不过通常情况下不会需要这么多,而且对于这么多接口和方法,我们在使用的时候也不方便,所有android中已经帮我能写好了一个实现类SimpleOnGestureListener,这个类实现了上面的三个接口,在使用的时候重写里面的方法就可以了。这样关于手势处理者的介绍就结束了。

ViewDragHelper拖动手势处理者,用于处理View的拖拽检测和处理。在我之前的博客有详细的说明,可以移步到ViewDragHelper的源码分析,里面有详细的说明。

Scroller 弹性滑动对象,用于实现View的弹性滑动。这个类的使用网上有很多,大家可以自行参考。

通过以上的介绍,对于View中事件的处理大家应该有了一定的认识,在实际的开发中可以根据需要来使用不同的帮助类来实现想要的效果,但是也不要忘了这些辅助的本质都是对MotionEvent中事件的处理,有时候可以不用辅助类,直接在onTouchEvent方法中就行判断。

滑动解决方案

对于View的滑动解决方案有很多种,以下是《群英传》中介绍的七种方法。

  1. layout方法:改变onLayout(Layout)布局时的参数。
  2. offsetLeftAndRight与offsetTopAndBottom :对左右,上下移动的APi的封装,效果跟layout方法一样。
  3. LayoutParams:LayoutParams保存了一个View的布局参数,可以动态的改变布局参数中的某一个属性,并重新设置给View,实现View的滑动。注意在获取这个参数的时候要根据父容器的类型还获得不同的LayoutParams。推荐使用ViewGroup.MarginLayoutParams来实现。
  4. scrollTo与scrollBy方法:移动的是View的内容而不是Vi额外本身,scrollTo表示移动到指定位置,scrollBy表示相对于现在的位置移动到指定位置。注意是瞬间执行。
  5. Scroller:具有过渡效果的移动,这是与scrollTo,scrollBy的最大的区别。
  6. 动画:可以使用属性动画,补间动画,帧动画,来实现View的滑动。优缺点应该都清楚。最新的方式还可以使用Material Design的方式来实现(对这个目前了解的不多,就不多说了)。
  7. ViewDragHelper:推荐大家使用的一个帮助类,可以参考之前我写的博客。

对于这七中方法,可以根据实际情况来选择,当个使用或组合使用多可以,当然还有一些其他的方法也能实现滑动,也不更多介绍了(其实我也不知道还有什么。重写onDraw?),学会这七种在处理滑动的时候就够用了。

总结

对于自定义View来说,View的参数获取,辅助的帮助类,滑动的解决方案,是我们应该了解的。这篇文章对自定义View的基础知识进行了一些总结,希望可以帮助大家。文中有不对的地方,请不吝赐教。

同样在最后说一句,在找工作。。。

0 0
原创粉丝点击