Como evitar que um scrollview role para um webview depois que os dados forem carregados?

107

Portanto, tenho um problema fascinante. Apesar de não estar rolando manual ou programaticamente minha visualização, meu WebView está sendo rolado automaticamente após o carregamento dos dados dentro dele.

Eu tenho um fragmento em um viewpager. Quando carrego o pager pela primeira vez, ele funciona conforme o esperado e tudo é mostrado. Mas quando eu "viro a página", os dados são carregados e o WebView aparece no topo da página, ocultando as visualizações acima dele, o que é indesejável.

Alguém sabe como evitar que isso aconteça?

Meu layout é assim:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/background" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/article_title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="2dp"
            android:text="Some Title"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="@color/article_title"
            android:textStyle="bold" />

        <LinearLayout
            android:id="@+id/LL_Seperator"
            android:layout_width="fill_parent"
            android:layout_height="1dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"
            android:background="@color/text"
            android:orientation="horizontal" >
        </LinearLayout>

        <WebView
            android:id="@+id/article_content"
            android:layout_width="match_parent"
            android:layout_marginRight="10dp"
            android:layout_marginLeft="10dp"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/article_link"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="5dp"
            android:layout_marginRight="10dp"
            android:layout_marginLeft="10dp"
            android:text="View Full Article"
            android:textColor="@color/article_title"
            android:textStyle="bold" />
    </LinearLayout>

</ScrollView>

Também não estou dando foco a nada. Por padrão, parece rolar automaticamente para o WebView após ser carregado. Como faço para evitar isso?

Navarr
fonte
por que exatamente você precisa do ScrollView, já que um WebView é rolável?
znat
Para manter alguns aspectos fora do webview em vez de renderizá-los como HTML. Para velocidade e qualidade.
Navarr,
1
mjp66 tem a melhor resposta - talvez você deva aceitar a resposta dele
AndrewS

Respostas:

43

Você pode simplesmente adicionar isso ao seu LinearLayout: android: focusableInTouchMode = "true". Funciona para mim.

 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:focusableInTouchMode="true"
    android:orientation="vertical" >
Peter Nguyen
fonte
4
Funciona sem efeitos colaterais!
Vaibhav Jani
267

Eu tive o mesmo problema, depois de horas tentando várias idéias, o que finalmente funcionou para mim foi simplesmente adicionar o descendantFocusabilityatributo ao ScrollView contendo LinearLayout, com o valor blocksDescendants. No seu caso:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:descendantFocusability="blocksDescendants" >

O problema não voltou a ocorrer desde então.

mjp66
fonte
3
Isso tem algum impacto negativo sobre a acessibilidade desses controles?
Cory Trese
34
Observe que, se houver visualizações filhas como EditText, esse método fará com que elas se tornem não editáveis.
djhworld
2
Esta pergunta / resposta não surge quando você pesquisa as palavras ScrollView Webview autoscroll, e deveria. Talvez este comentário ajude! Tive o mesmo problema ao usar um WebViewFragment e não encontrei essa pergunta, mesmo depois de muita pesquisa, até postar minha própria pergunta (agora excluída).
Colin M.
1
Trabalhando em um projeto Xamarin.Android, tive problemas de rolagem automática em uma visualização de rolagem com múltiplas visualizações de grade, preenchidas de forma assíncrona com imagens baixadas. Esta solução funcionou tão perfeitamente que tive dificuldade em acreditar à primeira vista e tive que testá-la novamente.
YumeYume
1
O mesmo problema ocorre com os anúncios em a RecyclerViewtambém. Sua solução também funciona nesse caso :)
Minas Mina
26

Você deve criar uma nova classe extend ScrollView e então Override requestChildFocus:

public class MyScrollView extends ScrollView {

    @Override 
    public void requestChildFocus(View child, View focused) { 
        if (focused instanceof WebView ) 
           return;
        super.requestChildFocus(child, focused);
    }
}

Em seguida, em seu layout xml, usando:

<MyScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/background" >

Isso funciona para mim. O ScrollView não irá mais rolar automaticamente para o WebView.

user1417127
fonte
5
Também precisava de construtores: public ExtendedScrollView(Context context) { super(context); } public ExtendedScrollView( Context context, AttributeSet attributeSet) { super(context, attributeSet); } public ExtendedScrollView( Context context, AttributeSet attributeSet, int defStyle) { super(context, attributeSet, defStyle); }
Erik B
5

Adicionar essas linhas no layout principal resolve o problema

android:descendantFocusability="blocksDescendants"
arun-r
fonte
4

Como isso:

<com.ya.test.view.MyScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:descendantFocusability="beforeDescendants"
        android:focusable="true"
        android:focusableInTouchMode="true" >
YaC King
fonte
4

Provavelmente existem pessoas que têm o mesmo problema que eu estava tendo, então vou ajudar.

Eu estava tentando colocar android: descendantFocusability = "beforeDescendants" em meu ScrollView principal da seguinte maneira:

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="beforeDescendants">
    /*my linearlayout or whatever to hold the views */

e não estava funcionando, então tive que fazer um RelativeLayout o pai do ScrollView e colocar o android: descendantFocusability = "beforeDescendants" no pai também.

Então, resolvi fazendo o seguinte:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants">

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">
/*my linearlayout or whatever to hold the views */
James
fonte
-2

Tive de usar o nome totalmente qualificado para MyScrollView, caso contrário, obtive uma exceção inflada.

<com.mypackagename.MyScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/background" >
Cathal Coffey
fonte