60

我有一个 ScrollView 的问题,它里面有一个个性化的 GridView 和其他视图提示。我第一次启动 Activity 时,ScrollView 从顶部开始,但是如果我在其他时间访问 Activity,则 ScrollView 从开头开始的 GridView。我将在此链接中找到的类 ExpandableHeightGridView用于我的 GridView。Activity 布局的 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 顶部到屏幕顶部制作一个快速动画,我不喜欢它。

有什么建议吗??

4

12 回答 12

182

解决方案:

好的,抱歉,如果回复晚了,但我偶然发现了同样的问题(只是我使用的是 ListView),经过一些试验和错误,我找到了解决方案

基本上问题在于,当您“破解”并使用ExpandableHeightGridView调整其内容的大小时,GridView/ListView 子项会自动请求父焦点(ScrollView) ,这发生在呈现布局之后,因此您在尝试滚动时会看到动画使用 scrollTo() (在创建布局和调整 gridView 大小之后发生,因此任何通用回调都无法以编程方式处理此问题)。

那么,我发现的最简单的解决方案是简单地禁用 ListView/GridView 上的可聚焦属性:

listView.setFocusable(false);

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

一切正常=)

于 2014-01-20T13:14:20.900 回答
22

最简单的方法是在父 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" >
于 2015-09-30T09:31:21.980 回答
8

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

android:focusableInTouchMode="true"
于 2017-10-27T09:49:07.187 回答
7

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

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

试试这个,希望它对你有用

于 2017-06-28T08:36:01.910 回答
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); 
    } 
});
于 2014-11-22T08:44:14.490 回答
4

滚动视图

android:fitsSystemWindows="false"
于 2016-12-28T19:08:53.187 回答
2

可悲的是,您遵循的示例非常糟糕。ListViews 和 GridViews 永远不应该放在 ScrollViews 中。

ScrollView 的目的是为其子视图赋予无限的高度。List/GridView 的目的是获取一个可能非常大的数据集,并且只生成足够的项目视图来一次填充可用的空间以提高效率。两者都能够在没有对方的情况下滚动其内容。

将 List/GridView 放入 ScrollView 就是在说“势不可挡的力量,遇到不动的物体”。要么你已经打败了 List/GridView 的观点,要么你已经通过结合它们打败了 ScrollView 的观点。

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

于 2013-06-02T19:50:28.840 回答
2

实现这一点的简单方法是在 XML 中为您的 ScrollView 设置一个 ID ...假设

scrollView_main

之后,您只需要转到您的 java 文件并将其声明为像 onCreate 过程上方的普通变量一样是这样的全局变量

ScrollView scrollView_main;

好的,现在是时候去 onCreate 过程并声明它,从 XML 文件中获取与您的 ID 的连接

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

最后是可以使您的 ScrollView 滚动到顶部的代码,这就是您的答案

scrollView_main.smoothScrollTo(0,0); //set it on top
于 2018-08-20T15:47:20.193 回答
0

我找到了一种在 ScrollView中为GridView提供固定大小并启用滚动的方法。这使您无需滚动 GridView 的所有元素即可查看整个 ScrollView,对我来说,使用ExpandableHeightGridView更有意义。

为此,您必须实现一个扩展 GridView 的新类并覆盖onTouchEvent()以调用requestDisallowInterceptTouchEvent(true)。因此,父视图将离开 Grid 拦截触摸事件。

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

我希望它有帮助 =)

于 2014-11-11T15:41:59.230 回答
0

我有一个类似的问题,并且完全不同的东西对我有用。我有以下类型的视图层次结构 -

<LinearLayout>
    <ImageView />
    <ScrollView>
        <TextView android:id="header_tv"/>
        <TabLayout />
        <ViewPager2 />
    </ScrollView>
</LinearLayout>

并且用于打开的视图已经滚动到视图寻呼机。我只是将android:focusable="true"添加到滚动视图的第一个元素来解决此问题,如下所示 -

<LinearLayout>
    <ImageView />
    <ScrollView>
        <TextView 
            android:id="header_tv"
            android:focusable="true" />
        <TabLayout />
        <ViewPager2 />
    </ScrollView>
</LinearLayout>
于 2020-11-28T12:08:19.943 回答
0

作为后续行动,我也会分享我的痛苦。在我的应用程序中,我有一个RecyclerViewinside a NestedScrollViewinside a 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
}

高温高压

于 2016-04-19T09:30:03.220 回答
0

If nothing works, just put this as the first element of your scrollView's single child:

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

example:

  <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>
于 2019-07-16T10:38:13.537 回答