高仿有赞微小店SplashView

从事android开发有段时间了,总是说该写写技术博客了,分享知识的同时也能从中知道自己的不足,有挫折才会有动力,有争吵才会有成长,大家一起共勉吧。

直接进入主题吧,前两天正好看见一款App,对里面的Splash View给吸引住了, 像我们一般的App一般不会在Splash View花费太多的时间折腾,小公司大都功能至上,体验次之。从一个App的每个设计细节往往能够窥探出公司对产品和客户的责任心,当然了,这个有点扯远了,整个功能倒不是很难,我们一起来分析分析吧,么么哒!

首先我们从平台上下载有赞微小店,将.apk后缀改成.zip解压到任意文件夹,文件夹内容如下:
这里写图片描述
在res里面会找到相应的资源,往往大点的公司美工都是很不错的,图片也切的比较精美。
拿到想要的资源后,来分析分析设计需求吧:
1:每个子图片都是相对性的布局在自己的位子,并且以动画的形式以一定的时间间隔进行展示,凸显层次感。
2:滑动的过程中,后面的背景图不会跟着一起滑动,滑动的过程中背景图的透明度会随着页面的左右滑动正比渐变,直至完整滑出页面。
3:每滑到新页面都会将旧页面进行隐藏,并以动画的形式展现新页面,凸显层次感。

大概就这么多了,运行效果图如下,加深大家的理解:
高仿有赞微小店SplashView_第1张图片
下面我们一起用代码来实现:
主布局代码activity_main.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">

            <RelativeLayout
                android:id="@+id/relativelayout_first"
                android:layout_width="300dp"
                android:layout_height="300dp"
                android:layout_centerInParent="true">

                <ImageView
                    android:id="@+id/start1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="20dp"
                    android:layout_marginTop="20dp"
                    android:src="@mipmap/img_guide_page_1_star"
                    android:visibility="gone" />

                <ImageView
                    android:id="@+id/start2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_marginRight="45dp"
                    android:layout_marginTop="3dp"
                    android:src="@mipmap/img_guide_page_1_star"
                    android:visibility="gone" />

                <ImageView
                    android:id="@+id/start3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_alignParentRight="true"
                    android:layout_marginBottom="25dp"
                    android:layout_marginRight="35dp"
                    android:src="@mipmap/img_guide_page_1_star"
                    android:visibility="gone" />

                <ImageView
                    android:id="@+id/first_page_img"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:src="@mipmap/img_guide_page_1" />
            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/relativelayout_second"
                android:layout_width="300dp"
                android:layout_height="300dp"
                android:layout_centerInParent="true"
                android:background="@mipmap/img_guide_page_bg">

                <ImageView
                    android:id="@+id/second_bg1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="50dp"
                    android:src="@mipmap/img_guide_page_3_icon1" />

                <ImageView
                    android:id="@+id/second_bg4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_centerHorizontal="true"
                    android:layout_marginBottom="50dp"
                    android:src="@mipmap/img_guide_page_3_icon4" />

                <ImageView
                    android:id="@+id/second_bg2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_marginRight="40dp"
                    android:layout_marginTop="80dp"
                    android:src="@mipmap/img_guide_page_3_icon2" />

                <ImageView
                    android:id="@+id/second_bg3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_alignParentRight="true"
                    android:layout_marginBottom="80dp"
                    android:layout_marginRight="40dp"
                    android:src="@mipmap/img_guide_page_3_icon3" />

                <ImageView
                    android:id="@+id/second_bg5"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_marginBottom="80dp"
                    android:layout_marginLeft="40dp"
                    android:src="@mipmap/img_guide_page_3_icon5" />

                <ImageView
                    android:id="@+id/second_bg6"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="40dp"
                    android:layout_marginTop="80dp"
                    android:src="@mipmap/img_guide_page_3_icon6" />

                <ImageView
                    android:id="@+id/second_bg7"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:src="@mipmap/img_guide_page_3_icon7" />
            </RelativeLayout>

            <RelativeLayout
                android:id="@+id/relativelayout_third"
                android:layout_width="300dp"
                android:layout_height="300dp"
                android:layout_centerInParent="true"
                android:background="@mipmap/img_guide_page_bg">

                <ImageView
                    android:id="@+id/third_box"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="30dp"
                    android:src="@mipmap/img_guide_page_4_box" />

                <ImageView
                    android:id="@+id/third_cash"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_alignParentRight="true"
                    android:layout_marginRight="15dp"
                    android:paddingBottom="40dp"
                    android:src="@mipmap/img_guide_page_4_cash" />

                <ImageView
                    android:id="@+id/third_arrow_2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_centerHorizontal="true"
                    android:layout_marginBottom="80dp"
                    android:src="@mipmap/img_guide_page_4_arrow_2" />

                <ImageView
                    android:id="@+id/third_arrow_1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="90dp"
                    android:src="@mipmap/img_guide_page_4_arrow_1" />

                <ImageView
                    android:id="@+id/third_arrow_3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="90dp"
                    android:src="@mipmap/img_guide_page_4_arrow_3" />

                <ImageView
                    android:id="@+id/third_order"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentBottom="true"
                    android:layout_marginLeft="15dp"
                    android:paddingBottom="40dp"
                    android:src="@mipmap/img_guide_page_4_order" />
            </RelativeLayout>

            <android.support.v4.view.ViewPager
                android:id="@+id/viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/transparent"></android.support.v4.view.ViewPager>

            <LinearLayout
                android:id="@+id/linearlayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:gravity="center"
                android:orientation="horizontal"
                android:paddingBottom="10dp">

            </LinearLayout>
        </RelativeLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:orientation="horizontal">

            <Button
                android:id="@+id/login"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="@drawable/login_bg"
                android:text="@string/login"
                android:textColor="#f94041"
                android:textSize="16sp" />

            <Button
                android:id="@+id/register"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:layout_weight="1"
                android:background="@drawable/register_bg"
                android:text="@string/register"
                android:textColor="@android:color/white"
                android:textSize="16sp" />
        </LinearLayout>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/splash_bg"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"
            android:src="@mipmap/splash_shake" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="10dp"
            android:src="@mipmap/splash_brand" />
    </FrameLayout>
</FrameLayout>

首先讲一下这个布局整体思路吧,也不难就是麻烦!–(,父类布局是FrameLayout,用这个的原因是最外层会遮罩一个InitSplashView图片,InitSplashView大概会显示2秒后将其状态设为INVISIABLE,然后显示的就是SplashView的,这个也是比较简单的做法了。当我们滑动ViewPager的时候ViewPager后面的背景是不会横着一起滑动的,所以后面的背景图肯定不是画在ViewPager所托管的子页面上,我们设置ViewPager的子页面背景为透明,这样后面的布局我们是可以看见的而且不会跟着ViewPager一起滑动,至于滑动过程后面的背景会跟着滑动偏移比例透明度会正比渐变,这个我们下面一起操作起来,很好玩的。
这边我们会有三个子页面,子页面里面的小图片都是以属性动画的形式进行展示的,当然我这边偷懒 ,minSdkVersion=11,哈哈,如果要兼容到3.0以下的话,还是乖乖的引入nineOldAndroids吧。
首先实现一个接口:

/** * Created by Administrator on 2015/9/17. * 动画公用接口<br/> */
public interface DefaultAnimator {
    void startAnimator(View view, AnimatorCallback animatorCallback);

    void withChangeAnimator(int position, float positionOffset, List<View> view, float positionOffsetPix, boolean flag);
}

接口两个方法分别为:startAnimator(启动动画), 2:withChangeAnimator(随着ViewPager的滑动正比渐变背景);
每个页面的动画单独抽成子类进行维护,这样可以减少代码耦合,也能提高代码的可维护度。
FirstAnimator:

package com.kakasure.splashdemo.animator;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageView;

import com.kakasure.splashdemo.R;
import com.kakasure.splashdemo.callback.AnimatorCallback;

import java.util.List;

/** * Created by Administrator on 2015/9/17. */
public class FirstAnimator implements DefaultAnimator {
    public View baseView;
    private ImageView start1;
    private ImageView start2;
    private ImageView start3;

    private void initView() {
        start1 = (ImageView) baseView.findViewById(R.id.start1);
        start2 = (ImageView) baseView.findViewById(R.id.start2);
        start3 = (ImageView) baseView.findViewById(R.id.start3);
        start1.setVisibility(View.GONE);
        start2.setVisibility(View.GONE);
        start3.setVisibility(View.GONE);
    }

    @Override
    public void startAnimator(final View view, final AnimatorCallback animatorCallback) {
        if (view != null) {
            baseView = view;
            initView();
            ImageView imageView = (ImageView) view.findViewById(R.id.first_page_img);
            AnimatorSet animatorSet = new AnimatorSet();
            ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
            ObjectAnimator scalexAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 0.4f, 1f);
            ObjectAnimator scaleyAnimator = ObjectAnimator.ofFloat(imageView, "scaleY", 0.4f, 1f);
            animatorSet.play(alphaAnimator).with(scalexAnimator).with(scaleyAnimator);
            animatorSet.setDuration(1 * 500);
            animatorSet.setInterpolator(new AccelerateInterpolator());
            animatorSet.start();
            animatorSet.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    animatorCallback.AnimatorStart(0);
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    animatorCallback.AnimatorComplete(0);
                    startAnimatorSet(start1);
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
        }
    }

    private void startAnimatorSet(final View view) {
        ObjectAnimator startAnimatorX1 = ObjectAnimator.ofFloat(view, "scaleX", 0f, 1f, 1.8f, 1f, 0.7f, 1.4f, 1.0f, 0.8f, 1f);
        ObjectAnimator startAnimatorY1 = ObjectAnimator.ofFloat(view, "scaleY", 0f, 1f, 1.8f, 1f, 0.7f, 1.4f, 1.0f, 0.8f, 1f);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.setDuration(200);
        animatorSet.setInterpolator(new AccelerateInterpolator());
        animatorSet.play(startAnimatorX1).with(startAnimatorY1);
        animatorSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                view.setVisibility(View.VISIBLE);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                switch (view.getId()) {
                    case R.id.start1:
                        startAnimatorSet(start2);
                        break;
                    case R.id.start2:
                        startAnimatorSet(start3);
                        break;
                    case R.id.start3:
                        // TODO NOTHING
                        break;
                    default:
                        break;
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animatorSet.start();
    }

    @Override
    public void withChangeAnimator(int position, float positionOffset, List<View> view, float positionOffsetPix, boolean flag) {
        if (view != null) {
            if (positionOffsetPix == 0) {
                view.get(position).setAlpha(1f);
            } else {
                if (flag) {
                    view.get(position).setAlpha(1 - positionOffset);
                } else {
                    view.get(position).setAlpha(positionOffset);
                }
            }
        }
    }
}

SecondAnimator.ThirdAnimator与上面显示雷同:
首先startAimator方法的触发时机为两种:
1:InitSplashView过渡两秒之后触发:

 myHandler.sendEmptyMessageDelayed(1, 2 * 1000);
 private Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            splashbg.setVisibility(View.GONE);
            updateIndicatorStatus(0);
        }
    };

2:第二种触发方法完全依赖OnPageChangeListener的实现监听:

@Override
        public void onPageSelected(int position) {
            updateIndicatorStatus(position);
            Log.i(TAG, "onPageSelected is called, position = " + position);
        }

那我们来看下updateIndicatorStatus到底是干什么的:

public void updateIndicatorStatus(int position) {
        currentPosition = position;
        AnimatorManager.getInstance().startAnimator(position);
        switch (position) {
            case 0:
                imgList.get(0).setBackgroundResource(R.mipmap.yindao_down);
                imgList.get(1).setBackgroundResource(R.mipmap.yindao_on);
                imgList.get(2).setBackgroundResource(R.mipmap.yindao_on);
                break;
            case 1:
                imgList.get(1).setBackgroundResource(R.mipmap.yindao_down);
                imgList.get(0).setBackgroundResource(R.mipmap.yindao_on);
                imgList.get(2).setBackgroundResource(R.mipmap.yindao_on);
                break;
            case 2:
                imgList.get(2).setBackgroundResource(R.mipmap.yindao_down);
                imgList.get(1).setBackgroundResource(R.mipmap.yindao_on);
                imgList.get(0).setBackgroundResource(R.mipmap.yindao_on);
                break;
            default:
                break;
        }
    }

这里我们会根据滑动监听动态改变Indicator Icon的背景图,同时我们会触发相应页面的初始动画,这里动画的统一管理我们会放在AnimatorManager进行管理:
代码如下:

package com.kakasure.splashdemo.manager;

import android.util.SparseArray;
import android.view.View;

import com.kakasure.splashdemo.callback.AnimatorCallback;
import com.kakasure.splashdemo.animator.AnimatorFactory;

import java.util.ArrayList;
import java.util.List;

/** * Created by Administrator on 2015/9/17. * 动画管理类<br/> * * @author dashentao * @date 2015 9-17 * @since V 1.0 */
public class AnimatorManager implements AnimatorCallback {
    // 管理View的集合
    private List<View> viewList = new ArrayList<View>();
    private static AnimatorManager mAnimatorManager;
    private static Object object = new Object();
    private SparseArray<Boolean> sparseArray = new SparseArray<Boolean>();

    public static AnimatorManager getInstance() {
        if (mAnimatorManager == null) {
            synchronized (object) {
                if (mAnimatorManager == null) {
                    mAnimatorManager = new AnimatorManager();
                }
            }
        }
        return mAnimatorManager;
    }

    public void add(View view) {
        if (viewList != null) {
            viewList.add(view);
        }
    }

    public void addAll(List<View> view) {
        if (viewList != null) {
            viewList.clear();
            viewList.addAll(view);
        }
    }

    /** * ViewPager滑动式渐变动画<br/> * * @param position * @param positionOffset */
    public void withChangeAnimator(int position, float positionOffset, float positionOffsetPix, boolean flag) {
        if (sparseArray != null) {
            if (sparseArray.get(position) != null && sparseArray.get(position)) {
                AnimatorFactory.getInstance(position).withChangeAnimator(position, positionOffset, viewList, positionOffsetPix, flag);
            }
        }
    }

    /** * 启动相应子页面的动画<br/> * * @param position */
    public void startAnimator(int position) {
        // 对动画做隐藏处理
        if (viewList != null && viewList.size() > 0) {
            for (int i = 0; i < viewList.size(); i++) {
                if (i == position) {
                    viewList.get(i).setVisibility(View.VISIBLE);
                } else {
                    viewList.get(i).setVisibility(View.INVISIBLE);
                }
            }
        }
        AnimatorFactory.getInstance(position).startAnimator(viewList.get(position), this);
    }

    @Override
    public void AnimatorComplete(int position) {
        if (sparseArray != null) {
            sparseArray.put(position, true);
        }
    }

    @Override
    public void AnimatorStart(int position) {
        if (sparseArray != null) {
            sparseArray.put(position, false);
        }
    }
}

在startAnimtor里面我们会隐藏其他页面,显示当前页面。这里我们通过简单工厂得到动画操作实例:

package com.kakasure.splashdemo.animator;

import android.util.Log;

/** * Created by Administrator on 2015/9/17. * 简单工厂类<br/> */
public class AnimatorFactory {
    public static final String TAG = AnimatorFactory.class.getSimpleName();

    public static DefaultAnimator getInstance(int position) {
        switch (position) {
            case 0:
                return new FirstAnimator();
            case 1:
                return new SecondAnimator();
            case 2:
                return new ThirdAnimator();
            default:
                Log.i(TAG, "you know, it will not be happened!");
                break;
        }
        return null;
    }
}

得到相应实例时候会相应的通过多态调用子类中StartAimator方法,顾客只需要调用某个方法,具体的逻辑子类自己去实现,顾客与用户进行解耦。

我们再来看下如何让ViewPager的子页面跟随滑动正比渐变,这个我们就要去了解OnPageChangeListener这个接口实现方法的具体含义了:
1:public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
——-时刻监听ViewPager的滑动状态,positionOffset为滑动的比例0f-1f,positionOffsetPixels为当前页面偏移的像素位置 。
2: public void onPageSelected(int position)
——-滑动完成之后掉用。
3: public void onPageScrollStateChanged(int state)
——-监听滑动状态:state==1时默示正在滑动,state==2时默示滑动完毕了,state==0时默示什么都没做。

然后思路就来了,我们根据positionOffset来动态设置整个子布局的ahpla(透明度),这样就可以达到效果了,开始动手吧。
代码如下:

@Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            Log.i(TAG, "position = " + position);
            boolean flag = false;
            if (position == currentPosition) {
                flag = true;
            } else {
                flag = false;
            }
            AnimatorManager.getInstance().withChangeAnimator(currentPosition, positionOffset, positionOffsetPixels, flag);
        }

在FirstAnimator里面自己实现:

@Override
    public void withChangeAnimator(int position, float positionOffset, List<View> view, float positionOffsetPix, boolean flag) {
        if (view != null) {
            if (positionOffsetPix == 0) {
                view.get(position).setAlpha(1f);
            } else {
                if (flag) {
                    view.get(position).setAlpha(1 - positionOffset);
                } else {
                    view.get(position).setAlpha(positionOffset);
                }
            }
        }
    }

这里面实现的过程中遇到一些问题,ViewPager页面滑动过程中PositionOffset渐变比例会随着滑动方向而不同,向左滑动比例会从1f-0f, 向右滑动比例会从0f-1f, 但是向左滑动时,position会是上个页面的position,不调试不知道,调试完了之后吓一跳,没办法,凡事都得实践才能出真理,所以这边做了特殊处理,还有就是当positionOffsetPix == 0时,我们会设置alpha为不透明,这样能保证当滑动到一半时松手自然回弹到当前页面布局透明度为0;

主MainActivity:

package com.kakasure.splashdemo.ui;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.kakasure.splashdemo.R;
import com.kakasure.splashdemo.manager.ActManager;
import com.kakasure.splashdemo.manager.AnimatorManager;

import java.util.ArrayList;
import java.util.List;

/** * Created by Administrator on 2015/9/16. * * @author dashentao * @date 2015 9-16 * @since V 1.0 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private String TAG = MainActivity.this.getClass().getSimpleName();
    private ViewPager viewPager;
    private Button login;
    private Button register;
    private LinearLayout linearLayout;
    private RelativeLayout relativeLayoutFirst;
    private RelativeLayout relativeLayoutSecond;
    private RelativeLayout relativeLayoutThrid;
    private FrameLayout splashbg;
    private List<ImageView> imgList = new ArrayList<ImageView>();
    private List<Fragment> fragList = new ArrayList<Fragment>();
    private int currentPosition = -1;
    private Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            splashbg.setVisibility(View.GONE);
            updateIndicatorStatus(0);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActManager.getInstance().pushActivity(this);
        initView();
        initListener();
        initAdapter();
        init();
    }

    public void initListener() {
        login.setOnClickListener(this);
        register.setOnClickListener(this);
        viewPager.setOnPageChangeListener(new MyPageChangeListener());
    }

    public void initView() {
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        login = (Button) findViewById(R.id.login);
        register = (Button) findViewById(R.id.register);
        linearLayout = (LinearLayout) findViewById(R.id.linearlayout);
        relativeLayoutFirst = (RelativeLayout) findViewById(R.id.relativelayout_first);
        relativeLayoutSecond = (RelativeLayout) findViewById(R.id.relativelayout_second);
        relativeLayoutThrid = (RelativeLayout) findViewById(R.id.relativelayout_third);
        splashbg = (FrameLayout) findViewById(R.id.splash_bg);
    }

    /** * 初始化适配器<br/> */
    public void initAdapter() {
        FragmentManager fragmentManager = getSupportFragmentManager();
        MyAdapter myAdapter = new MyAdapter(fragmentManager);
        for (int i = 0; i < 3; i++) {
            SplashFragment splashFragment = SplashFragment.newInstance(getResources().getStringArray(R.array.titles)[i]);
            fragList.add(splashFragment);
        }
        myAdapter.list.clear();
        myAdapter.list.addAll(fragList);
        viewPager.setAdapter(myAdapter);
    }

    public void init() {
        for (int i = 0; i < fragList.size(); i++) {
            ImageView imageView = new ImageView(this);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            linearLayout.addView(imageView, layoutParams);
            imgList.add(imageView);
        }
        List<View> view = new ArrayList<View>();
        view.add(relativeLayoutFirst);
        view.add(relativeLayoutSecond);
        view.add(relativeLayoutThrid);
        AnimatorManager.getInstance().addAll(view);
        myHandler.sendEmptyMessageDelayed(1, 2 * 1000);
    }

    public void updateIndicatorStatus(int position) {
        currentPosition = position;
        AnimatorManager.getInstance().startAnimator(position);
        switch (position) {
            case 0:
                imgList.get(0).setBackgroundResource(R.mipmap.yindao_down);
                imgList.get(1).setBackgroundResource(R.mipmap.yindao_on);
                imgList.get(2).setBackgroundResource(R.mipmap.yindao_on);
                break;
            case 1:
                imgList.get(1).setBackgroundResource(R.mipmap.yindao_down);
                imgList.get(0).setBackgroundResource(R.mipmap.yindao_on);
                imgList.get(2).setBackgroundResource(R.mipmap.yindao_on);
                break;
            case 2:
                imgList.get(2).setBackgroundResource(R.mipmap.yindao_down);
                imgList.get(1).setBackgroundResource(R.mipmap.yindao_on);
                imgList.get(0).setBackgroundResource(R.mipmap.yindao_on);
                break;
            default:
                break;
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.login:
                // 登录状态
                break;
            case R.id.register:
                // 用户注册
                break;
            default:
                Log.i(TAG, "It will not happened!");
                break;
        }
    }

    /** * 滑动页面监视器 */
    public class MyPageChangeListener implements ViewPager.OnPageChangeListener {

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Log.i(TAG, "positionOffset is =" + positionOffset);
// Log.i(TAG, "positionOffsetPixels is = " + positionOffsetPixels);
            Log.i(TAG, "position = " + position);
            boolean flag = false;
            if (position == currentPosition) {
                flag = true;
            } else {
                flag = false;
            }
            AnimatorManager.getInstance().withChangeAnimator(currentPosition, positionOffset, positionOffsetPixels, flag);
        }

        @Override
        public void onPageSelected(int position) {
            updateIndicatorStatus(position);
            Log.i(TAG, "onPageSelected is called, position = " + position);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }
    }

    /** * ViewPager适配器 */
    public class MyAdapter extends FragmentPagerAdapter {
        List<Fragment> list = new ArrayList<Fragment>();

        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return list.get(position);
        }

        @Override
        public int getCount() {
            return list.size();
        }
    }
}

再有就是动画方面了,无非就是对属性的一些操作;
具体涉及到这些:
1:透明度,X,Y轴的缩放同步播放:

AnimatorSet animatorSet = new AnimatorSet();
            ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
            ObjectAnimator scalexAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 0.4f, 1f);
            ObjectAnimator scaleyAnimator = ObjectAnimator.ofFloat(imageView, "scaleY", 0.4f, 1f);
            animatorSet.play(alphaAnimator).with(scalexAnimator).with(scaleyAnimator);
            animatorSet.setDuration(1 * 500);
            animatorSet.setInterpolator(new AccelerateInterpolator());
            animatorSet.start();

2:箭头显示的动画:

 float currentX3 = view.getTranslationX();
 float currentY3 = view.getTranslationY();
 ObjectAnimator arrowX3 = ObjectAnimator.ofFloat(view, "translationX", currentX3 -   AppUtils.dip2px(ActManager.getInstance().getCurrentActivity(), 8), currentX3);
 ObjectAnimator arrowY3 = ObjectAnimator.ofFloat(view, "translationY", currentY3 + AppUtils.dip2px(ActManager.getInstance().getCurrentActivity(), 8), currentY3);
 animatorSet.play(arrowX3).with(arrowY3);

等等,有动画基础的同学这些都是小儿科了。

还有一个地方比较重要:
就是启动子页面动画的时候,不会去触发ViewPager滑动引起的透明度改变,这样会避免闪烁现象。
这里主要是监听启动动画的回调:
当然我们在AnimatorManger会实现一个接口:

package com.kakasure.splashdemo.callback;

/** * Created by Administrator on 2015/9/17. */
public interface AnimatorCallback {
    void AnimatorComplete(int position);

    void AnimatorStart(int position);
}

然后将接口注册到FirstAnimator中,通过监听动画的执行状态通过callback接口回调给AnimatorManager;

animatorSet.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    animatorCallback.AnimatorStart(0);
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    animatorCallback.AnimatorComplete(0);
                    startAnimatorSet(start1);
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });

我们在启动withChangeAnimator的时候会去判断回调状态:

    /** * ViewPager滑动式渐变动画<br/> * * @param position * @param positionOffset */
    public void withChangeAnimator(int position, float positionOffset, float       positionOffsetPix, boolean flag) {
        if (sparseArray != null) {
            if (sparseArray.get(position) != null && sparseArray.get(position)) {
                AnimatorFactory.getInstance(position).withChangeAnimator(position, positionOffset, viewList, positionOffsetPix, flag);
            }
        }
    }

每个页面的动画滑动状态会通过SparseArray进行维护:

    private SparseArray<Boolean> sparseArray = new SparseArray<Boolean>();

尼玛,写博客比写代码累多了,终于倒腾倒腾的差不多了,由于第一次写技术博客,有很多小瑕疵,当然由于代码只是自己闲暇之余写的Demo,性能方面还是有待优化的,希望自己坚持下去,做一个懂得记录的Coder。

Github下载地址:https://github.com/dashentao1989/SplashView.git

你可能感兴趣的:(高仿有赞微小店SplashView)