【问题标题】:How to programmatically scroll an HorizontalScrollView如何以编程方式滚动 Horizo​​ntalScrollView
【发布时间】:2011-06-15 13:24:56
【问题描述】:

我有一个HorizontalScrollView,其中包含一个RelativeLayout。这个布局在 XML 中是空的,并且是从 onCreate 中的 java 填充的。

我希望这个滚动视图最初位于RelativeLayout 中间的某个位置,它比屏幕大得多。

我尝试了mHorizScrollView.scrollTo(offsetX, 0);,但它不起作用。 我不知道这是怎么回事。

我可以发布代码,但它并不真正相关。重要的是一切都以编程方式完成(必须:s),HorizontalScrollView 的初始位置必须以编程方式设置。

感谢阅读。如果您需要更多详细信息或不够清楚,请告诉我。

【问题讨论】:

    标签: android horizontal-scrolling horizontalscrollview


    【解决方案1】:

    使用 Kotlin 扩展函数。

    inline fun <T : View> T.afterMeasured(crossinline f: T.() -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            if (measuredWidth > 0 && measuredHeight > 0) {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                f()
            }
        }
    })
    

    }

    用法:

    mHorizontalScrollView.afterMeasured {
            var scrollTo = 0
            val count = (layout.svList.getChildAt(0) as LinearLayout)
                .childCount
    
            if(index < count){
                val child = (layout.svList.getChildAt(0) as LinearLayout)
                    .getChildAt(index)
    
                scrollTo = child.width
    
            }
    
            Log.d(TAG, "scrollToComment: $scrollTo")
    
            mHorizontalScrollView.scrollTo(scrollTo, 0)
        }
    

    【讨论】:

      【解决方案2】:

      我发现如果你extendHorizontalScrollView和覆盖onLayout,你可以干净地滚动,在超级调用onLayout之后:

      MyScrollView extends HorizontalScrollView {
          protected void onLayout (boolean changed, int l, int t, int r, int b) {
              super.onLayout(changed, l, t, r, b);
              this.scrollTo(wherever, 0);
          }
      }
      

      编辑: 要滚动到 startend,您可以使用:

      this.fullScroll(HorizontalScrollView.FOCUS_RIGHT/FOCUS_LEFT);
      

      而不是

      this.scrollTo(wherever, 0);
      

      【讨论】:

        【解决方案3】:
        public void autoSmoothScroll() {
        
                final HorizontalScrollView hsv = (HorizontalScrollView) view.findViewById(R.id.horiscroll);
                hsv.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
                        hsv.smoothScrollBy(500, 0);
                    }
                },100);
            }
        

        【讨论】:

        • 我想滚动到水平滚动视图中的视图。这段代码对我有用。我使用hsv.post() 而不是hsv.postDelayed()
        • 这样滚动也不错 hsv.arrowScroll(Horizo​​ntalScrollView.FOCUS_LEFT/RIGHT);
        【解决方案4】:

        更好的方法是使用ViewTreeObserver 来观察布局。

        View interestedInView;
        onCreate(){
          //Code
        
          //Observe for a layout change
          ViewTreeObserver viewTreeObserver = interestedInView.getViewTreeObserver();
          if (viewTreeObserver.isAlive()) {
            viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
              @Override
              public void onGlobalLayout() {
                //REMOVE THE VIEWTREE OBSERVER
                //interestedInView is ready for size and position queries because it has been laid out
              }
            });
          }
        }
        

        【讨论】:

        • 感谢它为我工作的帮助,但我有疑问它是否需要更多处理然后延迟(新 Runnable() ....)
        • 好吧,如果您要承担运行时开销,答案是肯定的,因为您要添加一个新的侦听器然后将其删除。但它是如此之小以至于它不会被计算在内。这种方法的稳健性是值得的。
        • 现在我正在使用 ViewTreeObserver 并且它为我工作,请告诉我它的效率是否较低或什么???
        • @MGD 不是。您只是附加一个侦听器,然后将其删除。所以它同样高效,更重要的是,非常强大。
        • 感谢 Vikram 的评论,但我在stackoverflow.com/questions/9414035/… 上发布了一些问题,如果您能提供帮助,请考虑这个问题 :)
        【解决方案5】:

        使用 view.post 并在 run 方法中写入 scrollTo(x,y)。这是根据 android API 文档在 post 方法中使视图无效的方法。

        【讨论】:

        • 我刚刚用 .post 替换了我的 postDelayed,它就像一个魅力。就像监听器一样健壮,因为它在视图被附加后触发。我用它来访问视图的尺寸,因为它只有在它被附加到屏幕上测量后才可用。
        【解决方案6】:

        onSizeChanged 函数应该可以工作。您无法理解的是 onSizeChanged 应该向您的活动的处理程序发送消息,而不是任何回调函数,因为处理程序将在 UI 线程中执行代码。您不能在它之外进行 UI 操作。看看处理程序。

        【讨论】:

        • onSizeChanged 必须在 UI 线程中调用,因为当我从 onSizeChanged 调用 scrollTo 时,它没有报错。
        【解决方案7】:

        问题是视图还没有大小。执行此操作的干净方法是实现 ScrollView 的 onSizeChanged 以向活动中的处理程序发送消息,以通知活动视图具有大小并且可以滚动。

        【讨论】:

        • 这看起来非常好,但它不起作用。我创建了一个扩展 Horizo​​ntalScrollView 并实现 onSizeChanged 的​​类。调用此回调时,它会调用 Activity 中执行滚动的方法。但是,滚动不起作用。仅在延迟发布时才有效。
        【解决方案8】:

        要测试是否是时间问题(我认为是),而不是在 onStart 中调用 scrollTo(),而是使用调用 scrollTo 的 Runnable 调用 postDelayed(),延迟 30 左右。

        【讨论】:

        • 这证实了这确实是一个时间问题。有没有比 postDelayed Runnable 更清洁的方法?
        • 您可能可以继承 Horizo​​ntalScrollView,添加一个指示需要滚动的字段,然后在下一次调用 onLayout() 结束时进行滚动(或者可能在 computeScroll() 或其他一些方法)。我认为使用 postDelayed 更容易。
        • 我发现了一些奇怪的东西,我认为使用 'scroll.smoothScrollTo' 你需要比使用 'scroll.scrollTo' 更多的延迟。
        • 我会非常小心地使用延迟作为解决方案,因为您不能说在您的设备/模拟器上设置的延迟是否适合所有其他设备的性能。我认为更好、更清洁的解决方案是扩展 Horizo​​ntalScrollView,正如您在 HaIR 的回答中看到的那样
        • @Muzikant - 我认为 HaIR 的回答提供了比我自己更好的解决方案。
        【解决方案9】:

        scrollTo 函数应该可以工作。 HSV的layout_width是多少,里面的view是多少?

        【讨论】:

        • 我认为这是一个时间问题。 HSV 内的视图是在运行时添加的(来自 onCreate),HSV 的 layout_width 是 fill_parent。 mHSV.scrollTo() 从 onStart 调用。
        猜你喜欢
        • 2021-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多