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.