墨迹天气新版的开机介绍很漂亮,上下滚动翻页,翻页结束后元素会有动画效果,分析一下动画元素都是基本的Animation,没有用到最新的属性动画;上下翻页滚动的控件android没有提供,只有横向的Viewpager,这里有一种实现->点击打开链接,用到了开源的控件ViewPager-Android,我们这里试着手动实现一个上下滚动的翻页控件。
首先我们用apktool把墨迹天气的安装包解压出来,取出其中的图片资源和布局文件,一共4个布局
要实现自定义布局,需要继承ViewGroup,然后实现onMeasure、onLayout方法
@Override
protected 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;
}
@Override
protected 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);
}
}这时候在如果在activity中将View inflate出来再通过addview添加到控件中就会看到第一页的内容,但此时还不能滑动。下面我们就来实现上下滑动翻页。
要响应控件上的手势操作需要实现onTouchEvent方法:
@Override
public 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;
}
@Override
public 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;
}
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;
@Override
public 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;
}
}滚动结束后要通知控件的使用者翻页已完成,所以定义一个翻页完成的接口
public void setOnPageScrollListener(OnPageScrollListener listener) {
mPageScrollListener = listener;
}
public interface OnPageScrollListener {
public void onPageChanged(int position);
}剩下的就是在activity中加载动画了,每当翻页结束就播放相应页面的动画并清除上一页的动画效果
class MyPageScrollListener implements OnPageScrollListener {
@Override
public void onPageChanged(int position) {
switch (position) {
case 0:
layout1AnimStart();
break;
case 1:
layout2AnimStart();
break;
case 2:
layout3AnimStart();
break;
case 3:
layout4AnimStart();
break;
}
}
}
代码在这里->http://download.csdn.net/detail/xu_fu/7185403
Android墨迹3.0特性介绍效果实现——做一个滚动的Layout,布布扣,bubuko.com
Android墨迹3.0特性介绍效果实现——做一个滚动的Layout
原文:http://blog.csdn.net/xu_fu/article/details/23208397