Android:ScrollView强制触底


Answers:


274

scroll.fullScroll(View.FOCUS_DOWN) 也应该工作。

放在一个 scroll.Post(Runnable run)

科特林密码

scrollView.post {
   scrollView.fullScroll(View.FOCUS_DOWN)
}

6
那似乎什么都没做,有什么建议吗?我在onCreate上尝试过,后来在按钮的onClick中尝试过。
理查德·约翰恩(RichardJohnn)2010年

改变方向似乎不起作用。否则它的工作。
Prashant

1
如果布局大小在调用前就已更改,则此方法不起作用。它需要改为发布。
MLProgrammer-CiM 2015年

2
在您花一些时间充分充实视图之前,此操作及以下操作将不起作用,只是简化了ademar答案。scrollView.postDelayed(new Runnable(){@Override public void run(){scrollView.fullScroll(View.FOCUS_UP //或向下);}},1000);
EngineSense 2015年

scroll.fullScroll(View.FOCUS_DOWN)将导致焦点改变。当有多个可聚焦视图时(例如两个EditText),这将带来一些奇怪的行为。检查我在底部提供的另一种解决方案。
Peacepassion '16

332

您应该像这样在scroll.post内部运行代码:

scroll.post(new Runnable() {            
    @Override
    public void run() {
           scroll.fullScroll(View.FOCUS_DOWN);              
    }
});

4
有某种方法可以不丢失当前元素的焦点,当我这样做时,我会丢失我当前元素的焦点(与scrollview不同)
rkmax 2014年

2
仅在尚未测量和布置布局的情况下才需要此操作(例如,如果在onCreate中运行它)。在按下按钮的情况下,不需要.post()。
Patrick Boos

12
如果您不想集中在ScrollView上,则可以使用scroll.scrollTo(0, scroll.getHeight());跳转到底部,或者scroll.smoothScrollTo(0, scroll.getHeight());滚动更平滑
yuval 2016年

该代码是否可能导致内存泄漏?将创建一个匿名Runnable,其中包含对活动(滚动)视图的引用。如果活动在可运行对象执行任务时被破坏,它将泄漏对滚动视图的引用,不是吗?
Jenever '18

在科特林:scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
艾伯特·维拉·卡尔沃

94

scroll.fullScroll(View.FOCUS_DOWN)会导致焦点的改变。当有多个可聚焦视图时(例如两个EditText),这将带来一些奇怪的行为。这个问题还有另一种方式。

    View lastChild = scrollLayout.getChildAt(scrollLayout.getChildCount() - 1);
    int bottom = lastChild.getBottom() + scrollLayout.getPaddingBottom();
    int sy = scrollLayout.getScrollY();
    int sh = scrollLayout.getHeight();
    int delta = bottom - (sy + sh);

    scrollLayout.smoothScrollBy(0, delta);

这很好。

Kotlin扩展

fun ScrollView.scrollToBottom() {
    val lastChild = getChildAt(childCount - 1)
    val bottom = lastChild.bottom + paddingBottom
    val delta = bottom - (scrollY+ height)        
    smoothScrollBy(0, delta)
}

很高兴我不必再为此浪费时间。正是我所需要的
Alexandre G

6
这应该有更多的支持。到目前为止,这是最好的答案。
埃里克·兰格

1
这是目前的最佳答案。
空指针

1
尝试了此页面上的所有其他内容,甚至包括下面的内容。这是唯一起作用的方法,并且不会导致我的EditText失去焦点。谢谢。
乔尔

如果您需要在键盘显示时向下滚动,请将此代码与此库结合使用。奇迹般有效。
wonsuc

47

有时scrollView.post不起作用

 scrollView.post(new Runnable() {
        @Override
        public void run() {
            scrollView.fullScroll(ScrollView.FOCUS_DOWN);
        }
    });

但是,如果您使用scrollView.postDelayed,它肯定会工作

 scrollView.postDelayed(new Runnable() {
        @Override
        public void run() {
            scrollView.fullScroll(ScrollView.FOCUS_DOWN);
        }
    },1000);

感谢您的识别。postDelayed是更好的解决方案。
Prashant

@Prashant :) :) :)
Ajay Shrestha

1
只要记住当您完成活动时就需要处置Runnable
FabioR

38

最适合我的是

scroll_view.post(new Runnable() {
     @Override
     public void run() {
         // This method works but animates the scrolling 
         // which looks weird on first load
         // scroll_view.fullScroll(View.FOCUS_DOWN);

         // This method works even better because there are no animations.
         scroll_view.scrollTo(0, scroll_view.getBottom());
     }
});

我试过了,但是这里的算法是错误的。请在底部检查我的答案。
Peacepassion '16

28

我增加以完美地工作。

    private void sendScroll(){
        final Handler handler = new Handler();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {Thread.sleep(100);} catch (InterruptedException e) {}
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.fullScroll(View.FOCUS_DOWN);
                    }
                });
            }
        }).start();
    }

注意

这个答案是真正旧版android的解决方法。今天,postDelayed该错误已不再存在,您应该使用它。


3
不在两个以上,但是在我的手机(LG JellyBean 4.1.2 Optimus G)中效果很好。
Youngjae 2013年

9
为什么不使用scrollView.postDelayed(runnable,100)?
马特·沃尔夫

1
@MattWolfe当时在某些旧版本的android中不起作用。但是今天,这个答案已经被弃用了。
ademar111190 2014年

4
对于上帝的爱,请使用scrollView.postDelayed(runnable,100)!:)
Alex Lockwood

1
我添加了一个注释@AlexLockwood,我希望人们使用postDelayed:)
ademar111190


3

当视图尚未加载时,您将无法滚动。您可以通过上面的发布或睡眠呼叫“稍后”执行此操作,但这不是很优雅。

最好计划滚动并在下一个onLayout()上进行滚动。示例代码在这里:

https://stackoverflow.com/a/10209457/1310343


3

要考虑的一件事是不设置什么。确保您的子控件(尤其是EditText控件)没有设置RequestFocus属性。这可能是布局上最后解释的属性之一,它将覆盖其父级(布局或ScrollView)上的重力设置。


3

这是滚动到底部的其他方法

fun ScrollView.scrollToBottom() {
    // use this for scroll immediately
    scrollTo(0, this.getChildAt(0).height) 

    // or this for smooth scroll
    //smoothScrollBy(0, this.getChildAt(0).height)

    // or this for **very** smooth scroll
    //ObjectAnimator.ofInt(this, "scrollY", this.getChildAt(0).height).setDuration(2000).start()
}

使用

如果您滚动视图已经布局

my_scroll_view.scrollToBottom()

如果您的滚动视图未完成布局(例如:您在“活动” onCreate方法中滚动到底部...)

my_scroll_view.post { 
   my_scroll_view.scrollToBottom()          
}

1

不完全是问题的答案,但是一旦EditText获得焦点,我就需要向下滚动。但是,被接受的答案会使ET也立即失去焦点(我认为是ScrollView)。

我的解决方法如下:

emailEt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if(hasFocus){
            Toast.makeText(getActivity(), "got the focus", Toast.LENGTH_LONG).show();
            scrollView.postDelayed(new Runnable() {
                @Override
                public void run() {
                    scrollView.fullScroll(ScrollView.FOCUS_DOWN);
                }
            }, 200);
        }else {
            Toast.makeText(getActivity(), "lost the focus", Toast.LENGTH_LONG).show();
        }
    }
});

1

我实际上发现两次调用fullScroll可以达到目的:

myScrollView.fullScroll(View.FOCUS_DOWN);

myScrollView.post(new Runnable() {
    @Override
    public void run() {
        myScrollView.fullScroll(View.FOCUS_DOWN);
    }
});

在执行第一次(不成功)滚动之后,可能与激活post()方法有关。我认为在对myScrollView进行任何先前的方法调用之后都会发生此行为,因此您可以尝试用与您相关的任何其他方法替换第一个fullScroll()方法。


0

使用Kotlin协程可以使用另一种很酷的方法来做到这一点。使用与带有可运行(post / postDelayed)的Handler相对的协程的优点是,它不会触发昂贵的线程来执行延迟的操作。

launch(UI){
    delay(300)
    scrollView.fullScroll(View.FOCUS_DOWN)
}

将协程的HandlerContext指定为UI很重要,否则可能不会从UI线程调用延迟的操作。


0

在那种情况下,仅使用scroll.scrollTo(0,sc.getBottom())不起作用,请使用scroll.post使用

例:

scroll.post(new Runnable() {
  @Override
  public void run() {
  scroll.fullScroll(View.FOCUS_DOWN);
  } 
});

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.