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>