2

我已经实现了一个水平滚动列表以及最新趋势的swipey标签(如google play store)。但是,即使当我尝试滚动我的水平列表(标签的一部分),而是,下一个标签出现。只有当我将手指放在列表以外的地方(以保持当前标签)时,我可以滚动列表。在swipey标签中水平滚动:android

请建议如何确保每当我尝试滚动我的列表时,选项卡不会更改。在任何其他地区刷卡应该改变标签。

以下是我的水平列表adpater观的落实:

public class HorizontalView extends AdapterView{ 

    public boolean mAlwaysOverrideTouch = true; 
    protected ListAdapter mAdapter; 
    private int mLeftViewIndex = -1; 
    private int mRightViewIndex = 0; 
    protected int mCurrentX; 
    protected int mNextX; 
    private int mMaxX = Integer.MAX_VALUE; 
    private int mDisplayOffset = 0; 
    protected Scroller mScroller; 
    private GestureDetector mGesture; 
    private Queue mRemovedViewQueue = new LinkedList(); 
    private OnItemSelectedListener mOnItemSelected; 
    private OnItemClickListener mOnItemClicked; 
    private OnItemLongClickListener mOnItemLongClicked; 
    private boolean mDataChanged = false; 

    public HorizontalView(Context context, AttributeSet attrs){ 
     super(context, attrs); 
     initView(); 
    } 

    private synchronized void initView(){ 
     mLeftViewIndex = -1; 
     mRightViewIndex = 0; 
     mDisplayOffset = 0; 
     mCurrentX = 0; 
     mNextX = 0; 
     mMaxX = Integer.MAX_VALUE; 
     mScroller = new Scroller(getContext()); 
     mGesture = new GestureDetector(getContext(), mOnGesture);  
    } 

    @Override 
    public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener){ 
     mOnItemSelected = listener; 
    } 

    @Override 
    public void setOnItemClickListener(AdapterView.OnItemClickListener listener){ 
     mOnItemClicked = listener; 
    } 

    @Override 
    public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) { 
     mOnItemLongClicked = listener; 
    } 

    private DataSetObserver mDataObserver = new DataSetObserver() { 
     @Override 
     public void onChanged() { 
      synchronized (HorizontalView.this) { 
      mDataChanged = true; 
      } 
      invalidate(); 
      requestLayout(); 
     } 

     @Override 
     public void onInvalidated() { 
      reset(); 
      invalidate(); 
      requestLayout(); 
     } 
    }; 

    @Override 
    public ListAdapter getAdapter() { 
     return mAdapter; 
    } 


    @Override 
    public View getSelectedView() { 
     // TODO Auto-generated method stub 
     return null; 
    } 


    public void setAdapter(ListAdapter adapter) { 
     // TODO Auto-generated method stub 
     if (mAdapter != null) { 
      mAdapter.unregisterDataSetObserver(mDataObserver); 
     } 
     mAdapter = adapter; 
     mAdapter.registerDataSetObserver(mDataObserver); 
     reset();   
    } 

    private synchronized void reset() { 
      initView(); 
      removeAllViewsInLayout(); 
      requestLayout(); 
    } 

    @Override 
    public void setSelection(int position) { 
     // TODO Auto-generated method stub 

    } 

    @SuppressWarnings("deprecation") 
    private void addAndMeasureChild(final View child, int viewPos) { 
     LayoutParams params = child.getLayoutParams(); 
     if (params == null) { 
      params = new LayoutParams(LayoutParams.FILL_PARENT, 
      LayoutParams.FILL_PARENT); 
     } 

     addViewInLayout(child, viewPos, params, true); 
     child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); 
    } 

    @Override 
    protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) { 
     super.onLayout(changed, left, top, right, bottom); 

     if (mAdapter == null) { 
      return; 
     } 

     if (mDataChanged) { 
      int oldCurrentX = mCurrentX; 
      initView(); 
      removeAllViewsInLayout(); 
      mNextX = oldCurrentX; 
      mDataChanged = false; 
     } 

     if (mScroller.computeScrollOffset()) { 
      int scrollx = mScroller.getCurrX(); 
      mNextX = scrollx; 
     } 

     if (mNextX <= 0) { 
      mNextX = 0; 
      mScroller.forceFinished(true); 
     } 

     if (mNextX >= mMaxX) { 
      mNextX = mMaxX; 
      mScroller.forceFinished(true); 
     } 

     int dx = mCurrentX - mNextX; 

     // removeNonVisibleItems(dx); 
     fillList(dx); 
     positionItems(dx); 

     mCurrentX = mNextX; 

     if (!mScroller.isFinished()) { 
      post(new Runnable() { 
       @Override 
       public void run() { 
        requestLayout(); 
       } 
      }); 
     } 
    } 

    private void fillList(final int dx) { 
     int edge = 0; 
     View child = getChildAt(getChildCount() - 1); 
     if (child != null) { 
      edge = child.getRight(); 
     } 
     fillListRight(edge, dx); 

     edge = 0; 
     child = getChildAt(0); 
     if (child != null) { 
      edge = child.getLeft(); 
     } 
     fillListLeft(edge, dx); 
    } 

    private void fillListRight(int rightEdge, final int dx) { 
     while (rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) { 
      View child = mAdapter.getView(mRightViewIndex, (View) mRemovedViewQueue.poll(), this); 
      addAndMeasureChild(child, -1); 
      rightEdge += child.getMeasuredWidth(); 

      if (mRightViewIndex == mAdapter.getCount() - 1) { 
       mMaxX = mCurrentX + rightEdge - getWidth(); 
      } 

      if (mMaxX < 0) { 
       mMaxX = 0; 
      } 
      mRightViewIndex++; 
     } 
    } 

    private void fillListLeft(int leftEdge, final int dx) { 
     while (leftEdge + dx > 0 && mLeftViewIndex >= 0) { 
     View child = mAdapter.getView(mLeftViewIndex, (View) mRemovedViewQueue.poll(), this); 
     addAndMeasureChild(child, 0); 
     leftEdge -= child.getMeasuredWidth(); 
     mLeftViewIndex--; 
     mDisplayOffset -= child.getMeasuredWidth(); 
     } 
    } 

    private void positionItems(final int dx) { 
     if (getChildCount() > 0) { 
     mDisplayOffset += dx; 
     int left = mDisplayOffset; 
     for (int i = 0; i < getChildCount(); i++) { 
      View child = getChildAt(i); 
      int childWidth = child.getMeasuredWidth(); 
      child.layout(left, 0, left + childWidth,child.getMeasuredHeight()); 
      left += childWidth; 
     } 
     } 
    } 

    public synchronized void scrollTo(int x) { 
     mScroller.startScroll(mNextX, 0, x - mNextX, 0); 
     requestLayout(); 
    } 

    @Override 
    public boolean dispatchTouchEvent(MotionEvent ev) { 
     boolean handled = super.dispatchTouchEvent(ev); 
     handled |= mGesture.onTouchEvent(ev); 
     return handled; 
    } 

    protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     synchronized (HorizontalView.this) { 
      mScroller.fling(mNextX, 0, (int) -velocityX, 0, 0, mMaxX, 0, 0); 
     } 
     requestLayout(); 

     return true; 
    } 

    protected boolean onDown(MotionEvent e) { 
     mScroller.forceFinished(true); 
     return true; 
    } 

    private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener(){ 

     @Override 
     public boolean onDown(MotionEvent e) { 
      return HorizontalView.this.onDown(e); 
     } 

     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) { 
      return HorizontalView.this.onFling(e1, e2, velocityX, velocityY); 
     } 

     @Override 
     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 

      synchronized (HorizontalView.this) { 
      mNextX += (int) distanceX; 
      } 
      requestLayout(); 

      return true; 
     } 

     @Override 
     public boolean onSingleTapConfirmed(MotionEvent e) { 
      for (int i = 0; i < getChildCount(); i++) { 
      View child = getChildAt(i); 
      if (isEventWithinView(e, child)) { 
       if (mOnItemClicked != null) { 
        mOnItemClicked.onItemClick(HorizontalView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i)); 
       } 
       if (mOnItemSelected != null) { 
        mOnItemSelected.onItemSelected(HorizontalView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i)); 
       } 
       break; 
      } 
      } 
      return true; 
     } 

     @Override 
     public void onLongPress(MotionEvent e) { 
      int childCount = getChildCount(); 
      for (int i = 0; i < childCount; i++) { 
       View child = getChildAt(i); 
       if (isEventWithinView(e, child)) { 
        if (mOnItemLongClicked != null) { 
       mOnItemLongClicked.onItemLongClick(HorizontalView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i)); 
        } 
        break; 
       } 

      } 
     } 

     private boolean isEventWithinView(MotionEvent e, View child) { 
      Rect viewRect = new Rect(); 
      int[] childPosition = new int[2]; 
      child.getLocationOnScreen(childPosition); 
      int left = childPosition[0]; 
      int right = left + child.getWidth(); 
      int top = childPosition[1]; 
      int bottom = top + child.getHeight(); 
      viewRect.set(left, top, right, bottom); 
      return viewRect.contains((int) e.getRawX(), (int) e.getRawY()); 
     } 
    }; 

    @Override 
    public void setAdapter(Adapter adapter) { 
     // TODO Auto-generated method stub 

    } 
    } 

其中包含水平列表也有其他意见的片段。以下是它的布局文件:

<?xml version="1.0" encoding="UTF-8"?> 

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:background="@drawable/photo" 
    android:orientation="vertical"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="horizontal" 
     android:gravity="center_vertical"> 

     <ImageView 
      android:id="@+id/main_image" 
      android:layout_width="100dp" 
      android:layout_height="100dp" 
      android:gravity="left" 
      android:contentDescription="@string/sunny_desc" 
      android:src="@drawable/sun5" /> 

     <LinearLayout 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:orientation="vertical" 
      android:gravity="center"> 

      <TextView 
       android:id="@+id/temp" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       android:layout_margin="10dp" 
       style="@android:style/TextAppearance.Large" 
       android:textStyle="bold" 
       android:gravity="right" 
       android:textColor="#FFFFFF" 
       android:text="@string/temp" /> 

      <TextView 
       android:id="@+id/type" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       android:layout_margin="10dp" 
       style="@android:style/TextAppearance.Medium" 
       android:textStyle="italic" 
       android:gravity="right" 
       android:textColor="#FFFFFF" 
       android:text="@string/type" /> 

     </LinearLayout>  

    </LinearLayout> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="horizontal" 
     android:baselineAligned="false" 
     android:gravity="center_vertical"> 

     <LinearLayout 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:orientation="vertical" 
      android:gravity="center_vertical"> 

      <TextView 
       android:id="@+id/humdity" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_marginTop="5dp" 
       android:layout_marginLeft="10dp" 
       android:layout_marginBottom="5dp" 
       android:gravity="left" 
       android:textColor="#FFFFFF" 
       android:text="@string/humidity" /> 

      <TextView 
       android:id="@+id/wind" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:layout_marginLeft="10dp" 
       android:layout_marginBottom="2dp" 
       android:gravity="left" 
       android:textColor="#FFFFFF" 
       android:text="@string/wind" /> 

     </LinearLayout> 

     <LinearLayout 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:orientation="vertical" 
      android:gravity="center_vertical"> 

      <TextView 
       android:id="@+id/sunrise" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       android:layout_marginTop="5dp" 
       android:layout_marginRight="10dp" 
       android:layout_marginBottom="5dp" 
       android:gravity="right" 
       android:layout_weight="1" 
       android:textColor="#FFFFFF" 
       android:text="@string/sunrise" /> 

      <TextView 
       android:id="@+id/sunset" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       android:layout_marginRight="10dp" 
       android:layout_marginBottom="2dp" 
       android:gravity="right" 
       android:textColor="#FFFFFF" 
       android:layout_weight="1" 
       android:text="@string/sunset" /> 
     </LinearLayout> 

    </LinearLayout> 



    <LinearLayout 
     android:layout_width="wrap_content" 
     android:layout_height="0dp" 
     android:layout_weight="1" 
     android:orientation="horizontal" > 

     <com.sparktg.weather.HorizontalView 
      android:id="@+id/item" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginLeft="10dp" 
      android:layout_marginRight="10dp" 
      android:layout_marginTop="10dp" 
      android:smoothScrollbar="true" 
      android:spacing="20dp" 
      android:cacheColorHint="#FFFFFF"> 
     </com.sparktg.weather.HorizontalView> 

    </LinearLayout> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical"> 

     <ListView android:id="@id/android:list" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:orientation="vertical 
       android:drawSelectorOnTop="false"/> 

    </LinearLayout> 

    </LinearLayout> 

我应该尝试在单个选项卡中实现多个片段吗?如果是,我该怎么做?我曾尝试使用下面的教程来实现我的重击标签:

http://davidjkelley.net/?p=34

请帮助。

回答

0

经过一番研究,我遇到了以下解决方案以解决我的问题。在我的适配器视图中添加了以下方法,之后滚动处理了哪个视图的滚动。

// Following is the method to ensure that when the view ontaing this 
// horizontal list is touched, rather than swiping between adjacent tabs 
// (using left and right swipe), the list can be scrolled. 
@Override 
public boolean onTouchEvent(MotionEvent p_event) { 
    if (p_event.getAction() == MotionEvent.ACTION_MOVE 
      && getParent() != null) { 
     getParent().requestDisallowInterceptTouchEvent(true); 
    } 

    return super.onTouchEvent(p_event); 
} 
0

TabLayout有一个方法setTabMode()

要么MODE_FIXED(默认) 或 MODE_SCROLLABLE

您也可以在XML与app:tabMode="scrollable".

定义此