纯手工自制的Android引导页,实现了Viewpager切换的淡入淡出(页面不移动!)切换以及文字动画。
下面是效果演示:
实现思路+心路历程...:
其实别的都还蛮简单的,就是这个ViewPager的淡入淡出切换动画比较棘手,以前都没有做过,然后去网上找了好久好久。
其中碰到各种坑无数,大概90%的人是引的 JazzyViewPager的包然后就balabala说自己实现了种种功能,真是醉了....
结论是国内根本找不到这个效果的实现嘛....
然后 在Github下了JazzyViewPager的包里也并没有看到我需要实现的效果:淡入淡出并且页面不滑动!不滑动!不动!
不过最后终于摸索出了方法...
对没错就是PageTransformer,在其中通过控制左右视图View的位置移动使得向右滑动时右视图不移动过来。(在下面会详细解释)。
代码实现:
GuideActivity.java
package com.whale.nangua.toquan;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;
import com.whale.nangua.toquan.frag.Guide1Fragment;
import com.whale.nangua.toquan.frag.Guide2Fragment;
import com.whale.nangua.toquan.frag.Guide3Fragment;
import com.whale.nangua.toquan.frag.Guide4Fragment;
import com.whale.nangua.toquan.view.NGGuidePageTransformer;
import java.util.ArrayList;
import java.util.List;
/**
* Created by nangua on 2016/8/1.
*/
public class GuideActivity extends FragmentActivity implements ViewPager.OnPageChangeListener,View.OnClickListener {
// 主界面适配器
private FragmentPagerAdapter guidePagerAdapter;
// 所有的Tab
private List<View> views;
// 碎片每个碎片为一个布局
private ArrayList<Fragment> fragments;
// 导航式Tab
private ViewPager vp;
//四个Choice按钮id
private int[] choicebtnids = {R.id.imgbtn_guide_choice1, R.id.imgbtn_guide_choice2,
R.id.imgbtn_guide_choice3, R.id.imgbtn_guide_choice4};
//四个Choice按钮
private ImageButton[] choicebtns;
//右移按钮
private ImageButton btn_guide_next;
//跳过按钮
private TextView btn_guide_skip;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guide);
// 创建碎片集合
fragments = new ArrayList<Fragment>();
initView();
}
private void initView() {
WindowManager wm = this.getWindowManager();
screenWith = wm.getDefaultDisplay().getWidth(); //屏幕宽度
//右移按钮
btn_guide_next = (ImageButton) findViewById(R.id.btn_guide_next);
btn_guide_next.setOnClickListener(this);
//跳过
btn_guide_skip = (TextView) findViewById(R.id.btn_guide_skip);
btn_guide_skip.setOnClickListener(this);
//绑定按钮组件
choicebtns = new ImageButton[4];
for (int i = 0; i < 4; i++) {
final int j = i;
choicebtns[i] = (ImageButton) findViewById(choicebtnids[i]);
choicebtns[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeTagView(j);
}
});
}
LayoutInflater inflater = LayoutInflater.from(this);
// 添加滑动
views = new ArrayList<>();
views.add(inflater.inflate(R.layout.fragment_guide1, null));
views.add(inflater.inflate(R.layout.fragment_guide2, null));
views.add(inflater.inflate(R.layout.fragment_guide3, null));
views.add(inflater.inflate(R.layout.fragment_guide4, null));
vp = (ViewPager) findViewById(R.id.vp_guide);
guidePagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public int getCount() {
return fragments.size();
}
@Override
public Fragment getItem(int arg0) {
return fragments.get(arg0);
}
};
// 声明各个Tab的实例
Guide1Fragment guide1Fragment = new Guide1Fragment();
Guide2Fragment guide2Fragment = new Guide2Fragment();
Guide3Fragment guide3Fragment = new Guide3Fragment();
Guide4Fragment guide4Fragment = new Guide4Fragment();
fragments.add(guide1Fragment);
fragments.add(guide2Fragment);
fragments.add(guide3Fragment);
fragments.add(guide4Fragment);
ngGuidePageTransformer = new NGGuidePageTransformer();
ngGuidePageTransformer.setCurrentItem(this, 0, fragments);
vp.setPageTransformer(true, ngGuidePageTransformer);
vp.setAdapter(guidePagerAdapter);
vp.setOnPageChangeListener(this);
//注意,设置Page 即缓存页面的个数,数过小时会出现fragment重复加载的问题
vp.setOffscreenPageLimit(4);
}
NGGuidePageTransformer ngGuidePageTransformer;
TranslationInterface tempfrag;
@Override
public void onClick(View v) {
switch (v.getId()) {
//下一个
case R.id.btn_guide_next:
int nextPage;
if (nowPage == 3) {
nextPage = 0;
}else {
nextPage = nowPage+1;
}
onPageSelected(nextPage);
changeTagView(nextPage);
break;
//跳过
case R.id.btn_guide_skip:
//TODO 跳过操作
break;
}
}
public interface TranslationInterface {
void translation(float x);
}
int screenWith ;//屏幕宽度
/**
* TODO 动画修改
* @param position
* @param positionOffset
* @param positionOffsetPixels
*/
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//如果向右
switch (position) {
case 0:
tempfrag = (Guide1Fragment) fragments.get(0);
tempfrag.translation(positionOffsetPixels);
break;
case 1:
tempfrag = (Guide2Fragment) fragments.get(1);
tempfrag.translation(positionOffsetPixels);
break;
case 2:
tempfrag = (Guide3Fragment) fragments.get(2);
tempfrag.translation(positionOffsetPixels);
break;
case 3:
tempfrag = (Guide4Fragment) fragments.get(3);
tempfrag.translation(positionOffsetPixels);
break;
}
}
private int nowPage = 0;
/**
* 自定义按钮选择的方法
* @param position
*/
private void pageCheck(int position) {
choicebtns[position].setBackgroundResource(R.drawable.shape_guide_choice);
for (int i = 0;i<4;i++) {
if (i!= position) {
choicebtns[i].setBackgroundResource(R.drawable.shape_guide_unchoice);
}
}
}
@Override
public void onPageSelected(int position) {
nowPage = position;
ngGuidePageTransformer.setCurrentItem(position);
pageCheck(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
// 更换标签
private void changeTagView(int change) {
vp.setCurrentItem(change, false);
}
}
整体页面的布局,其中比较重要的点时设置Viewpager的PageTransformer,以及设置文字动画的效果。
下面是最重要的类:PageTransformer.java
package com.whale.nangua.toquan.view;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.View;
import java.util.ArrayList;
public class NGGuidePageTransformer implements ViewPager.PageTransformer {
private static final float MIN_ALPHA = 0.0f; //最小透明度
public void transformPage(View view, float position) {
int pageWidth = view.getWidth(); //得到view宽
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left. 出了左边屏幕
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
if (position < 0) {
//消失的页面
view.setTranslationX(-pageWidth * position); //阻止消失页面的滑动
} else {
//出现的页面
view.setTranslationX(pageWidth); //直接设置出现的页面到底
view.setTranslationX(-pageWidth * position); //阻止出现页面的滑动
}
// Fade the page relative to its size.
float alphaFactor = Math.max(MIN_ALPHA, 1 - Math.abs(position));
//透明度改变Log
view.setAlpha(alphaFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right. 出了右边屏幕
view.setAlpha(0);
}
}
int nowPostion = 0; //当前页面
Context context;
ArrayList<Fragment> fragments;
public void setCurrentItem(Context context, int nowPostion, ArrayList<Fragment> fragments) {
this.nowPostion = nowPostion;
this.context = context;
this.fragments = fragments;
}
public void setCurrentItem(int nowPostion) {
this.nowPostion = nowPostion;
}
}
实现的思路注释也比较详细,但是我还是说明一下:
就是先判断滑动的位置,如果是向右滑动,则首先要阻止当前页面(消失ing的页面)随着Viewpager的特性向左边滑动,以及右边要出现的界面向左滑动(在此之前先直接设置右边的界面到屏幕最左边)。要注意的是这里区分位置以及区分左右边是根据position来判断的。