【问题标题】:Android ScrollView doesn't start at top, but at the beginning of the GridViewAndroid ScrollView 不是从顶部开始,而是在 GridView 的开头
【发布时间】:2013-05-28 23:23:21
【问题描述】:

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

有什么建议吗??

【问题讨论】:

    标签: java android gridview scrollview


    【解决方案1】:

    解决方案:

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

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

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

    listView.setFocusable(false);
    

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

    一切正常 =)

    【讨论】:

    • 也适用于 webview
    • 很棒的修复,谢谢。我想知道如果我在 xml 中设置它为什么它不起作用。
    • 也想知道为什么它在 xml 中不起作用。默认行为很奇怪,为什么会有人想要那个??
    【解决方案2】:

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

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

    这意味着当您启动 Activity 时,整个 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" >
    

    【讨论】:

    • 不适合我,我在滚动视图中有一个回收视图
    • RecyclerView 是一个特例,和 ListView 一样。通常,将 2 个可滚动容器彼此放在一个内部(一个 ScrollView 中的 ListView 或 RecyclerView)是一堆问题和导致不容易解决的问题。如果你有一个 EditText,在 RecyclerView 中,在 ScrollView 中,事情会变得非常糟糕,并且简单的解决方案(后代可聚焦性)并不容易应用,部分原因是滚动容器本身是如何实现的。
    • 请注意,ScrollView 仅当它是其他可滚动小部件的直接父级时才需要这些属性。否则只需获取父级并放置相同的属性。我将 LinearLayout 作为 ExpandableHeightGridView 的直接父级,并且此解决方案按需要工作。
    • 我在ScrollView 内有ExpandableListView,您的方法仅适用于Android 8(Sony G8441),但不适用于Android 5(华为荣耀7)、Android 6(三星Galaxy J5) ,Android 7(华为 P9 Lite)。
    【解决方案3】:

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

    android:focusableInTouchMode="true"
    

    【讨论】:

      【解决方案4】:

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

      android:focusable =“真” android:focusableInTouchMode =“真”

      试试这个,希望对你有用

      【讨论】:

        【解决方案5】:

        如果您想以编程方式将其滚动到顶部/底部,您可以这样做(来自here):

        焦点向下:

        ((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】:

          滚动视图

          android:fitsSystemWindows="false"
          

          【讨论】:

            【解决方案7】:

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

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

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

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

            【讨论】:

            • 在这个活动中,用户可以添加他想要多少个 textviews(用于信息、cmets 等)和 imageviews(他自己的照片)。我希望整个视图是可滚动的,并且gridview 非常适合管理图像,所以我喜欢这个解决方案。
            【解决方案8】:

            实现此目的的简单方法是在 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
            

            【讨论】:

            • 在以上所有答案中,只有这个对我有用,谢谢兄弟。
            【解决方案9】:

            我找到了一种方法,让 GridView在 ScrollView 内具有固定大小,并启用滚动。这使您无需滚动 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);
            

            希望对你有帮助=)

            【讨论】:

              【解决方案10】:

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

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

              当然,在打开 Activity 时,页面会滚动到中间包含 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
              }
              

              HTH

              【讨论】:

                【解决方案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>
                

                【讨论】:

                  【解决方案12】:

                  我遇到了类似的问题,但完全不同的东西对我有用。我有以下类型的视图层次结构-

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

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-02-14
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多