2011-08-01 88 views
1

我可以看到一些关于“ListView里面的ScrollView”问题的问题。我知道,我们不应该做这样的嵌套,只是因为这两个组件都有自己的滚动功能,而Google也这样说(我读过它是无用的东西)。但在我目前的项目中,我需要这样的行为:如果listview可以滚动 - 它是滚动,如果不是(列表视图的顶部或底部边界) - 滚动视图滚动。 所以,我写了这样的代码:ListView里面的ScrollView滚动改进

public static void smartScroll(final ScrollView scroll, final ListView list){ 
     scroll.requestDisallowInterceptTouchEvent(true); 
     list.setOnTouchListener(new OnTouchListener() { 
      private boolean isListTop = false, isListBottom = false; 
      private float delta = 0, oldY = 0; 
      @Override 
      public boolean onTouch(View v, MotionEvent event) {    
       switch (event.getAction()) { 
       case MotionEvent.ACTION_DOWN: 
        oldY = event.getY(); 
        break; 
       case MotionEvent.ACTION_UP: 
        delta = 0; 
        break; 
       case MotionEvent.ACTION_MOVE: 
        delta = event.getY() - oldY; 
        oldY = event.getY(); 

        isListTop = false; 
        isListBottom = false; 

        View first = list.getChildAt(0); 
        View last = list.getChildAt(list.getChildCount()-1);     
        if(first != null && list.getFirstVisiblePosition() == 0 && first.getTop() == 0 && delta > 0.0f){ 
         isListTop = true; 
        } 
        if(last != null && list.getLastVisiblePosition() == list.getCount()-1 && last.getBottom() <= list.getHeight() && delta < 0.0f){ 
         isListBottom = true; 
        } 

        if((isListTop && delta > 0.0f) || (isListBottom && delta < 0.0f)){ 
         scroll.post(new Runnable() { 
          public void run() { 
           scroll.smoothScrollBy(0, -(int)delta); 
          } 
         }); 
        } 

        break; 
       default: break; 
       }     
       scroll.requestDisallowInterceptTouchEvent(true); 
       return false; 
      } 
     }); 
    } 

和它的作品,至少在目标API 8.但也有一些滚动毛刺(不自然的跳跃)。我认为,scroll.smoothScrollBy(0, - (int)delta)的原因;有没有人想过,如何提高滚动视图滚动:)?它经常被称为(在移动中)和在后,也许这是原因?

+0

嗨,你目前在这个问题上的想法是什么?你有没有解决不自然的跳转问题?谢谢... – OferR

+0

嗨!那么,设计已经改变了,不再需要这种行为了。我的想法 - 我们不能在ScrollView中使用ListView,因为它们的实现。谷歌的人都是对的:)所以,要实现这样的行为,最好是基于ViewGroup实现自己的UI组件。 – Olsavage

+0

感谢您的回答Olsavage。因此,我将研究其他呈现信息的方式。 – OferR

回答

3

我都面临着同样的问题。我改进了这个代码,现在它工作正常,我认为。

public static void smartScroll(final ScrollView scroll, final ListView list){ 
    list.setOnTouchListener(new View.OnTouchListener() { 
     private boolean isListTop = false, isListBottom = false; 
     private float delta = 0, oldY = 0; 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      switch (event.getAction()) { 
       case MotionEvent.ACTION_DOWN: 
        scroll.requestDisallowInterceptTouchEvent(true); 
        list.requestDisallowInterceptTouchEvent(false); 
        oldY = event.getY(); 
        break; 
       case MotionEvent.ACTION_UP: 
        delta = 0; 
        break; 
       case MotionEvent.ACTION_MOVE: 
        delta = event.getY() - oldY; 
        oldY = event.getY(); 

        isListTop = false; 
        isListBottom = false; 

        View first = list.getChildAt(0); 
        View last = list.getChildAt(list.getChildCount()-1); 
        if(first != null && list.getFirstVisiblePosition() == 0 && first.getTop() == 0 && delta > 0.0f){ 
         isListTop = true; 
        } 
        if(last != null && list.getLastVisiblePosition() == list.getCount()-1 && last.getBottom() <= list.getHeight() && delta < 0.0f){ 
         isListBottom = true; 
        } 

        if((isListTop && delta > 0.0f) || (isListBottom && delta < 0.0f)){ 
         scroll.requestDisallowInterceptTouchEvent(false); 
         list.requestDisallowInterceptTouchEvent(true); 
        } 
        break; 
       default: break; 
      } 
      return false; 
     } 
    }); 
} 

当我们接触的ListView - 我们使它的滚动和禁用父滚动:

    scroll.requestDisallowInterceptTouchEvent(true); 
        list.requestDisallowInterceptTouchEvent(false); 

而且如果我们达到列表的边界 - 我们禁止其滚动和启用父滚动:

    scroll.requestDisallowInterceptTouchEvent(false); 
        list.requestDisallowInterceptTouchEvent(true); 

它为我滚动很光滑。希望这可以帮助。

+0

我测试了你的修改,它的工作原理就像我需要的一样。哇,我问这个问题差不多三年了。谢谢=) – Olsavage

0

我的sugesstion会把listview标签放在滚动视图的旁边。并且在滚动视图内添加listview之外的区域。然后将所有内容放在线性布局中。所以scollview和listview将是分开的。

+0

感谢您的建议,但我需要ListView滚动的内容。我的意思是,ListView滚动必须是最高优先级,但如果没有ListView滚动发生,父ScrollView应滚动ListView内... – Olsavage

+0

好吧,我想我应该接受你的答案。这意味着,只是不要把ListView放在ScrollView中=)也许它会帮助别人不浪费时间在这个没用的东西上...... – Olsavage

1

如果父级是ScrollView,则将其更改为LinearLayout。它会工作。例如,在这里我写了LinearLayout而不是ScrollView。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/scroll" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:fillViewport="true"> 

     <ListView android:id="@+id/fontlistView" 
      android:scrollbars="vertical" 
      android:layout_height="wrap_content" 
      android:layout_width="match_parent" 
      android:layout_gravity="center_horizontal" 
      android:scrollbarAlwaysDrawVerticalTrack="true"> 
     </ListView> 
</LinearLayout> 
0

我认为ü需要这个

listview = (ListView) findViewById(R.id.search_list); 
listview.setOnTouchListener(new View.OnTouchListener() { 
      public boolean onTouch(View v, MotionEvent event) { 
       if (event.getAction() == MotionEvent.ACTION_DOWN) { 
        v.getParent().requestDisallowInterceptTouchEvent(true); 
       } else if (event.getAction() == MotionEvent.ACTION_UP) { 
        v.getParent().requestDisallowInterceptTouchEvent(false); 

       } 
       return false; 
      } 
     }); 
相关问题