我可以在Android中以编程方式滚动ScrollView吗?


Answers:


165
ScrollView sv = (ScrollView)findViewById(R.id.scrl);
sv.scrollTo(0, sv.getBottom());

要么

sv.scrollTo(5, 10);


43
结合ercu的回答和对此的评论,最好的方法似乎是:mScrollView.post(new Runnable() { public void run() { mScrollView.fullScroll(View.FOCUS_DOWN); } });
麻雀

2
scrollTo()不会产生期望的转义。应该使用fullScroll()
阿米特·亚达夫

3
更加自然的滚动效果更自然:sv.smoothScrollTo(5,10)
ivan.panasiuk 2015年

205

Pragna的答案并不总是有效,请尝试以下操作:

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.scrollTo(0, mScrollView.getBottom());
        } 
});

要么

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_DOWN);
        } 
});

如果要滚动开始

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_UP);
        } 
});

28
我曾经mScrollView.fullScroll(mScrollView.FOCUS_DOWN);成功。
amcc 2012年

3
我可以证实Vanthel的发现。在可运行的帖子中使用mScrollView.fullScroll可以达到目的。
AlanKley 2013年

1
优秀的 !确实,没有Runnable,它就无法工作。现在,它起作用了!:)
Regis_AG 2013年

5
@HiteshDhamshaniya如果要平滑滚动,请尝试mScrollView.smoothScrollTo(0, mScrollView.getBottom());
Mike Ortiz 2014年

1
为什么post在这里需要?
流亭

35

我希望scrollView在onCreateView()之后直接滚动(而不是在单击按钮之后)。为了使其正常工作,我需要使用ViewTreeObserver:

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });

但是请注意,每当布局某些内容时(例如,将视图设置为不可见或类似的视图)都会调用此方法,因此,如果您不再需要此侦听器,请不要忘记使用以下方法删除它:

public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) 在SDK Lvl <16上

要么

public void removeOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) 在SDK Lvl> = 16中


23

这里有很多好的答案,但是我只想添加一件事。有时会发生您想将ScrollView滚动到版面的特定视图,而不是完全滚动到顶部或底部的情况。

一个简单的示例:在注册表单中,如果用户在未填写表单的编辑文本时点击“注册”按钮,则要滚动到该特定的编辑文本以告诉用户他必须填写该字段。

在这种情况下,您可以执行以下操作:

scrollView.post(new Runnable() { 
        public void run() { 
             scrollView.scrollTo(0, editText.getBottom());
        } 
});

或者,如果要平滑滚动而不是即时滚动:

scrollView.post(new Runnable() { 
            public void run() { 
                 scrollView.smoothScrollTo(0, editText.getBottom());
            } 
    });

显然,您可以使用任何类型的视图代替“编辑文本”。请注意,getBottom()根据其父级布局返回视图的坐标,因此ScrollView中使用的所有视图都应只有一个父级(例如,线性布局)。

如果您在ScrollView的子级中有多个父级,那么我发现的唯一解决方案是在父级视图上调用requestChildFocus:

editText.getParent().requestChildFocus(editText, editText);

但是在这种情况下,您无法流畅滚动。

我希望这个答案可以帮助遇到同样问题的人。


1
@JohnT很高兴它为您提供了帮助:)
Mattia Ruggiero

20

使用这样的东西:

mScrollView.scrollBy(10, 10);

要么

mScrollView.scrollTo(10, 10);


8

如果要立即滚动,则可以使用:

ScrollView scroll= (ScrollView)findViewById(R.id.scroll);
scroll.scrollTo(0, scroll.getBottom());

            OR

scroll.fullScroll(View.FOCUS_DOWN);

            OR

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

或者,如果您想要平滑而缓慢地滚动,则可以使用以下方法:

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

这是什么catch块呢?
约翰·萨丁尼亚

1
Catch块用于在滚动过程中捕获异常(如果发现)。
Maddy

5

**滚动到所需的高度。我已经提出了一些好的解决方案**

                scrollView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.scrollBy(0, childView.getHeight());
                    }
                }, 100);

4

我使它可以滚动到ScrollView的底部(内部带有TextView):

(我把它放在更新TextView的方法上)

final ScrollView myScrollView = (ScrollView) findViewById(R.id.myScroller);
    myScrollView.post(new Runnable() {
    public void run() {
        myScrollView.fullScroll(View.FOCUS_DOWN);
    }
});

4

是的你可以。

假设您有一个Layout,里面有很多Views。因此,如果要以View编程方式滚动到任意内容,则必须编写以下代码段:

例如:

content_main.xml

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/txtView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>
</ScrollView>

MainActivity.java

ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
Button btn = (Button) findViewById(R.id.ivEventBanner);
TextView txtView = (TextView) findViewById(R.id.ivEditBannerImage);

如果您想滚动到特定的View,例如txtview,在这种情况下,只需编写:

scrollView.smoothScrollTo(txtView.getScrollX(),txtView.getScrollY());

您完成了。


3

注意:如果您已经在一个线程中,则必须创建一个新的发布线程,否则它不会滚动新的长高度直到完整结束(对我而言)。例如:

void LogMe(final String s){
    runOnUiThread(new Runnable() {
        public void run() {
            connectionLog.setText(connectionLog.getText() + "\n" + s);
            final ScrollView sv = (ScrollView)connectLayout.findViewById(R.id.scrollView);
            sv.post(new Runnable() {
                public void run() {
                    sv.fullScroll(sv.FOCUS_DOWN);
                    /*
                    sv.scrollTo(0,sv.getBottom());
                    sv.scrollBy(0,sv.getHeight());*/
                }
            });
        }
    });
}

3

添加另一个不涉及坐标的答案。

这将使您所需的视图聚焦(但不会到达最高位置):

  yourView.getParent().requestChildFocus(yourView,yourView);

公共无效RequestChildFocus(查看子级,查看焦点)

孩子 -这ViewParent想要对焦的孩子。该视图将包含焦点视图。实际上不一定是焦点。

聚焦 -视图是实际具有焦点的孩子的后代


正是我需要的,谢谢。首先为滚动视图请求焦点,然后为scrollView.smoothScrollTo(0,scrollView.getChildAt(0).getBottom());
Vulovic Vukasin


2

每个人都在发布如此复杂的答案。

我找到了一个简单的答案,可以很好地滚动到底部:

final ScrollView myScroller = (ScrollView) findViewById(R.id.myScrollerView);

// Scroll views can only have 1 child, so get the first child's bottom,
// which should be the full size of the whole content inside the ScrollView
myScroller.smoothScrollTo( 0, myScroller.getChildAt( 0 ).getBottom() );

并且,如有必要,您可以将上面的第二行代码放入可运行的代码中:

myScroller.post( new Runnable() {
    @Override
    public void run() {
        myScroller.smoothScrollTo( 0, myScroller.getChildAt( 0 ).getBottom() );
    }
}

我花了很多时间研究并努力寻找这个简单的解决方案。希望对您有帮助!:)


1

我在sv.fullScroll(View.FOCUS_DOWN)中使用了Runnable; 它完美地解决了当前的问题,但是该方法使ScrollView从整个屏幕上获取了Focus,如果您使AutoScroll每次都发生,则EditText将无法从用户那里接收信息,我的解决方案是使用其他代码在runnable下:

sv.scrollTo(0,sv.getBottom()+ sv.getScrollY());

在不失去对重要观点的关注的情况下做到相同

问候。


0

它为我工作

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });

0
private int totalHeight = 0;

ViewTreeObserver ScrollTr = loutMain.getViewTreeObserver();
ScrollTr.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            loutMain.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        } else {
            loutMain.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
        TotalHeight = loutMain.getMeasuredHeight();

    }
});

scrollMain.smoothScrollTo(0, totalHeight);

0
I had to create Interface

public interface ScrollViewListener {
    void onScrollChanged(ScrollViewExt scrollView, 
                         int x, int y, int oldx, int oldy);
}    

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;

public class CustomScrollView extends ScrollView {
    private ScrollViewListener scrollViewListener = null;
    public ScrollViewExt(Context context) {
        super(context);
    }

    public CustomScrollView (Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomScrollView (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }
}




<"Your Package name ".CustomScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusableInTouchMode="true"
    android:scrollbars="vertical">

    private CustomScrollView scrollView;

scrollView = (CustomScrollView)mView.findViewById(R.id.scrollView);
        scrollView.setScrollViewListener(this);


    @Override
    public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
        // We take the last son in the scrollview
        View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1);
        int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));

        // if diff is zero, then the bottom has been reached
        if (diff == 0) {
                // do stuff
            //TODO keshav gers
            pausePlayer();
            videoFullScreenPlayer.setVisibility(View.GONE);

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