企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
#### 3.2.4 各种滑动方式的对比 上面分别介绍了三种不同的滑动方式,它们都能实现View的滑动,那么它们之间的差别是什么呢? 先看scrollTo/scrollBy这种方式,它是View提供的原生方法,其作用是专门用于View的滑动,它可以比较方便地实现滑动效果并且不影响内部元素的单击事件。但是它的缺点也是很显然的:它只能滑动View的内容,并不能滑动View本身。 再看动画,通过动画来实现View的滑动,这要分情况。如果是Android 3.0以上并采用属性动画,那么采用这种方式没有明显的缺点;如果是使用View动画或者在Android 3.0以下使用属性动画,均不能改变View本身的属性。在实际使用中,如果动画元素不需要响应用户的交互,那么使用动画来做滑动是比较合适的,否则就不太适合。但是动画有一个很明显的优点,那就是一些复杂的效果必须要通过动画才能实现。 最后再看一下改变布局这种方式,它除了使用起来麻烦点以外,也没有明显的缺点,它的主要适用对象是一些具有交互性的View,因为这些View需要和用户交互,直接通过动画去实现会有问题,这在3.2.2节中已经有所介绍,所以这个时候我们可以使用直接改变布局参数的方式去实现。 针对上面的分析做一下总结,如下所示。 * scrollTo/scrollBy:操作简单,适合对View内容的滑动; * 动画:操作简单,主要适用于没有交互的View和实现复杂的动画效果; * 改变布局参数:操作稍微复杂,适用于有交互的View。 下面我们实现一个跟手滑动的效果,这是一个自定义View,拖动它可以让它在整个屏幕上随意滑动。这个View实现起来很简单,我们只要重写它的onTouchEvent方法并处理ACTION_MOVE事件,根据两次滑动之间的距离就可以实现它的滑动了。为了实现全屏滑动,我们采用动画的方式来实现。原因很简单,这个效果无法采用scrollTo来实现。另外,它还可以采用改变布局的方式来实现,这里仅仅是为了演示,所以就选择了动画的方式,核心代码如下所示。 ``` public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getRawX(); int y = (int) event.getRawY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { break; } case MotionEvent.ACTION_MOVE: { int deltaX = x - mLastX; int deltaY = y - mLastY; Log.d(TAG, "move, deltaX:" + deltaX + " deltaY:" + deltaY); int translationX = (int)ViewHelper.getTranslationX(this) + deltaX; int translationY = (int)ViewHelper.getTranslationY(this) + deltaY; ViewHelper.setTranslationX(this, translationX); ViewHelper.setTranslationY(this, translationY); break; } case MotionEvent.ACTION_UP: { break; } default: break; } mLastX = x; mLastY = y; return true; } ``` 通过上述代码可以看出,这一全屏滑动的效果实现起来相当简单。首先我们通过getRawX和getRawY方法来获取手指当前的坐标,注意不能使用getX和getY方法,因为这个是要全屏滑动的,所以需要获取当前点击事件在屏幕中的坐标而不是相对于View本身的坐标;其次,我们要得到两次滑动之间的位移,有了这个位移就可以移动当前的View,移动方法采用的是动画兼容库nineoldandroids中的ViewHelper类所提供的setTranslationX和setTranslationY方法。实际上,ViewHelper类提供了一系列get/set方法,因为View的setTranslationX和setTranslationY只能在Android 3.0及其以上版本才能使用,但是ViewHelper所提供的方法是没有版本要求的,与此类似的还有setX、setScaleX、setAlpha等方法,这一系列方法实际上是为属性动画服务的,更详细的内容会在第5章进行进一步的介绍。这个自定义View可以在2.x及其以上版本工作,但是由于动画的性质,如果给它加上onClick事件,那么在3.0以下版本它将无法在新位置响应用户的点击,这个问题在前面已经提到过。