本文轉載自:http://blog.csdn.net/qq_22770457/article/details/52133288
純手工自制的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來判斷的