從事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。