演示效果
【暂时先借用小红帽图片素材的app效果来演示】
文件结构
(1)Android层的代码实现
(2)实现效果Gif一张
代码实现过程:
第三方库
(1)butterknife
通过Gradle引入
(2)viewpagerindicator
通过Model引入
代码层
(1)在ViewPager的滑动监听做处理
mNewVp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
private int lastOffset = -1;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Log.d("onPageScrolled参数", "position : " + position + "---" + "positionOffset : " + positionOffset + "---" + "positionOffsetPixels : " + positionOffsetPixels);
//-----------------------------第一部分------------------------------------
if (position == 0) {
settingOne(positionOffset);
} else if (position == 1) {
settingTwo(positionOffset);
} else if (position == 2) {
mHintFragment.startHintAnim();
}
//----------------------------第二部分--------------------------------------
if (lastOffset >= positionOffsetPixels) {
//右滑
Log.d("方向", "右");
} else if (lastOffset < positionOffsetPixels && position == 1) {
//左滑
Log.d("方向", "左");
mHintFragment.endHintAnim();
}
lastOffset = positionOffsetPixels;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
第一部分
第一部分主要控制各个页面滑动的效果:
控制第一个页面
settingOne()
控制第二个页面
settingTwo()
控制第三个页面
mHintFragment.startHintAnim();
第三个页面没有额外的头像动画,只是有个提示的弹出的效果,这是在Fragment中实现的。
settingOne 方法
* 设置第一个界面滑动
*/
private void settingOne(float positionOffset) {
//位移
int[] size = ((NewFragment) fragments.get(0)).getContentSize();
int xMove = (int) (size[0] * 0.53);
int yMove = (int) (size[1] * 0.47);
mAccountIv.setTranslationX(positionOffset * xMove);
mAccountIv.setTranslationY(positionOffset * yMove);
//大小改变
int moveSize = (int) (startSize * 0.4);
ViewGroup.LayoutParams params = mAccountIv.getLayoutParams();
params.width = (int) (dip2px(startSize) - dip2px(moveSize) * positionOffset);
params.height = (int) (dip2px(startSize) - dip2px(moveSize) * positionOffset);
mAccountIv.setLayoutParams(params);
}
这个方法主要是先设置好头像的滑动空间的比率:
然后通过控制ViewPager的滑动距离,一点一点移动到需要移动的位置。
通过setTranslationX和setTranslationY实现的。
mAccountIv.setTranslationX(positionOffset * xMove);
mAccountIv.setTranslationY(positionOffset * yMove);
而变化大小,则通过改变LayoutParams来实现的
ViewGroup.LayoutParams params = mAccountIv.getLayoutParams();
params.width = (int) (dip2px(startSize) - dip2px(moveSize) * positionOffset);
params.height = (int) (dip2px(startSize) - dip2px(moveSize) * positionOffset);
这里的mAccountIv指的就是头像。
settingTwo 方法
private void settingTwo(float positionOffset) {
//位移
int[] size = ((NewFragment) fragments.get(1)).getContentSize();
int xMove = (int) (size[0] * 0.53);
int yMove = (int) (size[1] * 0.47);
mAccountIv.setTranslationX(xMove * (1 - positionOffset));
mAccountIv.setTranslationY(yMove * (1 - positionOffset));
//大小改变
int moveSize = (int) (startSize * 0.4);
ViewGroup.LayoutParams params = mAccountIv.getLayoutParams();
params.width = (int) (dip2px(startSize - moveSize) + dip2px(moveSize) * positionOffset);
params.height = (int) (dip2px(startSize - moveSize) + dip2px(moveSize) * positionOffset);
mAccountIv.setLayoutParams(params);
}
这个方法和settingOne类似这里就不做多介绍了。
startHintAnim 方法
这个方法只是做了一个属性动画
/**
* 开启提示动画
*/
public void startHintAnim() {
if (mHintTv.getX() < 0) {
mHintTv.postDelayed(new Runnable() {
@Override
public void run() {
int width = mHintTv.getWidth();
ValueAnimator animator = ObjectAnimator.ofFloat(mHintTv, "translationX", -width, 0);
animator.setDuration(650);
animator.start();
}
}, 350);
}
}
endHintAnim 方法
/**
* 结束提示动画
*/
public void endHintAnim() {
if (mHintTv.getX() == 0) {
int width = mHintTv.getWidth();
ValueAnimator animator = ObjectAnimator.ofFloat(mHintTv, "translationX", 0, -width);
animator.setDuration(400);
animator.start();
}
}
项目目录截图
备注
剩下具体的实现逻辑在Demo中,可以具体看到。
如果大家在Demo的运行的过程中遇到问题可以联系我的邮箱:
issuperd@foxmail.com
高仿小红书引导页实现效果
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权