2014-09-11 113 views
2

我使用castorflex/VerticalViewPager庫包含帶有ListView裏面的片段。問題是,當我開始滑過ListView元素時,我無法更改ViewPager的頁面。當ListView到達ViewPager的頂部/底部列表時,是否有任何方法可以傳遞觸摸事件?我wan't達到流暢的效果(當列表不能再被滾動,ViewPager開始滾動,都在同一個觸摸事件)滾動縱向ViewPager與ListView裏面

回答

0

這是我爲實現here

取而代之的是RecyclerView的垂直尋呼機級解決方案實施擴展它,我們的定製內部RecyclerView類重寫自定義類 public boolean onTouchEvent(MotionEvent event)

在這裏我們可以通過MotionEvent event到一個類像如下,以確定是否要攔截事件:

/** 
* Tests the MotionEvent for valid behavior to care about overriding the touch event with 
*/ 
private boolean shouldDisableScrollableParent(final MotionEvent event) { 
    boolean intercept = false; 
    float x = event.getX(); 
    float y = event.getY(); 

    switch (event.getAction()) { 
     case MotionEvent.ACTION_MOVE: 

      float dx = x - mPreviousX; 
      float dy = y - mPreviousY; 

      // Here you can try to detect the swipe. It will be necessary to 
      // store more than the previous value to check that the user move constantly in the same direction 
      intercept = detectSwipe(dx, dy); 
      break; 

     case MotionEvent.ACTION_UP: 
     case MotionEvent.ACTION_CANCEL: 
     default: 
      break; 
    } 

    mPreviousX = x; 
    mPreviousY = y; 

    return intercept; 
} 

/** 
* Tests if we want to disable the parent touch interception 
*/ 
private boolean detectSwipe(final float dx, final float dy) { 
    // True if we're scrolling in Y direction 
    if (Math.abs(dx) < Math.abs(dy)) { 
     FoundationLog.d(TAG, "Direction Y is yielding: " + dy); 

     if (dy < 0) { 
      // Touch from lower to higher 
      return true; 
     } 

     // Top view isn't shown, can always scroll up 
     final View view = getChildAt(0); 
     if (view == null) { 
      return true; 
     } 

     // Top view baseline doesn't equal to top of the RecyclerView 
     if (view.getTop() < 0) { 
      return true; 
     } 
    } 

    return false; 
} 

然後在自定義RecyclerView類的public boolean onTouchEvent(MotionEvent event)方法,檢查是否getParent()(也可能是反覆這麼根父)解析爲類,你想從覆蓋觸摸的視圖的ViewParent。如果是的話,設置requestDisallowInterceptTouchEvent()trueViewParent

0

這是一個有點晚答覆,但我最近要求我們的應用程序ViewPager改爲垂直和我在我的名單有完全相同的問題。我希望這可以幫助可能有同樣問題的其他人。

首先,我的片段是ListFragment的擴展,但它對於包含列表的任何片段(顯然具有較小的修改)的作用方式相同。首先,我在列表中設置了一個OnScrollListener,並在onScrollStateChanged中設置了一個方法updateListVisibility,如果列表的頂部或底部的頂部在列表中可見(updateListPositionVisibility),則返回Activity的更新。

public class MyListFragment extends ListFragment { 

    ..... 
    private OnScrollStateChangedListener mListener; 
    ..... 

    @Override 
    public void onViewCreated(View view, Bundle savedInstanceState) { 

     super.onViewCreated(view, savedInstanceState); 
     ...... 
     getListView().setOnScrollListener(new AbsListView.OnScrollListener() { 

      @Override 
      public void onScrollStateChanged(AbsListView view, int scrollState) { 
       updateListVisibility(); 
      } 

      @Override 
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 

      } 
     }); 
    } 

    public void updateListVisibility() { 

     if (getListView() != null && getListView().getChildCount() > 0) { 

      boolean firstItemVisible = getListView().getFirstVisiblePosition() == 0; 
      boolean topOfFirstItemVisible = getListView().getChildAt(0).getTop() == 0; 

      boolean lastItemVisible = getListView().getLastVisiblePosition() == getListView().getAdapter().getCount() - 1; 
      boolean bottomOfLastItemVisible = getListView().getChildAt(getListView().getChildCount() - 1).getBottom() <= getListView().getHeight(); 

      mListener.updateListPositionVisibility(firstItemVisible && topOfFirstItemVisible, lastItemVisible && bottomOfLastItemVisible); 
     } 
    } 

    @Override 
    public void onAttach(Activity activity) { 

     super.onAttach(activity); 
     try { 
      mListener = (OnScrollStateChangedListener) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() + " must implement OnScrollStateChangedListener"); 
     } 
    } 


    /** 
    * Container Activity must implement this interface.... 
    */ 
    public interface OnScrollStateChangedListener { 

     public void updateListPositionVisibility(boolean topIsVisible, boolean bottomIsVisible); 
    } 

    ..... 
} 

在我的活動我把我的ViewPager的OnPageChangeListener和使用onPageSelected我用我的轉接器來獲得片段,這樣我可以稱之爲updateListVisibility就可以了,然後叫回我的活動。我的回調實現使用列表頂部和底部的可見性狀態更新了ViewPager(請參閱setListViewPositionsInViewPager)。

public class VerticallyPagedActivity extends BaseFragmentActivity implements 
    MyListFragment.OnScrollStateChangedListener { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 

     ...... 

     mPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 

     } 

     @Override 
     public void onPageSelected(int position) { 
      Object fragment = mAdapter.mItems.get(position); 
      if (fragment instanceof MyListFragment) { 
       ((MyListFragment) fragment).updateListVisibility(); 
      } else { 
       setListViewPositionsInViewPager(false, false); 
      } 
     } 

     @Override 
     public void onPageScrollStateChanged(int state) { 

     } 
    }); 
} 

public void setListViewPositionsInViewPager(boolean handleEventTop, boolean handleEventBottom) { 
    mPager.setListVisibility(handleEventTop, handleEventBottom); 
} 

// Callback. 
@Override 
public void updateListPositionVisibility(boolean topIsVisible, boolean bottomIsVisible) { 
    setListViewPositionsInViewPager(topIsVisible, bottomIsVisible); 
} 

我的適配器只是在mItems中維護片段的一個實例。

public class MyAdapter extends FragmentStatePagerAdapter { 

    ..... 
    public Map<Integer, Fragment> mItems; 

    public MyAdapter(FragmentManager fm, List<Content> content) { 
    super(fm); 
    mItems = new HashMap<>(); 
    ..... 

    @Override 
    public Fragment getItem(int position) { 

     ..... 
     MyListFragment fragment = new MyListFragment(); 
     ..... 
     mItems.put(position, fragment); 
     return fragment; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     mItems.remove(position); 
     super.destroyItem(container, position, object); 
    } 
} 

然後在我的Castorflex垂直視圖分頁器中,我使用名爲setListVisibility的方法設置列表可見性值。每次滾動列表或ViewPager被分頁時,這些都會更新,這意味着它們始終處於最新狀態。最重要的部分是,當頁面頂部可見並且用戶試圖向上或底部可見並且用戶試圖下去時,尋呼機攔截事件。使用MotionEvent.ACTION_MOVE下的switch語句內計算的dy值很容易實現這一點。

public class VerticalPager extends ViewGroup { 

    ..... 
    private boolean topOfListIsVisible; 
    private boolean bottomOfListIsVisible; 

    public void setListVisibility(boolean pTop, boolean pBottom) { 
     topOfListIsVisible = pTop; 
     bottomOfListIsVisible = pBottom; 
    } 

    ..... 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 

     ...... 

     switch (action) { 
      case MotionEvent.ACTION_MOVE: { 

      ...... 
      final float y = MotionEventCompat.getY(ev, pointerIndex); 
      final float dy = y - mLastMotionY; 
      final float yDiff = Math.abs(dy); 
      ...... 

      // Pager needs to handle the event. 
      if (topOfListIsVisible && bottomOfListIsVisible || bottomOfListIsVisible && dy < 0 || topOfListIsVisible && dy > 0) { 
       return true; 
      } 

     } 
     ..... 
    } 

    ..... 
} 
相關問題