Android界面滑动切换:MotionEvent、GestureListener及ViewPager
2017-03-07 13:32
399 查看
这篇博客记录一下Android界面滑动切换的几种方式。
来判断用户是否进行了滑动的操作。
我们看看对应实现中最核心的代码:
如果需要计算滑动速度,可以使用VelocityTracker。
其使用方法类似于:
示例代码如下:
为了整个切换工程更加平滑,可以在startActivity和finish后,利用overridePendingTransition接口实现一些动画效果。
上述demo的效果类似于下图:
demo代码下载地址
而且滑动效果不够强大。
例如,一旦滑动后,就会直接切换到另一个Activity;
不能做到:在切换的过程中展示下一个Activity,同时在切换过程中取消本次切换。
此时,就轮到ViewPager上场了。当利用ViewPager时,最好与Fragment组合使用。
我们将上面的FirstActivity和SecondActivity均转变为Fragment,如下:
然后,引入support-v4包后,利用Activity管理这两个Fragment:
Activity的布局中直接使用ViewPager:
其代码如下:
按照上述代码,就可以更简洁的实现滑动效果。
如下图所示,仍然可以有效滑动:
此外,还可以跟随手指取消滑动切换。
demo下载地址
1、监听MotionEvent
通过监听MotionEvent来进行滑动切换的原理,实际上是比较MotionEvent初始的坐标及移动后的坐标,来判断用户是否进行了滑动的操作。
我们看看对应实现中最核心的代码:
public class FirstActivity extends AppCompatActivity { .............. @Override public boolean onTouchEvent(MotionEvent event) { ........... switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: //每次手指落下时,均记录初始横坐标 mOrigin = event.getX(); break; case MotionEvent.ACTION_MOVE: //手指移动时,记录移动后的横坐标 float move = event.getX(); ................. //当移动距离大于门限后,就可以跳转了 //这里实现左滑切换,因此要求orgin的横坐标 > move的横坐标 if ((mOrigin - move > MIN_MOVE_INSTANCE) //此外,还可以判断移动速度是否大于门限 //由于手指移动时,会多次触发ACTION_MOVE,因此引入一个标志位,避免多次启动 && (speed > SPEED_MIN) && !mAlreadyJump){ Log.d("ZJTest", "go to second activity"); startActivity(new Intent(this, SecondActivity.class)); ..................... mAlreadyJump = true; } break; case MotionEvent.ACTION_UP: .................. //手指离开屏幕后,重置mAlreadyJump mAlreadyJump = false; break; default: return super.onTouchEvent(event); } return true; } }
如果需要计算滑动速度,可以使用VelocityTracker。
其使用方法类似于:
................... @Override public boolean onTouchEvent(MotionEvent event) { //让VelocityTracker监控event addEventToVelocityTracker(event); switch (event.getAction() & MotionEvent.ACTION_MASK) { .......... case MotionEvent.ACTION_MOVE: ...... /获取event的速度 float speed = getScrollVelocity(); ..... break; case MotionEvent.ACTION_UP: //回收Velocity recycleVelocityTracker(); ..... break; ......... } return true; } private VelocityTracker mVelocityTracker; private void addEventToVelocityTracker(MotionEvent event) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } //利用addMovement监控event mVelocityTracker.addMovement(event); } private void recycleVelocityTracker() { //利用recycle接口回收VelocityTracker mVelocityTracker.recycle(); mVelocityTracker = null; } private float getScrollVelocity() { //利用computeCurrentVelocity计算速度,参数为单位时间 mVelocityTracker.computeCurrentVelocity(1000); //getXVelocity用于获取水平方向的速度 return Math.abs(mVelocityTracker.getXVelocity()); } .............
2、使用GestureDetector
除了直接监听MotionEvent外,还可以利用GestureDetector完成类似的功能。示例代码如下:
public class SecondActivity extends AppCompatActivity { //这里使用的是兼容库中的GestureDetector GestureDetectorCompat mGestureDetector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); //与实现OnGestureListener的本地类配合使用 mGestureDetector = new GestureDetectorCompat( this, new LocalGestureListener()); } /** * Called to process touch screen events. You can override this to * intercept all touch screen events before they are dispatched to the * window. Be sure to call this implementation for touch screen events * that should be handled normally. * * @param ev The touch screen event. * * @return boolean Return true if this event was consumed. */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { //如上面源代码的注释,此处拦截MotionEvent给GestureDetector处理 mGestureDetector.onTouchEvent(ev); return super.dispatchTouchEvent(ev); } ............. private class LocalGestureListener implements GestureDetector.OnGestureListener { @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //同样利用横坐标和移动速度,判断是否需要切换Activity、 //这里实现的是,右滑切换,因此要求后一个点的横坐标大于前一个点 float move = e2.getX() - e1.getX(); if (move > MIN_MOVE_INSTANCE && velocityX > SPEED_MIN) { Log.d("ZJTest", "go to the first activity"); //由于FirstActivity启动的SecondActivity,因此SecondActivity finish后就回到了前一个Activity finish(); ................ } return true; } } }
为了整个切换工程更加平滑,可以在startActivity和finish后,利用overridePendingTransition接口实现一些动画效果。
上述demo的效果类似于下图:
demo代码下载地址
3、使用ViewPager
上述监听MotionEvent或者使用GestureListener均有些重复造轮子的感觉,而且滑动效果不够强大。
例如,一旦滑动后,就会直接切换到另一个Activity;
不能做到:在切换的过程中展示下一个Activity,同时在切换过程中取消本次切换。
此时,就轮到ViewPager上场了。当利用ViewPager时,最好与Fragment组合使用。
我们将上面的FirstActivity和SecondActivity均转变为Fragment,如下:
public class FirstFragment extends Fragment { public static FirstFragment newInstance() { return new FirstFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { return inflater.inflate(R.layout.fragment_first, container, false); } }
public class SecondFragment extends Fragment { public static SecondFragment newInstance() { return new SecondFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { return inflater.inflate(R.layout.fragment_second, container, false); } }
然后,引入support-v4包后,利用Activity管理这两个Fragment:
Activity的布局中直接使用ViewPager:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/view_pager" android:layout_height="match_parent" android:layout_width="match_parent"/>
其代码如下:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //定义数据 final Map<Integer, Fragment> data = new TreeMap<>(); data.put(0, FirstFragment.newInstance()); data.put(1, SecondFragment.newInstance()); //找到ViewPager ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager); //为ViewPager配置Adapter viewPager.setAdapter(new FragmentStatePagerAdapter( getSupportFragmentManager()) { @Override public Fragment getItem(int position) { return data.get(position); } @Override public int getCount() { return data.size(); } }); } }
按照上述代码,就可以更简洁的实现滑动效果。
如下图所示,仍然可以有效滑动:
此外,还可以跟随手指取消滑动切换。
demo下载地址
相关文章推荐
- Android之Fragment+ViewPager实现点击+滑动界面切换学习笔记
- 【Android开发日记】左右滑动刷新界面的思路记录 ViewPager GestureDetector
- 【Android 界面效果1】ViewPager多页面滑动切换以及动画效果
- android app主题UI界面框架搭建 tablayout+Viewpager+fragment 导航栏滑动和点击切换界面
- Android UI设计(引导界面):ViewPager之二滑动切换效果
- 基于android的网络音乐播放器-添加viewpager和fragment实现滑动切换多个界面(二)
- Android 安卓 fragment+viewpager 仿qq界面 实现点击菜单切换界面+滑动切换viewpager切换界面
- 【Android 界面效果1】ViewPager多页面滑动切换以及动画效果
- Android 实现多页界面左右滑动切换效果之入门+进阶 (ViewPager+PagerAdapter)
- Android ViewPager多页面滑动切换以及动画效果
- Android ViewPager多页面滑动切换以及动画效果
- Android ViewPager 实现多个页面切换滑动
- android-运用ViewGroup完成左右滑动切换界面以及界面裂开的作用
- Android ViewPager多页面滑动切换以及动画效果!!!
- Android ViewPager多页面滑动切换以及动画效果
- Android ViewPager多页面滑动切换以及动画效果
- Android ViewPager多页面滑动切换以及动画效果
- [Android实例] ViewPager多页面滑动切换以及动画效果
- Android ViewPager多页面滑动切换以及动画效果
- Android中用ViewPager实现多页面滑动切换及动画效果的实例