วิธีเลื่อนไปที่ด้านบนสุดของเค้าโครง ScrollView ที่ยาวได้อย่างไร


162

สำหรับส่วนหนึ่งของแอพของฉันผู้ใช้จะได้รับรายชื่อและขอให้จัดกลุ่มตามที่เห็นสมควร

(หมายเหตุรหัส ListView ถูกคัดลอกคำต่อคำจากการสอน Android Views ฉันยังไม่ได้ปรับแต่งมันให้ตรงกับความต้องการของฉันฉันแค่พยายามหาวิธีใช้งานนี้)

เค้าโครงพื้นฐานคือ LinearLayout ที่มี ScrollView (เรียกว่า "groupsScrollView" ในรหัสด้านล่าง) ซึ่งมี RelativeLayout ฉันมีปุ่มและข้อความจากนั้น ListView ของฉันอยู่ด้านล่างซึ่งแสดงรายการชื่อ ทั้งหมดนี้สูงกว่าพื้นที่หน้าจอที่มองเห็นได้ดังนั้นผู้ใช้จึงสามารถเลื่อนในแนวตั้งเพื่อดูได้ทั้งหมด

ทั้งหมดนี้ทำงานได้อย่างสวยงามยกเว้นเมื่อหน้าโหลดมันจะถูกเลื่อนไปด้านบนของ ListView ของฉันเสมอ - ในช่วงกลางของหน้า ข้อความและปุ่มที่ฉันสร้างที่บอกผู้ใช้ว่าต้องทำอย่างไรจะมองไม่เห็น

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

นี่คือวิธีการ onCreate ของฉัน:

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.groups);

    mainScrollView = (ScrollView)findViewById(R.id.groupsScrollView);

    //get the Bundle out of the Intent...
    Bundle extras = getIntent().getExtras();
    mNames = extras.getStringArray("mNames");

    setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, mNames));

    ListView lv = getListView();
    lv.setTextFilterEnabled(true);

    //This is the line I'm having issues with
    mainScrollView.pageScroll(View.FOCUS_UP);

    lv.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
          // When clicked, show a toast with the TextView text
          Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
              Toast.LENGTH_SHORT).show();
        }
      });
}

บรรทัด "mainScrollView.pageScroll (View.FOCUS_UP); เป็นปัญหามันไม่ได้ทำให้เกิดข้อผิดพลาด แต่ดูเหมือนจะไม่ทำอะไรเลยฉันลอง scrollTo (0,0), scrollDirection (View.FOCUS_UP ) และทุกอย่างอื่นที่ฉันสามารถนึกได้

เนื่องจากฉันไม่ได้รับข้อผิดพลาดฉันจึงต้องสมมติว่าคำสั่งเลื่อนเหล่านี้ใช้งานได้จริง แต่พวกเขากำลังเลื่อนไปที่ด้านบนของ ListView แทนที่จะเป็นด้านบนของ ScrollView หรือ RelativeLayout ที่มีอยู่ สิ่งนี้ดูเหมือนจะได้รับการยืนยันโดยคำอธิบายของตัวเองของ Google สำหรับวิธีการ scrollTo (int x, int y) ที่พวกเขาพูดว่า

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

ขอบคุณ!

คำตอบ:



175

มีปัญหาเดียวกันอาจเป็นข้อผิดพลาดบางประเภท

แม้แต่fullScroll(ScrollView.FOCUS_UP)คำตอบอื่น ๆ ก็ไม่ได้ผล
มีเพียงสิ่งเดียวที่ทำงานกับฉันที่โทรมาscroll_view.smoothScrollTo(0,0)หลังจากไดอะล็อกปรากฏขึ้น


สิ่งนี้ใช้ได้ในตอนแรก แต่ต่อมาเมื่อฉันพยายามทำมันซ้ำแล้วซ้ำอีกวิธีการนี้ไม่ได้ผลที่น่าพอใจ
JaydeepW

16
ฉันแก้จาก scroll_view.smoothScroll ไปที่ (0,0) เมื่อเรามี listview ด้านข้าง scrollview ในขณะนั้น fullScroll (ScrollView.FOCUS_UP) จะไม่ทำงาน
Kirtikumar A.

1
scroll_view.smoothScrollTo (0,0) ทำงานได้ดีสำหรับฉันมากกว่า mainScrollView.fullScroll (ScrollView.FOCUS_UP); ขอขอบคุณ!
marienke

2
ในอุปกรณ์ส่วนใหญ่ fullScroll (ScrollView.FOCUS_UP) ทำงานได้ แต่บน Nexus 5 และอุปกรณ์ที่ฉันมีขนาดตัวอักษรหันขึ้น - fullSscroll ย้ายไปอยู่ใต้แถบแอ็คชั่น smoothScrollTo (0,0) ทำงานได้ดีขึ้นในทุกอุปกรณ์
jt-gilkeson

นอกจากนี้ยังมีข้อได้เปรียบมากกว่าfullScroll()ในการที่จะช่วยให้รายการที่เลือกยังคงเลือกหลังจากย้าย ด้วยfullScroll()รายการแรกใน scrollview ถูกเลือกใหม่ทุกครั้งในกรณีของฉันโดยไม่ขึ้นกับรายการที่เลือกก่อนที่จะเลื่อนขึ้นด้านบน
GeertVc

97

ฉันมีปัญหาเดียวกันและสิ่งนี้แก้ไขได้ หวังว่ามันจะช่วยคุณ

listView.setFocusable(false);

3
นี่เป็นทางออกที่ถูกต้องสำหรับ gridviews เช่นกัน มันเกิดขึ้นเมื่อคุณมีองค์ประกอบมุมมองมากกว่าหนึ่งองค์ประกอบในกลุ่มมุมมองเดียวกันโดยเฉพาะมุมมองอื่นที่อยู่ด้านบนของรายการหรือมุมมองกริด เนื่องจากอแด็ปเตอร์แจ้งเธรด UI มุมมองจะถูกสร้างขึ้นใหม่และเลื่อนไปจนถึงองค์ประกอบแรก เพียงแค่เรียก listView.setFocusable (false) / gridView.setFocusable (false) หากคุณทำจากไฟล์ xml จะไม่สามารถใช้งานได้
omersem

วิธีการแก้ปัญหานี้ทำงานในกรณีของฉันด้วยฉันมี RecyclerView ภายใน NestedScrollView ดังนั้นมันจึงเลื่อนลงอัตโนมัติ ขอบคุณผู้ชาย!
Nilesh Rathore

ฉันต้องเพิ่มสิ่งนี้ก่อนที่จะตั้งค่าอแด็ปเตอร์ แต่หลังจากนั้นก็ใช้งานได้อย่างมีเสน่ห์ ขอบคุณ
ชุมชน

คำอธิบายที่สมบูรณ์แบบ !!
Borja López

ขอบคุณทั้งมิเกลและโดยเฉพาะอย่างยิ่ง omersem สำหรับคำอธิบายโดยเฉพาะอย่างยิ่งส่วนที่เกี่ยวกับวิธีการทำงานถ้าไม่ได้ตั้งค่าใน XML สิ่งนี้ช่วยให้ฉันปวดหัว
buradd

53

scrollViewObject.fullScroll(ScrollView.FOCUS_UP)สิ่งนี้ใช้ได้ดี แต่ปัญหาของสายนี้คือเมื่อข้อมูลถูกเรียกใช้ใน scrollViewObject จะถูกเรียกใช้ทันที คุณต้องรอเป็นมิลลิวินาทีจนกว่าข้อมูลจะถูกเติม ลองรหัสนี้:

scrollViewObject.postDelayed(new Runnable() {
    @Override
    public void run() {
        scroll.fullScroll(ScrollView.FOCUS_UP);
    }
}, 600);

หรือ

 scrollViewObject.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        scrollViewObject.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        scrollViewObject.fullScroll(View.FOCUS_UP);
    }
});

ฉันกำลังจัดการกับปัญหาเดียวกันกับที่ scrollview ควรจะเลื่อนไปที่ด้านล่างของหน้าแก้ไขมันขึ้นมา!
Machine Tribe

1
แทนที่จะคาดเดาว่า "วิเศษ" x จำนวนมิลลิวินาทีที่คุณต้องรอดูวัตถุเสนอวิธีการโพสต์ (Runnable) คุณสามารถใช้ที่จะโพสต์ runnable เมื่อเครื่องมือแสดงผลบน UI
Ryan

@Ryan: โพสต์ (เรียกใช้) ไม่ได้ผลสำหรับฉันใน Nexus 5 (Genymotion) ทุกครั้ง
Dika

โพสต์ (Runnable) อาจไม่ทำงานเพราะถ้าคุณดึงข้อมูลหลังจากดูขั้นตอนการ infloation เป็นครั้งแรกที่เลื่อนขึ้นใช้งานได้และจากนั้นข้อมูลจะปรากฏในมุมมอง ดังนั้นคุณควรใช้ postDelayed (Runnable, dummyMillis) หรือคุณควรใช้ scroll.fullScroll (ScrollView.FOCUS_UP) หลังจากประมวลผลข้อมูลแล้ว
oguzhan

ทางออกแรกของคุณที่คุณให้มิลลิวินาทีคงที่เป็นวิธีที่ไม่ดี
Malwinder Singh

35

ปัญหาหลักของโซลูชันที่ถูกต้องเหล่านี้คือคุณพยายามเลื่อนขึ้นเมื่อไม่ได้วาดบนหน้าจอ

คุณต้องรอจนกระทั่งหน้าจอเลื่อนดูอยู่บนหน้าจอจากนั้นเลื่อนขึ้นเพื่อแก้ปัญหาใด ๆ เหล่านี้ นี่เป็นวิธีที่ดีกว่าการโพสต์เดย์เนื่องจากคุณไม่คำนึงถึงความล่าช้า

    // Wait until my scrollView is ready
    scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Ready, move up
            scrollView.fullScroll(View.FOCUS_UP);
        }
    });

7
วิธีการแก้ปัญหาที่ดี - อย่าลืมลบผู้ฟังทั่วโลกเมื่อสิ้นสุดonGlobalLayoutวิธีการโทร scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Nilhcem

30

ง่ายมาก

    ScrollView scroll = (ScrollView) findViewById(R.id.addresses_scroll);
    scroll.setFocusableInTouchMode(true);
    scroll.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);

3
สำหรับฉันมันใช้งานไม่ได้ (บรรทัดที่ 3) การแก้ปัญหาคือ: scroll.fullScroll (View.FOCUS_UP); (รวมถึง 2 บรรทัดแรกของคุณ)
medskill

@medskill สวัสดีคุณเขียนสิ่งเหล่านี้ในไฟล์ xml ของคุณหรือไม่ onCreate()ฉันจำหน่ายเครื่องดื่มที่ว่านี้จะทำงานเฉพาะใน
รู้จัก

@ imknownJ.Kimu ทำงานให้ฉันในไฟล์ xml
Paglian

สิ่งนี้ใช้ได้สำหรับฉัน คุณต้องการทั้งบรรทัดที่สองและสาม มันจะไม่ทำงานใน XML สำหรับฉัน
ET

2
ฉันจะจูบคุณถ้าฉันทำได้! ใช้เวลา 1-2 ชั่วโมงกับสิ่งนี้ สิ่งที่ดีที่สุดเมื่อรอให้สองตัวอย่างดูโหลดและไม่ต้องการโฟกัส เพิ่มไปยัง onResume ()
John T

24

ฉันประสบปัญหาเดียวกันเมื่อฉันใช้ Scrollview ภายใน View Flipper หรือ Dialog เคสนั้น scrollViewObject.fullScroll(ScrollView.FOCUS_UP)ส่งคืน false เพื่อให้เคส scrollViewObject.smoothScrollTo(0, 0)นั้นได้ผลสำหรับฉัน

เลื่อนโฟกัสด้านบน


19
 final ScrollView scrollview = (ScrollView)findViewById(R.id.selected_place_layout_scrollview);

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




4
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Ready, move up
        scrollView.fullScroll(View.FOCUS_UP);
    }
});


0
@SuppressWarnings({ "deprecation", "unchecked" })
public void swipeTopToBottom(AppiumDriver<MobileElement> driver) 
                    throws InterruptedException {
       Dimension dimensions = driver.manage().window().getSize();
        Double screenHeightStart = dimensions.getHeight() * 0.30;
        int scrollStart = screenHeightStart.intValue();
        System.out.println("s="+scrollStart);
        Double screenHeightEnd = dimensions.getHeight()*0.90;
        int scrollEnd = screenHeightEnd.intValue();
        driver.swipe(0,scrollStart,0,scrollEnd,2000);
        CommonUtils.threadWait(driver, 3000);
    }

สิ่งนี้จะทำงานได้อย่างแน่นอน
Ajeet Gour

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