高仿有贊微小店SplashView

從事android開發有段時間了,總是說該寫寫技術博客了,分享知識的同時也能從中知道自己的不足,有挫折纔會有動力,有爭吵纔會有成長,大家一起共勉吧。

直接進入主題吧,前兩天正好看見一款App,對裏面的Splash View給吸引住了, 像我們一般的App一般不會在Splash View花費太多的時間折騰,小公司大都功能至上,體驗次之。從一個App的每個設計細節往往能夠窺探出公司對產品和客戶的責任心,當然了,這個有點扯遠了,整個功能倒不是很難,我們一起來分析分析吧,麼麼噠!

首先我們從平臺上下載有贊微小店,將.apk後綴改成.zip解壓到任意文件夾,文件夾內容如下:
這裏寫圖片描述
在res裏面會找到相應的資源,往往大點的公司美工都是很不錯的,圖片也切的比較精美。
拿到想要的資源後,來分析分析設計需求吧:
1:每個子圖片都是相對性的佈局在自己的位子,並且以動畫的形式以一定的時間間隔進行展示,凸顯層次感。
2:滑動的過程中,後面的背景圖不會跟着一起滑動,滑動的過程中背景圖的透明度會隨着頁面的左右滑動正比漸變,直至完整滑出頁面。
3:每滑到新頁面都會將舊頁面進行隱藏,並以動畫的形式展現新頁面,凸顯層次感。

大概就這麼多了,運行效果圖如下,加深大家的理解:
這裏寫圖片描述
下面我們一起用代碼來實現:
主佈局代碼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

發佈了20 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章