Por que minha atividade no Android sempre começa rolando para baixo?


91

Sempre que eu começo esta atividade, ela sempre começa do fundo do poço - rolando até o fim. Eu não estou fazendo nada estranho na atividade OnCreate (ou em qualquer lugar) que eu esperaria mudar a posição do scroll. Eu tentei definir o foco para o controle focalizável superior e o método scrollto, mas nenhum deles está funcionando. Além disso, nenhuma das minhas outras atividades tem esse problema. Aqui está o layout:

<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>

Como exatamente você tentou mudar o foco?
— devmiles.com

1
usando o método fulscroll conforme descrito abaixo e o método scrollto conforme descrito abaixo. Não me importo necessariamente em consertar dessa forma, mas deve haver um motivo pelo qual está começando assim e prefiro consertar corrigindo isso.
— MrGibbage

Respostas:


306

Quando o Android inicia uma atividade, algum controle precisa assumir o foco. Quando não há um controle designado para obter o foco, o sistema escolhe o primeiro controle elegível que deseja o foco. Se você definir a seguinte propriedade em seu LinearLayout - android:focusableInTouchMode="true"seu LinearLayoutfoco estará no início e sua atividade não rolará para EditTexta parte inferior.


Não está funcionando no meu GridLayout. Eu tenho um GridView no meio do layout, e ele sempre recebe o foco.
— Iqbal de

2
Coquei a cabeça por um dia inteiro e não consegui descobrir porque isso estava acontecendo em apenas uma atividade específica e ainda não entendo, pois não habilitei o foco em nenhuma visualização. Mas graças a você, consegui consertar esse problema. Seria ótimo se alguém pudesse lançar alguma luz sobre o que poderia ser o possível motivo, já que não há nada de novo que estou fazendo na nova atividade.
— Shubhral

2
Uma observação importante: isso deve ser adicionado como propriedade no LinearLayoutinterior do ScrollView, não na própria visualização de rolagem.
— Boris Strandjev

@BorisStrandjev nota muito importante. Deve ser adicionado à resposta. A propósito, obrigado por isso: P
— Coreggon

É literalmente mencionado na resposta.
— devmiles.com

35

Em vez de poluir itens em seu layout, você pode adicionar isso à sua Atividade / Aula:

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

Desta forma, não é um elemento dentro do seu scrollView obtendo o foco, é o seu scrollView como um contêiner que obtém o primeiro foco, movendo-se para a visão filha depois disso.


Funciona parcialmente para mim quando tento definir a altura de ListView com base em filhos dentro de ScrollView
— Konstantin Konopko

Isso ajudou! (embora os mesmos atributos em xml não funcionassem ...)
— Matan Dahan

Funciona como um encanto! Thx
— Bogy

Funcionou para mim, mas adicionei esta linha: scrollView.fullScroll (ScrollView.FOCUS_UP) Ambos não funcionaram separadamente.
— Juan Giorello

3

Você pode tentar este código:

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

[N: B] [link de referência] 1


1
é uma boa opção, mas simula um empurrão após a abertura, então não é uma boa experiência do usuário, eu acho
— iBabur

2

Junto com o que devmiles.com disse.

Se você definir a seguinte propriedade em seu LinearLayout - android: focusableInTouchMode = "true", seu LinearLayout será focado no início e sua atividade não rolará para EditText na parte inferior.

Se você chamar requestLayout () em uma visualização na parte inferior de seu layout linear, isso pode roubar o foco de sua visualização superior. Portanto, basta chamar requestFocus () na visualização superior no layout linear depois de chamar requestLayout () em uma visualização inferior.


1

Você já tentou usar o método fullScroll? Http: //developer.android.com/reference/android/widget/ScrollView.html#fullScroll (int)

yourScrollView.fullScroll(ScrollView.FOCUS_UP);

1

Para o desenvolvimento do Xamarin Android, se você deseja fazer a solução @Graeme, então:

// Set Focus to ScrollView
ScrollView scrollView = (ScrollView)FindViewById(Resource.Id.scrollView);
scrollView.FocusableInTouchMode = true;
scrollView.DescendantFocusability = Android.Views.DescendantFocusability.BeforeDescendants;

1

Basta torná-lo não focalizável em onCreate ()

editText.setFocusable(false);

E use

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

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

 ......
 };

e não rolará para baixo para Editar texto na próxima vez, um fragmento ou atividade for criada.


1

Adicione essas duas linhas em seu ScrollView

 android:focusableInTouchMode="true"
 android:descendantFocusability="blocksDescendants"

0

Não sei por que, mas você pode experimentar

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

no seu onCreatepara rolar manualmente para onde você quiser.


0

scrollView.requestFocus(View.FOCUS_UP)resolveu meu problema quando queria que a vista de cima ficasse visível. Especificar o parâmetro de direção para o método requestFocus(int direction)é uma boa maneira de controlar a ScrollViewposição. Mais detalhes aqui .


0

No meu caso eu tinha um VideoViewdentro de uma ConstraintLayoutdentro de uma ScrollView. Ele VideoViewsempre roubou o foco e há problemas com ele . A solução é usar a TextureView. Espero que isso ajude alguém, me custou pelo menos uma hora :)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.