Android ScrollView не запускается сверху, но в начале GridView

У меня проблема с ScrollView, внутри которой есть персонализированный GridView и другой тип представлений. В первый раз, когда я запускаю Activity, ScrollView начинается с вершины, но если я посещаю Activity еще раз, ScrollView запускает в начале GridView. Я использовал класс ExpandableHeightGridView, найденный в этой ссылке для моего GridView. Код xml для макета Activity:

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

Я пробовал использовать код scrollView.fullScroll(ScrollView.FOCUS_UP);, но он не работал. И даже с scrollView.scrollTo(0, 0); у меня не было успеха. Единственный выполненный код:

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

но он делает быструю анимацию с вершины GridView в верхней части экрана, и мне это не нравится.

Любое предложение

Ответ 1

Решение:

Хорошо, если это поздний ответ, но я наткнулся на ту же проблему (только то, что я использовал ListView вместо), и с небольшим количеством проб и ошибок я нашел решение для этого:

В основном проблема заключается в том, что ребенок GridView/ListView автоматически запрашивает родительский фокус (ScrollView), когда вы "взламываете" и изменяете его размер с помощью ExpandableHeightGridView, что происходит после визуализации макета, и, следовательно, вы видите эту анимацию при попытке чтобы прокрутить его с помощью scrollTo() (происходит создание AFTER, а AFTER gridView изменяется, поэтому любой общий обратный вызов бесполезен для обработки этого программно).

Итак, самым простым решением, которое я нашел, было просто отключить свойство focusable в ListView/GridView с помощью:

listView.setFocusable(false);

Таким образом, когда вы впервые вводите действие, фокус будет по умолчанию и не будет полагаться на Listview/GridView.

И все работает отлично =)

Ответ 2

Самый простой способ - добавить родительский ScrollView следующие атрибуты xml:

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

Это означает, что ScrollView в целом будет получать фокус вместо любого внутреннего контейнера при запуске операции. Это также полезно, например, когда у вас есть текст редактирования внутри вашего макета, и вы не хотите, чтобы он сразу получал фокус и всплывал клавиатура при входе на экран (это тот же принцип).

Итак, ваш ScrollView поверх макета будет выглядеть так:

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

Ответ 3

Просто добавьте две строки в родительский макет

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

Попробуйте это, надеюсь, что это сработает для вас.

Ответ 4

Просто добавьте эту строку кода в Child of ScrollView

android:focusableInTouchMode="true"

Ответ 5

Если вы хотите прокрутить его до верха/низа программно, вы можете сделать это (отсюда):

Для фокуса вниз:

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

Для фокуса наверх

((ScrollView) findViewById(R.id.scrollView)).post(new Runnable() { 
    public void run() { 
        ((ScrollView) findViewById(R.id.scrollView)).fullScroll(View.FOCUS_UP); 
    } 
});

Ответ 6

ScrollView

android:fitsSystemWindows="false"

Ответ 7

К сожалению, приведенный вами пример крайне низок. ListViews и GridViews никогда не должны помещаться в ScrollViews.

Цель ScrollView - предоставить бесконечную высоту его дочернему виду. Цель List/GridView состоит в том, чтобы использовать потенциально очень большой набор данных и создавать только достаточное количество элементов, чтобы заполнить пространство, доступное для него за раз для повышения эффективности. Оба могут прокручивать их содержимое без другого.

Вставка списка /GridView в ScrollView говорит: "Невозможная сила, встречайте неподвижный объект". Либо вы победили точку List/GridView, либо вы победили точку ScrollView, объединив их.

Более эффективные способы включения другого контента в пределах той же области прокрутки включают использование представлений заголовка/нижнего колонтитула с помощью ListView или объединение содержимого списковых адаптеров вместе в один адаптер. Создание элементов ListView, содержащих несколько элементов в строке для формирования сетки для части содержимого адаптера, является простым.

Ответ 8

Я нашел способ предоставить GridView фиксированный размер внутри ScrollView и разрешить прокрутку. Это позволяет вам видеть весь ScrollView без необходимости прокрутки всех элементов GridView, и для меня имеет смысл больше использовать ExpandableHeightGridView.

Для этого вам нужно будет реализовать новый класс, расширяющий GridView и переопределяющий onTouchEvent() для вызова requestDisallowInterceptTouchEvent (true). Таким образом, родительский вид оставит события касания перехвата сетки.

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);
    }
}

Добавьте его в свой макет с характеристиками и полями, которые вы хотите, внутри 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>

И просто получите его в своей деятельности:

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

Я надеюсь, что это поможет =)

Ответ 9

В качестве продолжения я также поделюсь своей болью. В моем приложении у меня есть RecyclerView внутри NestedScrollView внутри CoordinatorLayout:

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

     .......

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

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

  </NestedScrollView>
</CoordinatorLayout>

Конечно, при открытии активности страница прокручивается, чтобы включить recyclerView в середине. Ни один из ответов выше не работал, поэтому я придумал следующее решение:

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

НТН

Ответ 10

Простой способ добиться этого - установить идентификатор для вашего ScrollView в XML... скажем,

scrollView_main

После этого вам просто нужно перейти к вашему Java файлу и объявить его как обычную переменную над процедурой onCreate, чтобы он был глобальным, как этот

ScrollView scrollView_main;

хорошо, теперь пришло время перейти к процедуре onCreate и объявить это, чтобы получить соединение с вашим идентификатором из файла XML

scrollView_main = (ScrollView)findViewById(R.id.scrollView_main);

и, наконец, код, который поможет вам прокрутить ScrollView сверху, это ваш ответ

scrollView_main.smoothScrollTo(0,0); //set it on top

Ответ 11

Если ничего не работает, просто поместите это как первый элемент вашего дочернего элемента scrollView:

<EditText
   android:layout_width="0dp"
   android:layout_height="0dp"/>

пример:

  <ScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            <EditText
                    android:layout_width="0dp"
                    android:layout_height="0dp"/>
            <!-- your other views  -->
        </LinearLayout>
</ScrollView>