0
点赞
收藏
分享

微信扫一扫

Android墨迹3.0特性介绍效果实现——做一个垂直滚动的Layout



墨迹天气新版的开机介绍很漂亮,上下滚动翻页,翻页结束后元素会有动画效果,分析一下动画元素都是基本的Animation,没有用到最新的属性动画;上下翻页滚动的控件android没有提供,只有横向的Viewpager,这里有一种实现->点击打开链接,用到了开源的控件ViewPager-Android,我们这里试着手动实现一个上下滚动的翻页控件。

前期准备

首先我们用apktool把墨迹天气的安装包解压出来,取出其中的图片资源和布局文件,一共4个布局


Android墨迹3.0特性介绍效果实现——做一个垂直滚动的Layout_android

翻页控件实现

要实现自定义布局,需要继承ViewGroup,然后实现onMeasure、onLayout方法


[java]  view plain  copy


 print

?


  1. @Override  
  2. protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  3. int count = getChildCount();  
  4. int height = getMeasuredHeight();  
  5. int top = 0;  
  6. for (int i = 0; i < count; ++i) {  
  7.             View childView = getChildAt(i);  
  8. if (childView.getVisibility() != View.GONE) {  
  9.                 childView.layout(l, top, r, top + height);  
  10.                 top += height;  
  11.             }  
  12.         }  
  13. 1);  
  14. 2;  
  15.     }  
  16.   
  17. @Override  
  18. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  19. super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  20. int count = getChildCount();  
  21. for (int i = 0; i < count; ++i) {  
  22.             View childView = getChildAt(i);  
  23.             measureChild(childView, widthMeasureSpec, heightMeasureSpec);  
  24.         }  
  25.     }  



这里在onLayout方法中将页面排下来,每页内容都充满控件,垂直排列。

这时候在如果在activity中将View inflate出来再通过addview添加到控件中就会看到第一页的内容,但此时还不能滑动。下面我们就来实现上下滑动翻页。

要响应控件上的手势操作需要实现onTouchEvent方法:


[java]  view plain  copy


 print

?


  1. @Override  
  2. public boolean onTouchEvent(MotionEvent event) {  
  3.   
  4. if (mVelocityTracker == null) {  
  5.         mVelocityTracker = VelocityTracker.obtain();  
  6.     }  
  7.     mVelocityTracker.addMovement(event);  
  8.   
  9. switch (event.getAction()) {  
  10. case MotionEvent.ACTION_DOWN:  
  11. if (!mScroller.isFinished()) {  
  12.             mScroller.abortAnimation();  
  13.         }  
  14. int) event.getY();  
  15.         mStartYPosition = getScrollY();  
  16. break;  
  17. case MotionEvent.ACTION_MOVE:  
  18. int y = (int) event.getY();  
  19. int distance = mLastY - y;  
  20. int scrollY = getScrollY();  
  21. // 边界检查  
  22. if (distance < 0 && scrollY + distance < 0) {  
  23. 0 - scrollY;  
  24. else if (distance > 0 && scrollY + distance > mTotalHeight) {  
  25.             distance = mTotalHeight - scrollY;  
  26.         }  
  27. 0, distance);  
  28.         mLastY = y;  
  29. break;  
  30. case MotionEvent.ACTION_UP:  
  31.   
  32.         mEndYPosition = getScrollY();  
  33. int posDiff = mEndYPosition - mStartYPosition;  
  34.   
  35. 1000);  
  36. int velocityY = (int) mVelocityTracker.getYVelocity();  
  37.         mVelocityTracker.recycle();  
  38. null;  
  39.   
  40. if (Math.abs(velocityY) >= 600 || Math.abs(posDiff) > mTolerance) {  
  41. int dis = 0;  
  42. if (posDiff > 0) {  
  43.                 dis = getMeasuredHeight() - posDiff;  
  44. else if (posDiff < 0) {  
  45.                 dis = -(getMeasuredHeight() + posDiff);  
  46.             }  
  47. 0, 0, 0, dis);  
  48. else {  
  49. 0, 0, 0, -posDiff);  
  50.         }  
  51.   
  52.         postInvalidate();  
  53. break;  
  54. default:  
  55. break;  
  56.     }  
  57.   
  58. return true;  
  59. }  



上面的这些操作包括了滚动、边界检查(避免滑出边界)和完成翻页的功能,最开始其实是这样的


[java]  view plain  copy


 print

?


  1. @Override  
  2. public boolean onTouchEvent(MotionEvent event) {  
  3.   
  4. switch (event.getAction()) {  
  5. case MotionEvent.ACTION_DOWN:  
  6. int) event.getY();  
  7. break;  
  8. case MotionEvent.ACTION_MOVE:  
  9. int y = (int) event.getY();  
  10. int distance = mLastY - y;  
  11. 0, distance);  
  12.             mLastY = y;  
  13. break;  
  14. case MotionEvent.ACTION_UP:  
  15. break;  
  16. default:  
  17. break;  
  18.         }  
  19.   
  20. return true;  
  21.     }  



页面可以随着手指上下滚动,但是会超出边界,再添加上边界检查,就是修改一下ACTION_MOVE,


[java]  view plain  copy


 print

?


  1. case MotionEvent.ACTION_MOVE:  
  2. int y = (int) event.getY();  
  3. int distance = mLastY - y;  
  4. int scrollY = getScrollY();  
  5. // 边界检查  
  6. if (distance < 0 && scrollY + distance < 0) {  
  7. 0 - scrollY;  
  8. else if (distance > 0 && scrollY + distance > mTotalHeight) {  
  9.         distance = mTotalHeight - scrollY;  
  10.     }  
  11. 0, distance);  
  12.     mLastY = y;  
  13. break;  



这时候再滚动的时候就会发现到达边界的时候就无法再滑动了,下面再添加滑动半屏后自动完成翻页的功能,就是最上面的那个完整的代码,里面用到了scroller,在抬起手指的时候计算滚动剩余距离,然后开始滚动,scroller只负责完成滚动过程位置的计算,真正控制页面的是在computeScroll()方法里:


[java]  view plain  copy


 print

?


  1. @Override  
  2. public void computeScroll() {  
  3.   
  4. if (mScroller.computeScrollOffset()) {  
  5. int scroll = mScroller.getCurrY();  
  6. if (scroll > 0 && mEndYPosition + scroll > mTotalHeight) {  
  7.             scroll = mTotalHeight - mEndYPosition;  
  8. else if (scroll < 0 && mEndYPosition + scroll < 0) {  
  9.             scroll = -mEndYPosition;  
  10.         }  
  11. 0, mEndYPosition + scroll);  
  12. true;  
  13.         postInvalidate();  
  14. else if (mIsScrolling) {  
  15. if (mPageScrollListener != null) {  
  16. int position = getScrollY() / getMeasuredHeight();  
  17. if (position != mCurrentPage) {  
  18.                 mCurrentPage = position;  
  19.                 mPageScrollListener.onPageChanged(mCurrentPage);  
  20.             }  
  21.         }  
  22. false;  
  23.     }  
  24. }  



每次页面重绘都会调用computeScroll方法,然后通过scroller得到此时的滚动值,再次重绘,直到滚动结束,这里也做了下边界检测,防止滚过头了。

滚动结束后要通知控件的使用者翻页已完成,所以定义一个翻页完成的接口


[java]  view plain  copy


 print

?


  1. public void setOnPageScrollListener(OnPageScrollListener listener) {  
  2.         mPageScrollListener = listener;  
  3.     }  
  4.   
  5. public interface OnPageScrollListener {  
  6. public void onPageChanged(int position);  
  7.     }  



在computeScroll()中发现翻页完成了就调用这个接口。

剩下的就是在activity中加载动画了,每当翻页结束就播放相应页面的动画并清除上一页的动画效果


[java]  view plain  copy


 print

?


  1. class MyPageScrollListener implements OnPageScrollListener {  
  2.   
  3. @Override  
  4. public void onPageChanged(int position) {  
  5. switch (position) {  
  6. case 0:  
  7.                 layout1AnimStart();  
  8. break;  
  9. case 1:  
  10.                 layout2AnimStart();  
  11. break;  
  12. case 2:  
  13.                 layout3AnimStart();  
  14. break;  
  15. case 3:  
  16.                 layout4AnimStart();  
  17. break;  
  18.             }  
  19.         }  
  20.   
  21.     }  


演示效果


Android墨迹3.0特性介绍效果实现——做一个垂直滚动的Layout_viewpager_02

代码在这里->javascript:void(0)


举报

相关推荐

0 条评论