解決ViewPager設定切換動畫PageTransformer後子頁無法觸控的問題
阿新 • • 發佈:2019-02-09
通過ViewPager.setPageTransformer()方法可以設定切換動畫,但是如果ViewPager的子頁中要處理觸控事件,如瀏覽圖片時對圖片放大縮小,ViewPager切換子頁後,不能處理觸控事件,似乎子頁裡面的變的不可點選。嘗試了很多中Google上的方法,仍不能解決問題。其實這個是android4.1+版本上的bug,在呼叫了setPageTransformer()方法後,切換子頁後,當前最上面的View並不是眼睛所看的,而是另一個隱藏的子頁,該隱藏的子頁消費了觸控事件。嘗試了把當前子頁“放到最上面”,view.bringToFornt(),甚至把其他看不見的子頁都設定為隱藏,otherView.setVisibility(View.GONE),當前子頁仍然不能處理觸控事件。
最後查看了viewPager的原始碼,發現執行切換動畫的程式碼在onPageScrolled()方法內:
if(this.mPageTransformer != null) { scrollX = this.getScrollX(); childCount = this.getChildCount(); for(i = 0; i < childCount; ++i) { View var15 = this.getChildAt(i); ViewPager.LayoutParams var16 = (ViewPager.LayoutParams)var15.getLayoutParams(); if(!var16.isDecor) { float var17 = (float)(var15.getLeft() - scrollX) / (float)this.getClientWidth(); this.mPageTransformer.transformPage(var15, var17); } } }
其中的mPageTransformer就是setPageTransformer()傳進來的引數。於是,解決的方法便出來了:
public class SimpleViewPager extends ViewPager { private PageTransformer mPageTransformer; public SimpleViewPager(Context context) { this(context, null); } public SimpleViewPager(Context context, AttributeSet attrs) { super(context, attrs); } /** * android4.1+設定PageTransformer會使ViewPager的子頁裡面的觸控事件異常 * (當前看到的子頁並非在最上面,所以觸控事件被隱藏在其上面的View給消費了) * 所以結合setPageTransformer(),在onPageScrolled()裡“手動”呼叫切換頁面的動畫 * * @param position * @param offset * @param offsetPixels */ @Override protected void onPageScrolled(int position, float offset, int offsetPixels) { super.onPageScrolled(position, offset, offsetPixels); // 下面的原始碼來自super.onPageScrolled() int scrollX; int childCount; int i; if (this.mPageTransformer != null) { scrollX = this.getScrollX(); childCount = this.getChildCount(); for (i = 0; i < childCount; ++i) { View var15 = this.getChildAt(i); ViewPager.LayoutParams var16 = (ViewPager.LayoutParams) var15.getLayoutParams(); if (!var16.isDecor) { float var17 = (float) (var15.getLeft() - scrollX) / (float) this.getClientWidth(); this.mPageTransformer.transformPage(var15, var17); } } } } private int getClientWidth() { return this.getMeasuredWidth() - this.getPaddingLeft() - this.getPaddingRight(); } /** * 覆蓋該方法,不設定PageTransformer,以成員變數的形式儲存PageTransformer * * @param reverseDrawingOrder * @param transformer */ @Override public void setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) { super.setPageTransformer(reverseDrawingOrder, null); mPageTransformer = transformer; } }
原理很簡單,既然是因為設定了PageTransformer才導致子頁的觸控事件異常,那麼就不設定該屬性,通過間接的方式執行切換動畫。上面的類繼承了ViewPager,覆蓋了setPageTransformer()和onPageScrolled(),儲存傳進來的PageTransformer物件,父類ViewPager的mPageTransformer實際上為空,在onPageScrolled()方法中“手動執行”切換動畫。