Dlaczego moja aktywność w systemie Android jest zawsze przewijana do dołu?

91

Za każdym razem, gdy zaczynam tę aktywność, zawsze zaczyna się od dna - przewijana do samego końca. Nie robię nic dziwnego w działaniu OnCreate (lub gdziekolwiek indziej), że spodziewałbym się zmienić pozycję przewijania. Próbowałem ustawić fokus na najwyższą możliwą do ogniskowania kontrolkę i metodę scrollto, ale żadna z nich nie działa. Poza tym żadna z moich innych czynności nie ma tego problemu. Oto układ:

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scroll"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/edit_refresh_update_header"
            android:textSize="18sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="\n"
            android:textSize="4sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Variable:"
            android:textSize="18sp"/>

        <Spinner
            android:id="@+id/edit_refresh_variables_spinner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="\n"
            android:textSize="4sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Network:"
            android:textSize="18sp"/>

        <RadioGroup
            android:id="@+id/widget1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical">

            <RadioButton
                android:text="Web"
                android:id="@+id/edit_refresh_update_rb_web"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="NetRadioButtonSelected"
                android:checked="true"/>

            <RadioButton
                android:text="Socket Server"
                android:id="@+id/edit_refresh_update_rb_socket_server"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="NetRadioButtonSelected"/>
        </RadioGroup>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="\n"
            android:textSize="4sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Socket server request type:"
            android:textSize="18sp"/>

        <Spinner
            android:id="@+id/edit_refresh_socket_server_req_types_spinner"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="\n"
            android:textSize="4sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Socket server body:"
            android:textSize="18sp"/>

        <EditText
            android:layout_width="match_parent"
            android:id="@+id/edit_refresh_update_ss_body"
            android:layout_height="wrap_content"
            android:enabled="false"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="\n"
            android:textSize="4sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Url:"
            android:textSize="18sp"/>

        <EditText
            android:layout_width="match_parent"
            android:id="@+id/edit_refresh_update_url"
            android:layout_height="wrap_content"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="\n"
            android:textSize="4sp"/>

        <Button
            android:text="Save refresh update"
            android:id="@+id/edit_refresh_save_btn"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:layout_marginLeft="20dip"
            android:layout_marginRight="20dip"
            android:layout_marginBottom="20dp"
            android:layout_alignParentBottom="true"
            android:onClick="SaveRefreshUpdate">
        </Button>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="\n"
            android:textSize="4sp"/>
    </LinearLayout>
</ScrollView>
MrGibbage
źródło
Jak dokładnie próbowałeś zmienić skupienie?
devmiles.com
1
używając metody fulscroll opisanej poniżej i metody scrollto opisanej również poniżej. Niekoniecznie mam coś przeciwko naprawieniu tego w ten sposób, ale musi być powód, dla którego zaczyna się w ten sposób i wolałbym to naprawić, poprawiając to.
MrGibbage

Odpowiedzi:

307

Kiedy Android rozpoczyna działanie, należy się skupić na pewnej kontroli. Gdy nie ma wyznaczonej kontroli, na której można skupić się, system wybiera pierwszą odpowiednią kontrolkę, która chce się skupić. Jeśli ustawisz następującą właściwość w LinearLayout - android:focusableInTouchMode="true"Twój LinearLayoutskupi się na starcie i swoją aktywność nie będzie przewijać się EditTextna dnie.

devmiles.com
źródło
Nie działa w moim GridLayout. Mam widok GridView w środku układu i za każdym razem jest on fokusem.
Iqbal
2
Podrapałem się po głowie przez cały dzień i nie mogłem ustalić, dlaczego dzieje się to tylko w jednym konkretnym działaniu i nadal nie rozumiem, ponieważ nie włączyłem skupienia się na żadnym widoku. Ale dzięki tobie udało mi się rozwiązać ten problem. Byłoby wspaniale, gdyby ktoś mógł rzucić trochę światła na możliwy powód, ponieważ nie robię nic nowego w nowym działaniu.
Shubhral
2
Ważna uwaga: należy to dodać jako właściwość do LinearLayoutwnętrza ScrollView, a nie do samego widoku przewijania.
Boris Strandjev
@BorisStrandjev bardzo ważna uwaga. Należy dodać do odpowiedzi. Przy okazji, dzięki za to: P
Coreggon
Jest to dosłownie wymienione w odpowiedzi.
devmiles.com
35

Zamiast zanieczyszczać elementy w swoim układzie, możesz dodać to do swojej aktywności / klasy:

    ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
    scrollView.setFocusableInTouchMode(true); 
    scrollView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);

W ten sposób nie jest to element w Twoim scrollView, który ma fokus, jest to Twój scrollView jako kontener, który jest pierwszym fokusem, przenosząc się do widoku podrzędnego po tym.

Graeme
źródło
Częściowo działa dla mnie, gdy próbuję ustawić wysokość ListView na podstawie dzieci w ScrollView
Konstantin Konopko
To pomogło! (podczas gdy te same atrybuty w xml nie działały ..)
Matan Dahan,
Działa jak marzenie! Thx
Bogy
U mnie zadziałało, ale dodałem tę linię: scrollView.fullScroll (ScrollView.FOCUS_UP) Obie osobno nie działały.
Juan Giorello
3

Możesz wypróbować ten kod:

scroller.post(new Runnable() { 
    public void run() { 
        scroller.fullScroll(ScrollView.FOCUS_DOWN); 
    } 
}); 

[N: B] [odsyłacz] 1

Społeczność
źródło
1
to dobra opcja, ale symuluje szarpnięcie po otwarciu, więc myślę, że nie jest to dobre wrażenia użytkownika
iBabur
2

Wraz z tym, co powiedział devmiles.com.

Jeśli ustawisz następującą właściwość w swoim LinearLayout - android: focusableInTouchMode = "true", twój LinearLayout będzie skupiony na początku, a twoja aktywność nie zostanie przewinięta do EditText na dole.

Jeśli wywołasz requestLayout () w widoku u dołu układu liniowego, może to odebrać fokus z najwyższego widoku. Więc po prostu wywołaj requestFocus () w górnym widoku w układzie liniowym po wywołaniu requestLayout () w dolnym widoku.

luca992
źródło
1

Czy próbowałeś użyć metody fullScroll? Http: //developer.android.com/reference/android/widget/ScrollView.html#fullScroll (int)

yourScrollView.fullScroll(ScrollView.FOCUS_UP);
Mikrofon
źródło
1

W przypadku programowania na platformie Xamarin Android, jeśli chcesz wykonać rozwiązanie @Graeme, to:

// Set Focus to ScrollView
ScrollView scrollView = (ScrollView)FindViewById(Resource.Id.scrollView);
scrollView.FocusableInTouchMode = true;
scrollView.DescendantFocusability = Android.Views.DescendantFocusability.BeforeDescendants;
Asher Garland
źródło
1

Po prostu spraw, aby nie można było skupić się na onCreate ()

editText.setFocusable(false);

I użyć

editText.setOnClickListener(new ....){
 ......
  editText.setFocusable(true);
  editText.setFocusableInTouchMode(true);
  editText.requestFocus();

  showSoftKeyboard(); //Use InputMethodManager to open soft Keyboard

 ......
 };

i następnym razem nie przewinie się do Edittext, utworzony zostanie fragment lub działanie.

głośnik kodowy
źródło
1

Dodaj te dwie linie do swojego ScrollView

 android:focusableInTouchMode="true"
 android:descendantFocusability="blocksDescendants"
Hemendra Gangwar
źródło
0

Nie wiem dlaczego, ale możesz poeksperymentować

ScrollView sv = (ScrollView) findViewById(R.id.scroll);
sv.scrollTo(0,0);

w swoim, onCreateaby ręcznie przewinąć go tam, gdzie chcesz.

zapl
źródło
0

scrollView.requestFocus(View.FOCUS_UP)rozwiązałem mój problem, gdy chciałem, aby widok z góry był widoczny. Określenie parametru kierunku w metodzie requestFocus(int direction)jest dobrym sposobem na kontrolowanie ScrollViewpozycji. Więcej szczegółów tutaj .

Amit
źródło
0

W moim przypadku miałem VideoViewinside a ConstraintLayoutinside a ScrollView. VideoViewZawsze kradzież ostrość, a tam są problemy z nim . Rozwiązaniem jest użycie pliku TextureView. Mam nadzieję, że to komuś pomoże, kosztowało mnie to przynajmniej godzinę :)

Daniel Wilson
źródło