Android ViewPager實現(xiàn)動畫切換效果
概述
ViewPager是Android開發(fā)中使用場景非常頻繁的控件,單一的動畫效果切換已經(jīng)越來越不能滿足追求個性化的應(yīng)用中。而ViewPager自身也帶有一個接口來處理頁面間的動畫切換,那就是setPageTransformer。下面我們通過代碼來學(xué)習動畫效果的切換。
實現(xiàn)簡單動畫切換
代碼如下:
1.布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_pager_box"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_margin="10dp"
android:layout_width="wrap_content"
android:layout_height="120dp" />
</LinearLayout>
MainActivity 中相關(guān) java 代碼
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
public class MainActivity extends Activity {
private ViewPager viewPager;
private int[] imageIds = new int[]{R.drawable.pic1,R.drawable.pic2,R.drawable.pic3,R.drawable.pic4,R.drawable.pic5,};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setOffscreenPageLimit(3); //設(shè)置內(nèi)存中預(yù)加載頁面數(shù)
viewPager.setPageTransformer(true, new DepthPageTransformer()); //設(shè)置頁面切換過渡動畫
viewPager.setAdapter(new PagerAdapter() {
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public int getCount() {
return imageIds.length;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(MainActivity.this);
imageView.setScaleType(ScaleType.CENTER_CROP);
imageView.setImageResource(imageIds[position]);
imageView.setTag(position); //設(shè)置標記
container.addView(imageView);
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
container.removeView((View)object);
}
});
}
}
3.控制切換動畫的類DepthPageTransformer的代碼
import android.support.v4.view.ViewPager;
import android.view.View;
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
@Override
public void transformPage(View view, float position) {
android.util.Log.i("yuminfeng", "====view:" + view.getTag() + ",position:" + position);
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
上面的代碼十分簡單,僅僅只是ViewPager的初始化配置,然后通過setPageTransformer設(shè)置頁面切換動畫。有一個細節(jié)還需要注意,設(shè)置setOffscreenPageLimit(3),表示內(nèi)存中預(yù)加載頁面為3,這三個頁面是不可見的。如果加上當前顯示的頁面,總共初始化了4個頁面。不設(shè)置的話,系統(tǒng)使用默認的預(yù)加載的頁數(shù)為1。
第一次啟動應(yīng)用后,我們通過在DepthPageTransformer類中記錄的日志可以看到,如下:
總共初始化了4個view,其中當前對用戶可見view的位置為0,其余都是不可見。所以當position=0時,表示當前的頁面。
我們繼續(xù)操作并向左滑動一頁,日志如下:
由此可以看到,之前的view的位置變?yōu)?1,它的右邊的view位置為0,變成可見。
繼續(xù)滑動至最后一頁后:
我們看到最后一頁的view已經(jīng)展現(xiàn)在用戶面前,位置為0,而其他頁面位置都是為負,表示所有頁面都滑至左邊。這時我們注意的話,可以發(fā)現(xiàn)view:0,不在日志信息中,難道它沒有被初始化?其實它已經(jīng)被系統(tǒng)回收了,通過Adapter中destroyItem方法。因為我們之前設(shè)置ViewPager中預(yù)加載的頁數(shù)限制為3,系統(tǒng)中最多的存在4個view,所以view:0被回收。
從上面的分析我們可以知道,當view的position處于[-1,1]時,該view能夠被用戶所見,其他位置便不可見。而PageTransformer的接口中,真是利用了這個特點,根據(jù)view的position來對它進行縮放,旋轉(zhuǎn)等動畫操作。我們繼續(xù)分析DepthPageTransformer類:
當 position < -1,即[-Infinity,-1) 時:
view處于左邊不可見中,這里view.setAlpha(0); 表示完全透明。
當-1 <= position <= 0 時,該view處于可見區(qū)域,:
1.如果view向左滑動,表示當前view逐漸滑出可見區(qū)域
2.如果view向右滑動,表示左邊的view逐漸劃入當前可見區(qū)域。
view.setAlpha(1),設(shè)置透明度,表示完全不透明。
view.setTranslationX(0),表示設(shè)置view相對于左側(cè)位置的水平位置,距離左邊的距離。
view.setScaleX(1)和view.setScaleY(1),表示view的x,y軸不進行縮放。
當0 < position <= 1 時,該view處于可見區(qū)域:
1.如果view向右滑動,表示當前view逐漸滑出可見區(qū)域。
2.如果view向左滑動,表示右邊的view逐漸滑入可見區(qū)域。
view.setAlpha(1 - position),根據(jù)view滑動的位置,設(shè)置view的透明度。position 越接近于0,表明view面對用戶顯示的越多,所以就越不透明。
view.setTranslationX(pageWidth * -position),根據(jù)view滑動的位置,設(shè)置view相對于左側(cè)位置的水平位置,當position = 0 時,view完全顯示,這時相對左邊為0,當 position = 1 時,view完全不可見,這時相對左邊為view的寬度。
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
根據(jù)view的position,設(shè)置view的縮放大小。當 position,越大時,越遠離用戶界面,于是越不可見。
當1< position 時,即(1,+Infinity]時:
view.setAlpha(0),設(shè)置完全透明不可見。
上述代碼執(zhí)行效果如下:

我們還可以定制其他的動畫效果,實現(xiàn)原理和上面一樣,這里就不一一列出來了。
實現(xiàn)廣告輪播效果圖
如圖:

實現(xiàn)上面的效果圖,只需要對上面的代碼進行一些修改即可:
想要在屏幕上出現(xiàn)多個頁面,我們需要設(shè)置屬性:android:clipChildren=”false”,該屬性的意思是在View進行繪制的時候,不去裁切它們的顯示范圍,即不限制view的顯示范圍。
我們修改布局文件,如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_pager_box"
android:layout_width="match_parent"
android:layout_height="160dp"
android:gravity="center"
android:clipChildren="false"
android:orientation="horizontal" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_margin="30dp"
android:layout_height="120dp" />
</LinearLayout>
在ViewPager的外面控件中設(shè)置了android:clipChildren=”false”,然后設(shè)置viewpager中android:layout_margin屬性,留出間距,方便顯示左右兩邊的圖片。后面我們還要java代碼設(shè)置viewpager的屬性,如:
viewPager.setPageMargin(40); //設(shè)置頁面間間距
這樣可以讓頁面之間存在一定的間隔。最后,我們通過setPageTransformer方法設(shè)置自己定義的動畫即可,與上面一致。
該效果的動畫類代碼:
import android.support.v4.view.ViewPager;
import android.view.View;
public class AlphaScaleTransformer implements ViewPager.PageTransformer {
private static final float DEFAULT_MIN_ALPHA = 0.5f;
private float mMinAlpha = DEFAULT_MIN_ALPHA;
private static final float DEFAULT_MIN_SCALE = 0.85f;
private float mMinScale = DEFAULT_MIN_SCALE;
public static final float DEFAULT_CENTER = 0.5f;
@Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
view.setScaleX(0.999f);// hack
view.setPivotY(pageHeight / 2);
view.setPivotX(pageWidth / 2);
if (position < -1) { // [-Infinity,-1)
view.setAlpha(mMinAlpha);
view.setScaleX(mMinScale);
view.setScaleY(mMinScale);
view.setPivotX(pageWidth);
} else if (position <= 1) { // [-1,1]
if (position < 0) // [0,-1]
{ // [1,min]
float factor = mMinAlpha + (1 - mMinAlpha) * (1 + position);
float scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale;
view.setAlpha(factor);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
view.setPivotX(pageWidth * (DEFAULT_CENTER + (DEFAULT_CENTER * -position)));
} else// [1,0]
{
// [min,1]
float factor = mMinAlpha + (1 - mMinAlpha) * (1 - position);
float scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale;
view.setAlpha(factor);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
view.setPivotX(pageWidth * ((1 - position) * DEFAULT_CENTER));
}
} else { // (1,+Infinity]
view.setAlpha(mMinAlpha);
view.setPivotX(0);
view.setScaleX(mMinScale);
view.setScaleY(mMinScale);
}
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習有所幫助,也希望大家多多支持腳本之家。
- anndroid使用ViewPager實現(xiàn)三個fragment切換
- Android使用TabLayou+fragment+viewpager實現(xiàn)滑動切換頁面效果
- Android App中使用ViewPager+Fragment實現(xiàn)滑動切換效果
- Android基于ViewPager實現(xiàn)類似微信頁面切換效果
- Android使用自定義PageTransformer實現(xiàn)個性的ViewPager動畫切換效果
- Android實現(xiàn)單頁顯示3個Item的ViewPager炫酷切換效果
- Android使用ViewPager實現(xiàn)頂部tabbar切換界面
- Android中TabLayout結(jié)合ViewPager實現(xiàn)頁面切換
- Android使用ViewPager快速切換Fragment時卡頓的優(yōu)化方案
相關(guān)文章
Android獲取系統(tǒng)時間以及網(wǎng)絡(luò)時間
這篇文章主要為大家詳細介紹了Android獲取系統(tǒng)時間以及網(wǎng)絡(luò)時間的方法,感興趣的小伙伴們可以參考一下2016-07-07
Android開發(fā)技巧之ViewStub控件惰性裝載
布局文件中的控件并不一定在程序啟動時全都用到,有一些控件只在特定的情況下才會被使用到;我們急需一種機制來改變<include>標簽的這種行為,只在需要時裝載控件。這種機制就是本節(jié)要介紹的ViewStub控件2013-01-01
Android Jetpack架構(gòu)組件Lifecycle詳解
這篇文章主要介紹了Android Jetpack架構(gòu)組件Lifecycle詳解,Lifecycle是Jetpack架構(gòu)組件中用來感知生命周期的組件,使用Lifecycles可以幫助我們寫出和生命周期相關(guān)更簡潔更易維護的代碼。對此感興趣的小伙伴可以來學(xué)習一下2020-07-07
解決Android Studio導(dǎo)入項目非常慢的辦法
在使用Android studio的時候常常遇到這樣的問題,從其他地方導(dǎo)入項目,Android studio呈現(xiàn)非常慢的現(xiàn)象!當遇到這種情況時,可以看看是下面這篇文章,再按照方法來解決!2016-09-09

