2013-06-02 8 views
38

Mam problem z ScrollView, który ma w środku spersonalizowany GridView i inne tipe poglądów. Przy pierwszym uruchomieniu Activity, ScrollView zaczyna się od góry, ale jeśli odwiedzę tę czynność innym razem, ScrollView rozpoczyna się na początku GridView. Użyłem klasy ExpandableHeightGridView znalezionej w this link dla mojego GridView. Kod XML dla układu działalności jest to jedno:Android ScrollView nie zaczyna się od góry, ale na początku GridView

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/scrollViewLuogo" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#fff" > 

<RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#fff" > 

    <LinearLayout 
     android:id="@+id/linearLayout2" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" > 

     <ImageView 
      android:id="@+id/imageView1" 
      android:layout_width="150dp" 
      android:layout_height="100dp" 
      android:layout_marginLeft="14dp" 
      android:layout_marginRight="10dp" 
      android:layout_marginTop="10dp" 
      android:adjustViewBounds="true" 
      android:maxHeight="200dp" 
      android:maxWidth="200dp" 
      android:scaleType="fitXY" 
      android:src="@android:drawable/ic_menu_gallery" /> 

     <LinearLayout 
      android:id="@+id/linearLayout1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginTop="10dp" 
      android:orientation="vertical" > 

      <TextView 
       android:id="@+id/nomeTVActivityLuogo" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:textStyle="bold" 
       android:textSize="17sp" 
       android:textColor="#005788" /> 

      <TextView 
       android:id="@+id/indirizzoTVActivityLuogo" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" /> 
     </LinearLayout> 
    </LinearLayout> 

    <LinearLayout 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_below="@+id/linearLayout2" 
     android:layout_marginTop="10dp" 
     android:orientation="vertical" > 

     <ImageView 
      android:id="@+id/imageViewMappaLuogo" 
      android:layout_width="wrap_content" 
      android:layout_height="60dp" 
      android:layout_marginBottom="10dp" 
      android:layout_marginLeft="14dp" 
      android:layout_marginRight="14dp" 
      android:layout_marginTop="5dp" 
      android:scaleType="fitXY" 
      android:src="@drawable/sfondo_mappa" /> 

     <TextView 
      android:id="@+id/textView1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginLeft="14dp" 
      android:text="Immagini" 
      android:textColor="#97d6f9" /> 

     <View 
      android:layout_width="fill_parent" 
      android:layout_height="2dp" 
      android:layout_marginLeft="14dp" 
      android:layout_marginRight="14dp" 
      android:layout_marginTop="5dp" 
      android:background="#97d6f9" /> 

     <com.example.mappine.ExpandableHeightGridView 
      android:id="@+id/gridViewLuogo" 
      android:layout_width="wrap_content" 
      android:layout_height="match_parent" 
      android:layout_marginBottom="10dp" 
      android:layout_marginLeft="10dp" 
      android:layout_marginRight="10dp" 
      android:layout_marginTop="10dp" 
      android:numColumns="3" > 
     </com.example.mappine.ExpandableHeightGridView> 

    </LinearLayout> 

</RelativeLayout> 

Próbowałem przy użyciu kodu scrollView.fullScroll(ScrollView.FOCUS_UP); ale nie work.And nawet z scrollView.scrollTo(0, 0); nie miałem powodzenia. Jedynym kod, który pracował był:

scrollView.post(new Runnable() 
     { 
     public void run() { 
      scrollViewLuogo.fullScroll(ScrollView.FOCUS_UP); 
     } 
     }); 

ale to sprawia, że ​​szybki animację z góry GridView na górze ekranu, a ja się nie podoba.

Jakieś sugestie?

Odpowiedz

124

Rozwiązanie:

Ok przepraszam, jeśli jest to późna odpowiedź, ale natknąłem się w tej samej sprawie (tylko że używałem ListView zamiast) i trochę prób i błędów znalazłem rozwiązanie temu :

Zasadniczo problem polega na tym, że GridView/ListView dziecko automatycznie żąda rodzic ostrości (Scrollview) podczas „hack” i zmieniać jego zawartość z ExpandableHeightGridView, co się dzieje, gdy układ jest renderowany, a więc widać tę animację podczas próby przewinięcia do góry za pomocą scrollTo() (dzieje się PO utworzeniu układu i AFTER gridView jest zmieniany, więc wszelkie ogólne wywołania zwrotne są bezużyteczne, aby obsłużyć to programowo).

Więc, najprostszym rozwiązaniem znalazłem się po prostu wyłączyć właściwość aktywowana na ListView/GridView z:

listView.setFocusable(false); 

tamtędy kiedy po raz pierwszy wprowadzić aktywność, ostrość będzie domyślnie i nie polegać na ListView/GridView.

A wszystko działa dobrze =)

+1

To powinno być uznane za poprawną odpowiedź – FabioR

+1

Działa również dla webview. –

+1

Naprawna poprawka, dziękuję. Zastanawiam się, dlaczego to nie działa, jeśli ustawię go w xml. – Emanuel

2

Niestety ten przykład jest bardzo słaby. ListViews i GridViews nigdy nie powinny być umieszczane w ScrollViews.

Celem ScrollView jest nadanie nieskończonej wysokości jego widokowi podrzędnemu. Celem List/GridView jest zrobienie potencjalnie bardzo dużego zestawu danych i wygenerowanie wystarczającej liczby widoków przedmiotów, aby wypełnić przestrzeń udostępnioną mu w danym momencie dla zwiększenia wydajności. Oba są w stanie przewijać zawartość bez drugiego.

Umieszczenie listy/GridView w ScrollView mówi "siła nie do zatrzymania, spotkaj nieruchomy obiekt". Albo pokonałeś punkt List/GridView lub pokonałeś punkt ScrollView, łącząc je.

Lepsze sposoby dodawania innych treści w tym samym regionie przewijania obejmują używanie widoków nagłówka/stopki z ListView lub łączenie w inny sposób zawartości kart list razem w jedną kartę. Tworzenie elementów ListView, które zawierają kilka elementów w wierszu w celu utworzenia siatki dla części zawartości adaptera, jest proste.

+0

W tym ćwiczeniu użytkownik może dodać ile TextView (informacje, komentarze, itd.) i widoków obrazu (jego własne zdjęcia), które chce. Chcę, żeby cały widok był przewijany, a widok siatki jest idealny do zarządzania obrazami, więc lubię to rozwiązanie. – user2328149

0

znalazłem sposób nadania GridView stały rozmiar wewnątrz Scrollview i umożliwiają poruszanie go. To pozwala zobaczyć cały ScrollView bez konieczności przewijania wszystkich elementów GridView, i ma to więcej sensu dla mnie, używając ExpandableHeightGridView.

Aby to zrobić, trzeba by wdrożyć nową klasę rozciągający GridView i zastąpić onTouchEvent() zadzwonić requestDisallowInterceptTouchEvent (true). W ten sposób widok nadrzędny pozostawi zdarzenia przechwycenia dotykowego Grid.

GridViewScrollable.java:

package com.example; 
import android.content.Context; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.widget.GridView; 

public class GridViewScrollable extends GridView { 

    public GridViewAdjuntos(Context context) { 
     super(context); 
    } 

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

    public GridViewAdjuntos(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev){ 
     // Called when a child does not want this parent and its ancestors to intercept touch events. 
     requestDisallowInterceptTouchEvent(true); 
     return super.onTouchEvent(ev); 
    } 
} 

Dodaj go w układzie z charakterystyką i marże chcesz, wewnątrz Scrollview:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:isScrollContainer="true" > 

    <com.example.GridViewScrollable 
    android:id="@+id/myGVS" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:gravity="center" 
    android:numColumns="auto_fit" 
    android:stretchMode="columnWidth" /> 

</ScrollView> 

i po prostu go w swojej działalności:

GridViewScrollable myGridView = (GridViewScrollable) findViewById(R.id.myGVS); 

Mam nadzieję, że to pomoże =)

1

Jeśli chcesz przewinąć go do górnej/dolnej programowo, można to (to od here) zrobić:

((ScrollView) findViewById(R.id.scroller)).post(new Runnable() { 
    public void run() { 
     ((ScrollView) findViewById(R.id.scroller)).fullScroll(View.FOCUS_DOWN); 
    } 
}); 
16

Najprostszym sposobem jest dodanie na rodzica Scrollview następujące xml atrybuty:

android:descendantFocusability="beforeDescendants" 
android:focusableInTouchMode="true" 

Oznacza to, że ScrollView jako całość będzie skupiał się na fokowaniu, a nie na kontenerze wewnętrznym po uruchomieniu działania. Jest to również użyteczne, na przykład, gdy masz tekst edycji wewnątrz swojego układu i nie chcesz, aby od razu się skupił i wyskakuje klawiatura przy wchodzeniu na ekran (to ta sama zasada).

Więc twój Scrollview na górze układu będzie wyglądać następująco:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/scrollViewLuogo" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:descendantFocusability="beforeDescendants" 
    android:focusableInTouchMode="true" 
    android:background="#fff" > 
+2

nie działa dla mnie, mam widok z recyklingu wewnątrz przewijania –

+1

RecyclerView to specjalny przypadek, taki sam jak ListView. Ogólnie rzecz biorąc, posiadanie dwóch przewijanych pojemników, jeden wewnątrz siebie (ListView lub RecyclerView wewnątrz ScrollView) jest gniazdem problemów i problemów, które nie prowadzą do łatwego rozwiązania. Jeśli masz EditText, wewnątrz RecyclerView, wewnątrz ScrollView, rzeczy stają się bardzo nieprzyjemne, a proste rozwiązanie (Descendant focusability) nie działa łatwo, częściowo z powodu implementacji przewijanych kontenerów. – Disruption

+0

Należy pamiętać, że ** ScrollView ** wymaga tego atrybutu tylko wtedy, gdy jest bezpośrednim rodzicem innego przewijanego widżetu. W przeciwnym razie po prostu uzyskaj rodzica i umieść te same atrybuty. Miałem ** LinearLayout ** jako bezpośredni rodzic ** ExpandableHeightGridView ** i to rozwiązanie działa zgodnie z oczekiwaniami. – mimoralea

0

Jako obserwacji będę dzielić mój ból, jak również. W moim app mam RecyclerView Wewnątrz NestedScrollView Wewnątrz CoordinatorLayout:

<CoordinatorLayout> 
    <NestedScrollView id="@+id/content"> 

    ....... 

    <TextView android:id="@+id/header"/> 

    <RecyclerView android:id="@+id/recyclerView"/>  

    </NestedScrollView> 
</CoordinatorLayout> 

Oczywiście po otwarciu aktywność, strony przewijane do włączenia recyclerView w środku.Żadna z powyższych odpowiedzi pracował, więc wymyśliłem następujące rozwiązanie:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    .... 
    content.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { 
    @Override 
    public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { 
     Rect scrollBounds = new Rect(); 
     v.getHitRect(scrollBounds); 
     if(header.getLocalVisibleRect(scrollBounds)){ 
     if(View.VISIBLE != recyclerView.getVisibility()){ 
      recyclerView.setVisibility(View.VISIBLE); 
      fillRecyclerViewSomehow(); 
     } 
     } 
    } 
    } 
} 

@Override 
protected void onResume() { 
    ... 
    recyclerView.setVisibility(View.GONE); // this effectively suppresses the focusability 
} 

HTH

3

Scrollview

android:fitsSystemWindows="false" 
1

Wystarczy dodać te dwie linie w układzie macierzystym

android : focusable = "true" android: focusableInTouchMode = "true"

Spróbuj tego, nadzieję, że będzie pracować dla Ciebie

2

Wystarczy dodać poniższy wiersz kodu w Dziecka Scrollview

android:focusableInTouchMode="true" 
Powiązane problemy