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

Posted

技术标签:

【中文标题】我可以在 Android 中以编程方式滚动 ScrollView 吗?【英文标题】:Can I scroll a ScrollView programmatically in Android? 【发布时间】:2011-09-20 06:01:59 【问题描述】:

有没有办法以编程方式将ScrollView 滚动到某个位置?

我创建了动态TableLayout,它被放置在ScrollView 中。因此,我希望在特定操作(例如单击按钮等)上,特定行应自动滚动到顶部位置。

有可能吗?

【问题讨论】:

【参考方案1】:

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

【讨论】:

我成功使用了mScrollView.fullScroll(mScrollView.FOCUS_DOWN); 我可以确认 Vanthel 的发现。可运行的帖子中的 mScrollView.fullScroll 起到了作用。 太棒了!事实上,没有 Runnable,它就行不通。现在,它起作用了! :) @HiteshDhamshaniya 如果你想要流畅的滚动,试试mScrollView.smoothScrollTo(0, mScrollView.getBottom()); 这里为什么需要post【参考方案2】:
ScrollView sv = (ScrollView)findViewById(R.id.scrl);
sv.scrollTo(0, sv.getBottom());

sv.scrollTo(5, 10);

【讨论】:

结合ercu的回答和评论,最好的办法似乎是:mScrollView.post(new Runnable() public void run() mScrollView.fullScroll(View.FOCUS_DOWN); ); scrollTo() 不会产生期望结果。应该使用 fullScroll() 更漂亮的滚动效果更自然:sv.smoothScrollTo(5, 10)【参考方案3】:

我希望 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

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

【讨论】:

【参考方案4】:

这里有很多好的答案,但我只想补充一件事。有时您希望将 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);

但在这种情况下,您无法平滑滚动。

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

【讨论】:

@JohnT 很高兴它帮助了你:)【参考方案5】:

使用这样的东西:

mScrollView.scrollBy(10, 10);

mScrollView.scrollTo(10, 10);

【讨论】:

【参考方案6】:

尝试使用scrollTo方法More Info

【讨论】:

【参考方案7】:

如果你想立即滚动,那么你可以使用:

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 块有什么作用? Catch 块用于在滚动过程中捕获异常(如果发现)。【参考方案8】:

**向上滚动到所需的高度。我想出了一些好的解决方案**

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

【讨论】:

【参考方案9】:

是的,你可以。

假设你有一个Layout,而在其中,你有很多Views。所以如果你想以编程方式滚动到任何View,你必须编写以下代码sn-p:

例如:

content_main.xml

<ScrollView
    android:id="@+id/scrollView"
    android:layout_
    android:layout_>

    <LinearLayout
        android:layout_
        android:layout_
        android:orientation="vertical">

        <Button
            android:id="@+id/btn"
            android:layout_
            android:layout_ />

        <TextView
            android:id="@+id/txtView"
            android:layout_
            android:layout_ />

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

你就完成了。

【讨论】:

【参考方案10】:

我让它滚动到 ScrollView 的底部(里面有一个 TextView):

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

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

【讨论】:

【参考方案11】:

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

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());*/
                
            );
        
    );

【讨论】:

【参考方案12】:

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

这将使您想要的视图成为焦点(但不是顶部位置):

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

public void RequestChildFocus(查看孩子,查看重点)

child - 这个 ViewParent 想要获得焦点的孩子。此视图将包含焦点视图。它不一定是真正具有焦点的视图。

focused - 实际上具有焦点的 child 的后代视图

【讨论】:

正是我需要的,谢谢。首先为您滚动视图请求焦点,然后 scrollView.smoothScrollTo(0, scrollView.getChildAt(0).getBottom());【参考方案13】:

只是页面滚动:

ScrollView sv = (ScrollView) findViewById(your_scroll_view);
sv.pageScroll(View.FOCUS_DOWN);

【讨论】:

【参考方案14】:

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

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

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

我花了很多时间研究并四处寻找这个简单的解决方案。我也希望它对你有帮助! :)

【讨论】:

【参考方案15】:

我使用 Runnable 和 sv.fullScroll(View.FOCUS_DOWN); 它非常适合当前的问题,但是该方法使 ScrollView 从整个屏幕中获取焦点,如果您每次都使 AutoScroll 发生,则没有 EditText 将能够从用户那里接收信息,我的解决方案是使用不同的代码在runnable下:

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

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

问候。

【讨论】:

【参考方案16】:

它对我有用

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

【讨论】:

【参考方案17】:
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);

【讨论】:

【参考方案18】:
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_
    android:layout_
    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);

        
    

【讨论】:

以上是关于我可以在 Android 中以编程方式滚动 ScrollView 吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何在IOS中以编程方式滚动UICollectionViewCell?

如何使用 vanilla js 在 Cordova / Capacitor / Conic 中以编程方式滚动

在 Swift 中以编程方式添加时,UIScrollView 根本不滚动?

如何在 SwiftUI 中以编程方式滚动列表?

未能尝试在 SWIFT 中以编程方式在滚动视图中添加 UIView 约束

是否可以在 android 中以编程方式创建和填充 AutoCompleteTextView?