2011-08-01 85 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; 
      } 
     }); 
相關問題