編輯:關於Android編程
每當viewpager上一個可見或依附的頁面發生了滾動事件就會調用PageTransformer,這讓應用可以使用自定義transformation讓viewpager某一個頁面視圖上實現某些特定的動畫屬性。
但是這樣的屬性動畫只能支持到android3.0版本或以上,在早期的版本上設置viewpager的PageTransformer會被忽略。
transformPage 應用屬性動畫到一個指定的頁面
void transformPage (View page, float position)

package com.example.simple.pagertransformdemo;
public class MainActivity extends AppCompatActivity {
private int imgIds[] = {R.drawable.img_1, R.drawable.img_2, R.drawable.img_3};
private List viewList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i < 3; i++) {
View rootView = View.inflate(MainActivity.this, R.layout.item_pager, null);
ImageView imageView = (ImageView) rootView.findViewById(R.id.pager_iv);
imageView.setImageResource(imgIds[i]);
TextView textView = (TextView) rootView.findViewById(R.id.pager_tv);
textView.setText(String.valueOf(i));
viewList.add(i, rootView);
}
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(new MyAdapter());
}
private class MyAdapter extends PagerAdapter {
@Override
public int getCount() {
return 3;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(viewList.get(position));
return viewList.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(viewList.get(position));
}
}
}

我們多加了一行代碼
viewPager.setPageTransformer(true ,new ZoomInTransform());
看看這這句代碼的作用
看源碼也可以得出
public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
if (Build.VERSION.SDK_INT >= 11) {
final boolean hasTransformer = transformer != null;
final boolean needsPopulate = hasTransformer != (mPageTransformer != null);
mPageTransformer = transformer;
setChildrenDrawingOrderEnabledCompat(hasTransformer);
if (hasTransformer) {
//reverseDrawingOrder等於true時為倒序,false為正序
mDrawingOrder = reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD;
} else {
mDrawingOrder = DRAW_ORDER_DEFAULT;
}
if (needsPopulate) populate();
}
}
將 reverseDrawingOrder 改爲 false 看看效果
viewPager.setPageTransformer(false ,new ZoomInTransform());

再看看ZoomInTransform的代碼就一目了然了
public class ZoomInTransform implements ViewPager.PageTransformer {
public static final String TAG = "simple_PagerTransform";
@Override
public void transformPage(View page, float position) {
int width = page.getWidth();
int height = page.getHeight();
//這裏只對右邊的view做了操作
if (position > 0 && position <= 1) {//right scorlling
//position是1.0->0,但是沒有等於0
Log.e(TAG, "right----position====" + position);
//設置該view的X軸不動
page.setTranslationX(-width * position);
//設置縮放中心點在該view的正中心
page.setPivotX(width / 2);
page.setPivotY(height / 2);
//設置縮放比例(0.0,1.0]
page.setScaleX(1 - position);
page.setScaleY(1 - position);
} else if (position >= -1 && position < 0) {//left scrolling
} else {//center
}
}
}
我們還可以看看transformPage是怎麼來的
//這是viewpager源代碼的一部分,transformPage方法的來源
if (mPageTransformer != null) {
final int scrollX = getScrollX();
final int childCount = getChildCount();
//遍歷viewpager所有的子view
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.isDecor) continue;
//position等於該view的左起點減去在X軸的位移除以viewpager的寬度,也就是算出真正的位移比例
final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();
mPageTransformer.transformPage(child, transformPos);
}
}

public class SimplePageTransform implements ViewPager.PageTransformer {
@Override
public void transformPage(View view, float position) {
int width = view.getWidth();
int pivotX = 0;
if (position <= 1 && position > 0) {// right scrolling
pivotX = 0;
} else if (position == 0) {
} else if (position < 0 && position >= -1) {// left scrolling
pivotX = width;
}
//設置x軸的錨點
view.setPivotX(pivotX);
//設置繞Y軸旋轉的角度
view.setRotationY(90f * position);
}
}
@Override
public void transformPage(View view, float position) {
if (position <= 1 && position > 0) {
int hashCode = view.hashCode();
Log.d(TAG,"right hashCode="+hashCode);
} else if (position == 0) {
int hashCode = view.hashCode();
Log.d(TAG,"center hashCode="+hashCode);
} else if (position < 0 && position >= -1) {
int hashCode = view.hashCode();
Log.w(TAG,"left hashCode="+hashCode);
}
}
看看log信息
下一頁的view hashcode
left hashCode=75472620
right hashCode=55231157
center hashCode=55231157
再下一頁的view hashcode
left hashCode=55231157
right hashCode=45932420
center hashCode=45932420
上一頁的view hashcode
left hashCode=55231157
right hashCode=45932420
center hashCode=55231157
再上一頁的view hashcode
left hashCode=75472620
right hashCode=55231157
center hashCode=75472620
由此以及上面transformPage方法的出處可得出規律,transformPage返回的view並不是一個,而是根據相應的position的返回相應的view。
也由此可以提出viewpager的坐標系(ps:不會畫圖請不要打我)

淺藍色為left view,紅色為center view,深藍色為right view,當滑動事件開始,他們的關系也會跟變化,所以可得出在[-1,0)這個區間為left,(0,1]這個區間為right,只有當等於0才為center。如果viewpager裡面view很多肯定就還會有-2,+2等等的其他坐標點,但是我們只關注left,center,right這3個view上就可以實現很多炫酷的動畫啦!
Android-CleanArchitecture實戰
概述關於Retrofit,Rxjava,MVP等的使用現在已經成為了Android項目開發的標配,而Clean架構都能很好的兼顧這些方面,使得代碼結構清晰,而且在一般在項
Qt for Android 編譯安卓原生可執行程序
作為 C/C++ 程序員,有時候我們希望在安卓上運行從 C/C++ 生成的可執行程序,而不是在 Java 中通過 jni 的方式來調用 C
Android開發使用的常見第三方框架匯總
1、volley項目地址 https://github.com/smanikandan14/Volley-demo(1) JSON,圖像等的異步下載;(2) 網絡請求的排
Android5.0L退出APP橫豎屏切換導致的觸摸屏輸入(Touch Event)無效(凍屏)問題分析(Key Event仍然有效)
一、問題現象1、多次進出需要強制橫屏的app,比如Real FootBall2015,在退出app的時候會有概率出現退出卡頓,然後TP無法輸入的問題。2、出問題時Powe