Android: ScrollView kuvveti alta


200

Bir ScrollView en alttan başlamak istiyorum. Herhangi bir yöntem var mı?


1
Bence onun sadece scrollTo (), evet ben sadece ScrollView için dev dokümanlar kontrol. Tereyağından kıl çeker gibi.
Noah Seidman

Yanıtlar:


278

scroll.fullScroll(View.FOCUS_DOWN) ayrıca çalışması gerekir.

Bunu bir scroll.Post(Runnable run)

Kotlin Kodu

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

6
Bu hiçbir şey yapmıyor gibi görünüyor, herhangi bir öneri? Ben onCreate ve daha sonra onClick bir düğmeye denedim.
RichardJohnn

Yön değiştirmede işe yaramıyor gibi görünüyor. Aksi halde çalışır.
Prashant

1
Düzen boyutu çağrılmadan hemen önce değiştiyse bu çalışmaz. Bunun yerine gönderilmesi gerekiyor.
MLProgrammer-CiM

2
Bu ve aşağıda, tamamen şişirmek için görünüme zaman verene kadar çalışmaz, sadece ademar cevabını basitleştirir. scrollView.postDelayed (new Runnable () {@Over public void run () üzerine atla {scrollView.fullScroll (View.FOCUS_UP // Veya Aşağı);}}, 1000);
EngineSense

scroll.fullScroll (View.FOCUS_DOWN) odak değişikliğine yol açar. Birden fazla odaklanabilir görünüm olduğunda, örneğin iki EditText olduğunda, bu garip bir davranış getirecektir. Altta verdiğim başka bir çözümü kontrol edin.
barış anlayışı

333

scroll.post içindeki kodu şu şekilde çalıştırmalısınız:

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

4
Odak mevcut elemanını kaybetmeden bir yolu var, bunu yaptığımda mevcut elemanımın odağını kaybediyorum (
scrollview'dan

2
Bu yalnızca mizanpajın henüz ölçülmediği ve düzenlenmediği durumlarda gereklidir (örneğin, onCreate'de çalıştırırsanız). Bir düğmeye basmak gibi durumlarda .post () gerekmez.
Patrick Boos

12
ScrollView'a odaklanmak istemiyorsanız scroll.scrollTo(0, scroll.getHeight());, aşağıya atlamak veya scroll.smoothScrollTo(0, scroll.getHeight());daha yumuşak bir kaydırma için kullanabilirsiniz
yuval

Bu kod olası bir bellek sızıntısı değil mi? Bir aktivite (kaydırma) görünümüne referans tutan anonim bir Runnable oluşturulur. Eğer runnable görevini yerine getirirken aktivite yok edilirse, kaydırma görüntüsüne bir referans sızdırır, değil mi?
Jenever

Kotlin'de:scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
Albert Vila Calvo

95

scroll.fullScroll(View.FOCUS_DOWN)odak değişikliğine yol açacaktır. Birden fazla odaklanabilir görünüm olduğunda, örneğin iki EditText olduğunda bu garip bir davranış getirecektir. Bu sorunun başka bir yolu daha var.

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

Bu iyi çalışıyor.

Kotlin Uzantısı

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

Çok memnunum bu konuda daha fazla zaman harcamak zorunda kalmadım. Tam ihtiyacım olan şey
Alexandre G

6
Bunun daha fazla oyu olmalı. Bu en iyi cevap.
Eric Lange

1
Burada bulunan en iyi cevap bu.
geçersiz işaretçi

1
Bu sayfadaki her şeyi, hatta bunun altındaki şeyleri bile denedim. Bu işe yarayan tek şeydi ve EditText'imin odağını kaybetmesine neden olmuyor. Teşekkür ederim.
Joel

Klavye gösterilirken aşağı kaydırmanız gerekiyorsa, bu kodu bu kitaplıkla birleştirin . Tıkır tıkır çalışıyor.
wonsuc

48

Bazen scrollView.post çalışmıyor

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

AMA scrollView.postDelayed kullanıyorsanız kesinlikle işe yarar

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

kimlik için teşekkürler. postDelayed daha iyi bir çözümdür.
Prashant

@Prashant :) :) :)
Ajay Shrestha

1
Aktiviteyi bitirdiğinizde Runnable'ınızı atmanız gerektiğini unutmayın
FabioR

38

Benim için en iyi olan şey

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

Bunu denedim, ama buradaki algoritma yanlış. Cevabımı aşağıdan kontrol edin lütfen.
barış anlayışı

28

Mükemmel çalışmayı artırıyorum.

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

Not

Bu cevap, android'in gerçekten eski sürümleri için bir çözümdür. Bugün postDelayedartık bu hata var ve kullanmalısınız.


3
İkiden fazla değil, ancak bu benim telefonumda iyi çalışıyor (LG JellyBean 4.1.2 Optimus G).
Youngjae

9
Neden scrollView.postDelayed (runnable, 100) kullanmıyorsunuz?
Matt Wolfe

1
@MattWolfe zamanın bazı eski android sürümlerinde çalışmadı. Ancak bugün bu cevap hiç reddedildi.
ademar111190

4
Tanrı sevgisi için scrollView.postDelayed (runnable, 100) kullanın! :)
Alex Lockwood

1
@AlexLockwood bir not ekledim Umarım insanlar postDelayed:) kullanın
ademar111190

4

bunu başarılı bir şekilde denedim.

scrollView.postDelayed(new Runnable() {
    @Override
    public void run() {
        scrollView.smoothScrollTo(0, scrollView.getHeight());
    }
}, 1000);

3

Görünüm henüz yüklenmediğinde kaydırma yapamazsınız. Yukarıdaki gibi bir posta veya uyku çağrısı ile 'daha sonra' yapabilirsiniz, ancak bu çok zarif değil.

Kaydı planlamak ve sonraki onLayout () öğesinde yapmak daha iyidir. Örnek kod burada:

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


3

Dikkate alınması gereken bir şey, ne ayarlanmayacağıdır. Alt denetimlerinizin, özellikle EditText denetimlerinin, RequestFocus özelliğinin ayarlanmadığından emin olun. Bu, mizanpajdaki en son yorumlanan özelliklerden biri olabilir ve ebeveynlerindeki yerçekimi ayarlarını geçersiz kılar (mizanpaj veya ScrollView).


3

Aşağıya kaydırmanın diğer yolları

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

kullanma

Önceden düzenlenmiş olan kaydırma görüntünüz varsa

my_scroll_view.scrollToBottom()

Kaydırma görünümünüz tamamlanmadıysa (ör. Etkinlik onCreateyönteminde en alta kaydırırsınız ...)

my_scroll_view.post { 
   my_scroll_view.scrollToBottom()          
}

1

Tam olarak sorunun cevabı değil, ama bir EditText odaklanır ulaşmaz aşağı kaydırmak gerekiyordu. Ancak kabul edilen cevap ET'nin de odağı hemen kaybetmesini sağlayacaktır (sanırım ScrollView'a göre).

Geçici çözümüm şuydu:

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

Aslında fullScroll'u iki kez çağırmanın hile yaptığını gördüm:

myScrollView.fullScroll(View.FOCUS_DOWN);

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

İlk (başarısız) kaydırma yapıldıktan hemen sonra post () yönteminin etkinleştirilmesiyle ilgili olabilir. Bu davranış, myScrollView önceki bir yöntem çağrısından sonra oluşur, bu yüzden ilk fullScroll () yöntemini sizinle ilgili başka bir şeyle değiştirmeyi deneyebilirsiniz.


0

Kotlin coroutines ile bunu yapmanın başka bir harika yolu var. Runnable (post / postDelayed) ile bir Handler'a karşı koroutin kullanmanın avantajı, gecikmeli bir eylem gerçekleştirmek için pahalı bir iş parçacığını ateşlememesidir.

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

Coroutine HandlerContext'i UI olarak belirtmek önemlidir, aksi takdirde gecikmeli eylem UI iş parçacığından çağrılamayabilir.


0

Bu durumda sadece scroll.scrollTo (0, sc.getBottom ()) kullanmıyorsanız, scroll.post kullanarak kullanın

Misal:

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


0

Bu anında çalışır . Gecikmesiz.

// wait for the scroll view to be laid out
scrollView.post(new Runnable() {
  public void run() {
    // then wait for the child of the scroll view (normally a LinearLayout) to be laid out
    scrollView.getChildAt(0).post(new Runnable() {
      public void run() {
        // finally scroll without animation
        scrollView.scrollTo(0, scrollView.getBottom());
      }
    }
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.