如何添加子ScrollViews?

时间:2014-08-19 09:15:18

标签: android touch focus android-scrollview

我有一个外部Horizo​​ntalScrollView,它允许我在我的应用程序中滚动3页。在第3页(最右边)页面上,我有一个屏幕,其中包含外部scrollview中的Horizo​​ntalScrollView。

然而,当我触摸子滚动视图时,它的外部滚动视图会获取触摸事件。如何确保子scrollview获取事件?

   +---screen--+
   |+----------+----------+----------+
   |+  outer   |          |+---------+---------+---------+
   |+  scroll  |          ||  child scroll     |         |
   |+          |          |+--------++---------+---------+
   |+          |          +----------+                 <>
   |+          |          + Textview +
   |+----------+----------+----------+
   +-----------+                   <>

这是我借用的扩展Horizo​​ntalScrollView的代码:

import android.app.ActionBar.LayoutParams;
import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.HorizontalScrollView;

public class CustomHorizontalScrollView extends HorizontalScrollView implements
    OnTouchListener, OnGestureListener
{

  private static final int SWIPE_MIN_DISTANCE       = 300;

  private static final int SWIPE_THRESHOLD_VELOCITY = 300;
  private static final int SWIPE_PAGE_ON_FACTOR     = 5;

  private GestureDetector  gestureDetector;
  private int              scrollTo                 = 0;
  private int              maxItem                  = 0;
  private int              activeItem               = 0;
  private float            prevScrollX              = 0;
  private boolean          start                    = true;
  private int              itemWidth                = 0;
  private float            currentScrollX;
  private boolean          flingDisable             = true;
  public int tag;

  public CustomHorizontalScrollView( Context context )
  {
    super( context );
    setLayoutParams( new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) );
  }

  public CustomHorizontalScrollView( Context context, int maxItem, int itemWidth )
  {
    this( context );
    this.maxItem = maxItem;
    this.itemWidth = itemWidth;
    gestureDetector = new GestureDetector( this );
    this.setOnTouchListener( this );
  }

  @Override
  public boolean onTouch( View v, MotionEvent event )
  {
    if( gestureDetector.onTouchEvent( event ) )
    {
      return true;
    }
    Boolean returnValue = gestureDetector.onTouchEvent( event );

    int x = (int) event.getRawX();

    switch( event.getAction() )
    {
      case MotionEvent.ACTION_MOVE:
        if( start )
        {
          this.prevScrollX = x;
          start = false;
        }
        break;
      case MotionEvent.ACTION_UP:
        start = true;
        this.currentScrollX = x;
        int minFactor = itemWidth / SWIPE_PAGE_ON_FACTOR;

        if( ( this.prevScrollX - this.currentScrollX ) > minFactor )
        {
          if( activeItem < maxItem - 1 )
            activeItem = activeItem + 1;

        }
        else 
        if( ( this.currentScrollX - this.prevScrollX ) > minFactor )
        {
          if( activeItem > 0 )
            activeItem = activeItem - 1;
        }
        System.out.printf( "SV%d horizontal : %d\n", tag, activeItem );
        scrollTo = activeItem * itemWidth;
        this.smoothScrollTo( scrollTo, 0 );
        returnValue = true;
        break;
    }
    return returnValue;
  }

  @Override
  public boolean onFling( MotionEvent e1, MotionEvent e2, float velocityX,
      float velocityY )
  {
    if( flingDisable )
      return false;
    boolean returnValue = false;
    float ptx1 = 0, ptx2 = 0;
    if( e1 == null || e2 == null )
      return false;
    ptx1 = e1.getX();
    ptx2 = e2.getX();
    // right to left

    if( ptx1 - ptx2 > SWIPE_MIN_DISTANCE
        && Math.abs( velocityX ) > SWIPE_THRESHOLD_VELOCITY )
    {
      if( activeItem < maxItem - 1 )
        activeItem = activeItem + 1;

      returnValue = true;

    }
    else if( ptx2 - ptx1 > SWIPE_MIN_DISTANCE
        && Math.abs( velocityX ) > SWIPE_THRESHOLD_VELOCITY )
    {
      if( activeItem > 0 )
        activeItem = activeItem - 1;

      returnValue = true;
    }
    scrollTo = activeItem * itemWidth;
    this.smoothScrollTo( 0, scrollTo );
    return returnValue;
  }

  @Override
  public boolean onDown( MotionEvent e )
  {
    return false;
  }

  @Override
  public void onLongPress( MotionEvent e )
  {
  }

  @Override
  public boolean onScroll( MotionEvent e1, MotionEvent e2, float distanceX,
      float distanceY )
  {
    return false;
  }

  @Override
  public void onShowPress( MotionEvent e )
  {
  }

  @Override
  public boolean onSingleTapUp( MotionEvent e )
  {
    return false;
  }
}

以下是我构建布局的方法。我将mBaseLinearLayout添加到外部滚动视图的第3页。然后我可以滚动到第3页。一旦第3页在屏幕上,我就希望能够滚动子滚动视图。当TextView控件在屏幕上保持静止时,它应滚动屏幕左侧。

// Base layout is only one page wide but it has keypad scroll layout that extends over 3 pages..
mBaseLinearLayout = new LinearLayout( mActivity );
mBaseLinearLayout.setLayoutParams( new LinearLayout.LayoutParams( ContextActivity.screenWidth, ContextActivity.screenHeight ) );
mBaseLinearLayout.setOrientation( LinearLayout.VERTICAL );
mBaseLinearLayout.setBackgroundColor(  Color.YELLOW );

mKeypadScrollView = new CustomHorizontalScrollView( mActivity, 3, ContextActivity.screenWidth );
mKeypadScrollView.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1 ) );
mKeypadScrollView.tag = 69;

// Add 3 pages of buttons to the page layout..
mPageLinearLayout = new LinearLayout( mActivity );
mPageLinearLayout.setLayoutParams( new LinearLayout.LayoutParams( ContextActivity.screenWidth * nNumPages, ContextActivity.screenHeight ) );

GridLayout page1 = CreateAlphaPage( 0 ); 
GridLayout page2 = CreateAlphaPage( 1 );
GridLayout page3 = CreateAlphaPage( 2 );

mPageLinearLayout.addView( page1 );
mPageLinearLayout.addView( page2 );
mPageLinearLayout.addView( page3 );

// Add scroll view to the top of the base layout and a text view underneath.
mKeypadScrollView.addView( mPageLinearLayout );

TextView tv = new TextView( mActivity );
tv.setX( 0 );
tv.setWidth( ContextActivity.screenWidth );
tv.setHeight( ContextActivity.screenHeight );
tv.setBackgroundColor( Color.MAGENTA );
tv.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1 ) );

mBaseLinearLayout.addView( mKeypadScrollView );
mBaseLinearLayout.addView( tv );

1 个答案:

答案 0 :(得分:0)

我自己解决了这个问题。解决方案是创建一个ScrollStopListener接口,以便在达到scrollview的极值时,我可以阻止外部scrollview可滚动。这使内部scrollview接收事件。显然这个解决方案对每个人都不起作用,但它对我来说很好,我可以继续处理我的应用程序。我相信随着时间的推移,有人会回复更好的解决方案。