Android ScrollView不是从顶部开始,而是在GridView的开始

我有一个ScrollView的问题,里面有一个个性化的GridView和其他视图。第一次启动Activity时,ScrollView从顶部开始,但是如果我在其他时间访问Activity,ScrollView会在开始时开始GridView.I使用了在这个链接中find的类ExpandableHeightGridView用于我的GridView。 活动布局的xml代码是这样的:

<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顶部到屏幕顶部制作了一个快速的animation,我不喜欢它。

任何build议?

解:

对不起,如果这是一个迟到的答复,但我偶然发现相同的问题(只是我使用的是ListView),并与一些试验和错误, 我find了解决scheme

基本上问题在于当你使用ExpandableHeightGridView (在渲染布局之后)“修改”其内容并调整其内容时,GridView / ListView子自动请求父焦点(ScrollView),因此当您尝试滚动时会看到该animation使用scrollTo()(发生后,布局创build和AFTER gridView被resize,所以任何通用的callback没有用处理这个编程)。

那么,我发现最简单的解决scheme是简单地禁用ListView / GridView上的focusable属性:

 listView.setFocusable(false); 

这样,当你第一次进入活动,焦点将默认,而不是依靠Listview / GridView。

和所有工作正常=)

最简单的方法是在父ScrollView上添加以下xml属性:

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

这意味着当您启动活动时,ScrollView作为一个整体将成为焦点而不是任何内部容器。 这也是有用的,例如,当你的布局中有一个编辑文本,你不希望它立即得到焦点,并在进入屏幕时popup键盘(这是相同的原理)。

所以,你的布局顶部的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" > 

滚动型

 android:fitsSystemWindows="false" 

可悲的是,你所遵循的例子是极其糟糕的。 不应该将ListView和GridView放置在ScrollView中。

ScrollView的目的是为其子视图提供无限的高度。 List / GridView的目的是获取一个潜在的非常大的数据集,只生成足够的项目视图来填充一次提供的空间以提高效率。 两者都能够滚动他们的内容没有其他。

把一个List / GridView放在ScrollView里,是说“不可阻挡的力量,碰到不动的东西”。 要么你已经击败了List / GridView的点,或者你已经通过组合它们击败了ScrollView的观点。

在相同的滚动区域内包含其他内容的更好方法包括使用ListView的页眉/页脚视图,或者将列表适配器的内容连接在一起成为一个适配器。 创build包含每行几个项目的ListView项目,以便为适配器内容的一部分形成网格很简单。

如果你想以编程的方式将它滚动到顶部/底部,你可以这样做(从这里 ):

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

我发现了一种在ScrollView中GridView一个固定大小的方法,并且可以滚动它。 这可以让你看到整个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); 

我希望它有助于=)

作为后续行动,我也会分享我的痛苦。 在我的应用程序中,我有一个RecyclerView里面的一个NestedScrollView里面的CoordinatorLayout

 <CoordinatorLayout> <NestedScrollView id="@+id/content"> ....... <TextView android:id="@+id/header"/> <RecyclerView android:id="@+id/recyclerView"/> </NestedScrollView> </CoordinatorLayout> 

当然在打开活动时,页面滚动到中间包括recyclerView。 上面的答案都没有工作,所以我想出了以下解决scheme:

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

HTH

只需在父级布局中添加这两行

android:focusable =“true”android:focusableInTouchMode =“true”

试试这个,希望它能为你工作

只需在ScrollView的Child中添加这一行代码即可

 android:focusableInTouchMode="true"