ฉันสามารถเลื่อน ScrollView โดยทางโปรแกรมใน Android ได้ไหม


145

มีวิธีใดในการเลื่อน ScrollViewโปรแกรมไปยังตำแหน่งใดตำแหน่งหนึ่งโดยโปรแกรม?

ผมได้สร้างแบบไดนามิกซึ่งถูกวางไว้ในTableLayout ScrollViewดังนั้นฉันต้องการให้มีการกระทำที่เฉพาะเจาะจง (เช่นการคลิกปุ่ม ฯลฯ ) แถวใดแถวหนึ่งควรเลื่อนไปที่ตำแหน่งบนสุดโดยอัตโนมัติ

เป็นไปได้ไหม?

คำตอบ:


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 () จะไม่สร้างความปรารถนา resull หนึ่งควรไปกับ fullScroll ()
Amit Yadav

3
การเลื่อนที่ดีกว่านี้คือเอฟเฟกต์ธรรมชาติ: sv.smoothScrollTo (5, 10)
ivan.panasiuk

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

3
ฉันสามารถยืนยันสิ่งที่ค้นพบของ Vanthel mScrollView.fullScroll ในโพสต์ runnable ได้หลอกลวง
AlanKley

1
ยอดเยี่ยม! แน่นอนถ้าไม่มี Runnable มันก็ไม่ทำงาน ตอนนี้มันใช้งานได้! :)
Regis_AG

5
@HiteshDhamshaniya mScrollView.smoothScrollTo(0, mScrollView.getBottom());ถ้าคุณต้องการเลื่อนเรียบลอง
Mike Ortiz

1
ทำไมมันถึงต้องการpostที่นี่?
Liuting

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 ควรมีเฉพาะพาเรนต์เท่านั้น (เช่น Linear Layout)

หากคุณมีผู้ปกครองหลายคนอยู่ในลูกของ ScrollView วิธีแก้ปัญหาเดียวที่ฉันได้พบคือการเรียก requestChildFocus บนมุมมองหลัก:

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

แต่ในกรณีนี้คุณไม่สามารถเลื่อนได้อย่างราบรื่น

ฉันหวังว่าคำตอบนี้สามารถช่วยคนที่มีปัญหาเดียวกัน


1
@JohnT ดีใจที่มันช่วยคุณ :)
Mattia Ruggiero



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บล็อกทำอย่างไร
John Sardinha

1
บล็อก catch คือการตรวจจับข้อยกเว้นระหว่างการเลื่อนถ้าพบใด ๆ
แมดดี้

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 (ดูลูก, ดูเน้น)

child - ลูกของ 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() );

และถ้าจำเป็นคุณสามารถใส่รหัสบรรทัดที่สองด้านบนลงใน runnable:

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

ฉันใช้เวลาค้นคว้าและเล่นไปรอบ ๆ เพื่อหาทางออกที่ง่ายนี้ ฉันหวังว่ามันจะช่วยคุณได้เช่นกัน! :)


1

ฉันใช้ Runnable กับ sv.fullScroll (View.FOCUS_DOWN); มันทำงานได้อย่างสมบูรณ์แบบสำหรับปัญหาที่เกิดขึ้นทันที แต่วิธีการนี้ทำให้ ScrollView รับโฟกัสจากหน้าจอทั้งหมดหากคุณทำให้ 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);

        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.