Android-欢迎页联动动画设计
前言:博客还是要坚持写的,之前弄过一个欢迎页的联动效果,不是很复杂,其中包括两个点:一个是ViewPager滑动时两层布局的错位效果,另一个页面中View在滑动时的渐隐渐现效果。
以下是我的设计思路:
1.将A,B两个ViewPager放置于同一布局中,屏蔽掉B的内部点击事件,给A设置OnPageChangeListener,在A的监听方法中调用B的scrollTo使B一起滑动,此时可以设置一定比例来制造错位效果。页面进度条的位置也在这里设置。
2.给B设置PageTransformer,可以根据页面移动的位置参数来设置View的透明度、缩放等操作,以此来制造渐隐渐现效果。
以下是具体实现:
1.自定义NotouchLayout布局,复写onInterceptTouchEvent函数将其返回true,事件不会向子控件转发,将布局B放在其中,即屏幕掉了其内部触摸事件。
public class NotouchLayout extends RelativeLayout {
public NotouchLayout(Context context) {
super(context);
}
public NotouchLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
}
2.封装了一个GuidePage布局,以下是布局文件,其他初始化过程不在此展示,重点分析一下setPageTransformer和setOnPageChangeListener两个部分。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.jeffrey.demo.guidedemo.NotouchLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/bg_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:focusable="false" />
</com.jeffrey.demo.guidedemo.NotouchLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/progress_bar_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="36dp"
android:orientation="horizontal">
<View
android:layout_width="20dp"
android:layout_height="2dp"
android:background="#80d7d7d7" />
<View
android:layout_width="20dp"
android:layout_height="2dp"
android:layout_marginLeft="1dp"
android:background="#80d7d7d7" />
<View
android:layout_width="20dp"
android:layout_height="2dp"
android:layout_marginLeft="1dp"
android:background="#80d7d7d7" />
<View
android:layout_width="20dp"
android:layout_height="2dp"
android:layout_marginLeft="1dp"
android:background="#80d7d7d7" />
</LinearLayout>
<View
android:id="@+id/progress_mark_view"
android:layout_width="20dp"
android:layout_height="2dp"
android:layout_alignLeft="@id/progress_bar_view"
android:layout_alignParentBottom="true"
android:layout_marginBottom="36dp"
android:background="#80828282" />
</RelativeLayout>
</FrameLayout>
布局中包含两个ViewPager,以及下面白色进度条的布局。
mPager.setPageTransformer(true, new DepthPageTransformer());
public class DepthPageTransformer implements android.support.v4.view.ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1 + position);
view.setTranslationX(7 * pageWidth / 24 * -position);
// view.setScaleX(1);
// view.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
Log.d("ty", "position:" + position + "Traslation" + pageWidth * position);
if (position >= 0.5) {
view.setTranslationX(pageWidth / 2);
} else {
view.setTranslationX(pageWidth * position);
}
//Scale the page down (between MIN_SCALE and 1) UI缩放的设置
// float scaleFactor = MIN_SCALE
// + (1 - MIN_SCALE) * (1 - Math.abs(position));
// view.setScaleX(scaleFactor);
// view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
transformPage方法中的两个参数:ViewPager中当前显示view对象,以及其位置参数position,关于position具体含义可对照下图:为了设置渐变效果,以卡片(page)左边为标准,当处于[-Infinity,-1)区间时不显示,在[-1,0]区间时根据偏移量的增加透明度先增后减,同时根据偏移量来移动view,设置一定比例实现间错效果,当然也可以设置缩放效果(此处没有设置),在 (1,+Infinity]区间也不显示。这样就完成了渐隐渐现和间错效果
image下面是联动效果,三个参数position代表当前view下标,positionOffset代表偏移量是一个百分比,positionOffsetPixels代表偏移量是像素单位。在这里用setTranslationX设置了下面进度条的滑动,用scrollTo使mFramePager(B)按真实比例滑动,因为之前mPager(A)设置了一定的滑动比例,这样就实现了带间错联动效果。
mPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//进度条
view.setTranslationX((view.getWidth() + view.getWidth() / 20f) * (position + positionOffset));
//设置联动
float pageOffset = position + positionOffset;
Log.d("pageOffset", pageOffset + "");
if (mFramePager != null) {
mFramePager.scrollTo((int) (pageOffset * mFramePager.getWidth()), mFramePager.getScrollY());
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
这样就实现了最终的效果,Demo源码