Android墨迹3.0特性介绍效果实现

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

前期准备

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

翻页控件实现

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

@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int count = getChildCount();int height = getMeasuredHeight();int top = 0;for (int i = 0; i < count; ++i) {View childView = getChildAt(i);if (childView.getVisibility() != View.GONE) {childView.layout(l, top, r, top + height);top += height;}}mTotalHeight = height * (count – 1);mTolerance = height / 2;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int count = getChildCount();for (int i = 0; i < count; ++i) {View childView = getChildAt(i);measureChild(childView, widthMeasureSpec, heightMeasureSpec);}}这里在onLayout方法中将页面排下来,每页内容都充满控件,垂直排列。

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

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

@Overridepublic boolean onTouchEvent(MotionEvent event) {if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();}mVelocityTracker.addMovement(event);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:if (!mScroller.isFinished()) {mScroller.abortAnimation();}mLastY = (int) event.getY();mStartYPosition = getScrollY();break;case MotionEvent.ACTION_MOVE:int y = (int) event.getY();int distance = mLastY – y;int scrollY = getScrollY();// 边界检查if (distance < 0 && scrollY + distance < 0) {distance = 0 – scrollY;} else if (distance > 0 && scrollY + distance > mTotalHeight) {distance = mTotalHeight – scrollY;}scrollBy(0, distance);mLastY = y;break;case MotionEvent.ACTION_UP:mEndYPosition = getScrollY();int posDiff = mEndYPosition – mStartYPosition;mVelocityTracker.computeCurrentVelocity(1000);int velocityY = (int) mVelocityTracker.getYVelocity();mVelocityTracker.recycle();mVelocityTracker = null;if (Math.abs(velocityY) >= 600 || Math.abs(posDiff) > mTolerance) {int dis = 0;if (posDiff > 0) {dis = getMeasuredHeight() – posDiff;} else if (posDiff < 0) {dis = -(getMeasuredHeight() + posDiff);}mScroller.startScroll(0, 0, 0, dis);} else {mScroller.startScroll(0, 0, 0, -posDiff);}postInvalidate();break;default:break;}return true;}上面的这些操作包括了滚动、边界检查(避免滑出边界)和完成翻页的功能,最开始其实是这样的@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mLastY = (int) event.getY();break;case MotionEvent.ACTION_MOVE:int y = (int) event.getY();int distance = mLastY – y;scrollBy(0, distance);mLastY = y;break;case MotionEvent.ACTION_UP:break;default:break;}return true;}页面可以随着手指上下滚动,但是会超出边界,再添加上边界检查,就是修改一下ACTION_MOVE,case MotionEvent.ACTION_MOVE:int y = (int) event.getY();int distance = mLastY – y;int scrollY = getScrollY();// 边界检查if (distance < 0 && scrollY + distance < 0) {distance = 0 – scrollY;} else if (distance > 0 && scrollY + distance > mTotalHeight) {distance = mTotalHeight – scrollY;}scrollBy(0, distance);mLastY = y;break;这时候再滚动的时候就会发现到达边界的时候就无法再滑动了,下面再添加滑动半屏后自动完成翻页的功能,就是最上面的那个完整的代码,里面用到了scroller,在抬起手指的时候计算滚动剩余距离,然后开始滚动,scroller只负责完成滚动过程位置的计算,真正控制页面的是在computeScroll()方法里:@Overridepublic void computeScroll() {if (mScroller.computeScrollOffset()) {int scroll = mScroller.getCurrY();if (scroll > 0 && mEndYPosition + scroll > mTotalHeight) {scroll = mTotalHeight – mEndYPosition;} else if (scroll < 0 && mEndYPosition + scroll < 0) {scroll = -mEndYPosition;}scrollTo(0, mEndYPosition + scroll);mIsScrolling = true;postInvalidate();} else if (mIsScrolling) {if (mPageScrollListener != null) {int position = getScrollY() / getMeasuredHeight();if (position != mCurrentPage) {mCurrentPage = position;mPageScrollListener.onPageChanged(mCurrentPage);}}mIsScrolling = false;}}每次页面重绘都会调用computeScroll方法,然后通过scroller得到此时的滚动值,再次重绘,直到滚动结束,这里也做了下边界检测,防止滚过头了。当你能飞的时候就不要放弃飞

Android墨迹3.0特性介绍效果实现

相关文章:

你感兴趣的文章:

标签云: