Android 1分钟教你打造酷炫的引导页(实现ViewPager淡入淡出切换)

纯手工自制的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来判断的。

时间: 2024-10-07 06:13:55

Android 1分钟教你打造酷炫的引导页(实现ViewPager淡入淡出切换)的相关文章

Android使用SVG矢量图打造酷炫动效!

尊重原创,欢迎转载,转载请注明: FROM  GA_studio   http://blog.csdn.net/tianjian4592 一个真正酷炫的动效往往让人虎躯一震,话不多说,咱们先瞅瞅效果: 这个效果我们需要考虑以下几个问题: 1. 这是图片还是文字: 2. 如果是图片该如何拿到图形的边沿线坐标,如果是文字呢? 3. 如果拿到了边沿线坐标,如何让光线沿着路径跑动: 4. 怎么处理过程的衔接: 以上四个问题似乎不是太好处理,而这几个问题也正好是这个效果精华所在,接下来咱们一个一个进行考虑

使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突

使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种冲突 如果你还在为处理滑动冲突而发愁,那么你需要静下心来看看这边文章,如果你能彻底理解这篇文章中使用的技术,那么,一切滑动冲突的问题解决起来就轻而易举了:先扔一个最终实现的效果图 先分析下效果图中实现的功能点 顶部下拉时背景图形成视差效果 上拉时标题栏透明切换显示 底部实现TabLayout+ViewPager+Fragment+RecyclerV

10年Android老司机教你打造独一无二的刷新加载框架

首先我们给出如下几个参数,后面要用: 10年Android老司机教你打造独一无二的刷新加载框架既然是刷新,我们的滚动肯定是在 父view 之前的.所以我们需要在 onNestedPreScroll 这个方法里面写上我们所需要改动的x,y值. 我们需要用 父view 去拦截它.我们需要判断 dy 的值是否大于0,因为大于0是刷新操作,小于0是加载操作.然后我们需要判断 recyclerview 是否是纵向的而不是横向的. 10年Android老司机教你打造独一无二的刷新加载框架上拉加载 上面我也说

MVC中使用SignalR打造酷炫实用的即时通讯功能

資料來源:http://www.fangsi.net/1144.html 前言,现在这世道写篇帖子没个前言真不好意思发出来.本贴的主要内容来自于本人在之前项目中所开发的一个小功能,用于OA中的即时通讯.由于当时走的太急,忘记把代码拿出来.想想这已经是大半年前的事情了,时间过了这么久,在当时最新的SignalR2.0.1到现在已经变成了2.2.昨天晚上特地熬了个夜,重新又把它写出来做了一个小小的Demo.当然我只是大自然的搬运工,这个SignalR即时通讯功能里面有一些前端的类库不是我自己写的.我

MVC中使用SignalR打造酷炫实用的即时通讯功能附源码

前言,现在这世道写篇帖子没个前言真不好意思发出来.本贴的主要内容来自于本人在之前项目中所开发的一个小功能,用于OA中的即时通讯.由于当时走的太急,忘记把代码拿出来.想想这已经是大半年前的事情了,时间过了这么久,在当时最新的SignalR2.0.1到现在已经变成了2.2.昨天晚上特地熬了个夜,重新又把它写出来做了一个小小的Demo.当然我只是大自然的搬运工,这个SignalR即时通讯功能里面有一些前端的类库不是我自己写的.我只是改吧改吧~~在此鸣谢 @贤心,是他的几条库才使得我的这个功能如此酷炫.

Android 仿网易新闻v3.5:上下滑动的引导页

版权声明:本文为博主原创文章,未经博主允许不得转载. 最近看了下网易新闻月初发布的3.5版,发现两个比较明显的改动: 1.引导页的修改,变为上下滑动. 2.增加了聚合阅读,里面的动画效果也是蛮有创意的.于是又禁不住模仿一下 这次先看这个上下滑动的引导页效果图: 这种效果具体怎么做呢? 首先直接上github,直接看有没有相关的开源项目,果不其然,被我找到了: https://github.com/JakeWharton/Android-DirectionalViewPager JakeWhart

Android 教你亲手打造酷炫的弹幕效果

公司的新产品上线需要添加的弹幕功能,于是花了一天时间写了一个Demo. 效果实现如下: 一开始的思路是: 1.首先实现一个自定义的Layout,在其中获得需要展示的弹幕数组,每个弹幕数组的项包括弹幕文本以及图片Url地址. 2.在Layout内部使用Handler或者计时线程循环发送弹幕. 3.弹幕实现采用自定义弹幕View,配合动画实现滚屏呈现. 总结之后发现主要的难点还是在弹幕的出现位置选择以及弹幕如何确保及时销毁上(我会说一开始调试的时候出现满屏弹幕的华丽场景么..),以及如何实现组件的复

Grafana、collectd 和 InfluxDB 打造酷炫监控系统(四)常用插件介绍和自定义数据篇

一.常用插件介绍 获取指定端口的连接状态ESTABLISHED.CLOSE_WAIT.LISTEN等 tcpconns: <Plugin tcpconns> ListeningPorts false LocalPort "80" RemotePort "80" </Plugin> 获取Nginx的状态 nginx: <Plugin nginx> URL "http://test.tt.com/NginxStatus&qu

学习websocket-SignalR,MVC中使用SignalR打造酷炫实用的即时通讯

http://www.cnblogs.com/Leo_wl/p/4793284.html http://www.fangsi.net/archives/1144.html