Detecteren einde van de ScrollView

Ik heb een app, dat is een Activiteit die gebruik maakt van een ScrollView. Ik nodig hebt om te detecteren wanneer de gebruiker krijgt naar de bodem van de ScrollView. Ik heb een paar googleing en ik vond deze pagina waar wordt uitgelegd. Maar, in het voorbeeld, dat de jongens zich uitstrekt ScrollView. Zoals ik al zei, ik nodig uit te breiden Activiteit.

Dus zei ik: “ok, laten we proberen te maken van een aangepaste klasse die ScrollView, overschrijven de onScrollChanged() methode, op te sporen het einde van de scroll, en dienovereenkomstig te handelen”.

Ik deed, maar in deze lijn:

scroll = (ScrollViewExt) findViewById(R.id.scrollView1);

het gooit een java.lang.ClassCastException. Ik veranderde de <ScrollView> tags in mijn XML-maar, uiteraard, het werkt niet. Mijn vragen zijn: Waarom, als ScrollViewExt breidt ScrollView, gooit mijn gezicht een ClassCastException? is er een manier om te detecteren einde van het scrollen zonder knoeien te veel?

Bedankt mensen.

BEWERKEN:
Zoals beloofd, hier is het stuk van mijn XML zaken:

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


        <WebView
            android:id="@+id/textterms"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center_horizontal"
            android:textColor="@android:color/black" />

    </ScrollView>

Ik veranderde van TextView te WebView te kunnen rechtvaardigen van de tekst aan de binnenzijde. Wat ik wil bereiken is de “knop Accepteren niet activeren totdat de voorwaarden van de opdracht volledig te lezen” ding. Mijn uitgebreide klasse is genoemd ScrollViewExt. Als ik de tag ScrollView voor ScrollViewExt het genereert een

android.view.InflateException: Binary XML file line #44: Error inflating class ScrollViewExt

omdat het niet begrijpen van de tag ScrollViewEx. Ik denk niet dat het een oplossing heeft…

Bedankt voor uw antwoorden!

  • toon ons uw xml-indeling
  • Geen behoefte aan aangepaste klassen of complexe extensies. Gewoon gebruik maken van canScrollVertically(int)
InformationsquelleAutor Fustigador | 2012-04-25



11 Replies
  1. 104

    Deed het!

    Afgezien van de correctie Alexandre wordt u verzocht mij, ik moest het maken van een Interface:

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

    Dan, ik had voor het overschrijven van de OnScrollChanged methode van ScrollView in mijn ScrollViewExt:

    public class ScrollViewExt extends ScrollView {
        private ScrollViewListener scrollViewListener = null;
        public ScrollViewExt(Context context) {
            super(context);
        }
    
        public ScrollViewExt(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public ScrollViewExt(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);
            }
        }
    }

    Nu, als Alexandre zei, zet de naam van het pakket in de XML-tag (mijn schuld), mijn Activity class implementeert de interface gemaakt voor, en dan zet het allemaal samen:

    scroll = (ScrollViewExt) findViewById(R.id.scrollView1);
    scroll.setScrollViewListener(this);

    En in de methode OnScrollChanged, van de interface…

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

    En het werkte!

    Hartelijk dank voor uw hulp, Alexandre!

    • Ik probeer dit te gebruiken in antwoord op mijn aanvraag, en het probleem is -scrollView.getHeight() is altijd gelijk te bekijken.getBottom(), terwijl de scrollView.getScrollY() is altijd 0. Heb je enig idee waarom dat zou kunnen zijn?
    • Bedankt, dat is briljant, want het maakt het maken van pijlen op de bovenkant en de onderkant van de ScrollView en ze te laten verschijnen of verdwijnen afhankelijk van de scrollview het standpunt, dat de gebruiker zich bewust dat er meer items zijn om te zien…
    • Zie dit antwoord te krijgen van de hoogte van een scroll-bekijk de inhoud. stackoverflow.com/questions/3609297/…
    • Ik gebruikte deze logica maar voor HorizontalScrollView, bedankt man!
    • Fantastisch !!! Het werkt… geweldig werk van de mens. 🙂 +1
    • Sinds scrollView heeft slechts één kind view = scrollView.getChildAt(0) en scrollView.getScrollY()==y in uw functie kan de functie worden gewijzigd boven met behulp van deze,eerder dan het openen van redundante gegevens.
    • Briljante werkte als een charme 🙂
    • Ik heb een vraag, ik ben het bijwerken van mijn scrollview dynamisch, dus ik wil niet dat dit op scrollChanged, ik wil om te detecteren of de gebruiker geschoven omhoog (draai autoscroll uit) als de gebruiker scrollt naar beneden tot op de bodem (draai autoscroll op).. Cna iemand helpen aub.
    • Check out deze Ali stackoverflow.com/questions/4414929/…
    • de plaats waar u de interface verklaring van ScrollViewListener?
    • Bedoel je deze?: gaat u = (ScrollViewExt) findViewById(R.-id.scrollView1); scroll.setScrollViewListener(this); Het is alweer een tijdje geleden dat dan, en als ik het me goed herinner, zijn in de activiteit die de scrollview u wilt weten wanneer krijgt de bodem.
    • Uw Weergave-cast is verouderd 🙂
    • Ik heb een interface apart bestand en ik heb scrollview binnen Fragment hoe roep ik het: scrollview.setScrollViewListener(this); ik probeerde scrollview.setScrollViewListener(getactivity()); dit werkt niet.. 🙁 Kunt u uitleggen op wat moet komen?
    • ‘Dit’, omdat de activiteit of het fragment waar je scrollview is voor het implementeren van de interface die u hebt gemaakt, en “dit” verwijst naar zichzelf. Afhankelijk van uw situatie, “dit” kan verwijzen naar andere zaak. Als dat het geval is, probeer dan met nameofyourclass.ScrollViewListener in plaats van “dit”
    • Het lijkt te werken voor het merendeel van de gevallen (dat is, scrollview consumeren ouder hoogte), maar lijkt niet te werken wanneer een andere weergave bestaat onder de scrollview
    • Ik wil meer van deze oplossing: stackoverflow.com/a/37630070/1464013
    • In mijn ervaring, moet u controleren als(diff <= 0)

  2. 56

    Vond ik een eenvoudige manier om te zoeken naar dit :

       scrollView.getViewTreeObserver()
           .addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
                @Override
                public void onScrollChanged() {
                    if (scrollView.getChildAt(0).getBottom()
                         <= (scrollView.getHeight() + scrollView.getScrollY())) {
                        //scroll view is at bottom
                    } else {
                        //scroll view is not at bottom
                    }
                }
            });
    • Hoeft niet te worden aangepast ScrollView.
    • Scrollview kan hosten alleen een rechtstreeks kind, dus scrollView.getChildAt(0) in orde is.
    • Deze oplossing is recht, zelfs de hoogte van de directe kind van ga bekijken is match_parent of wrap_content.
    • Hartelijk dank! Werkt!
    • Mooie oplossing! Bedankt.
    • Om te voorkomen dat bellen onder meerdere keren vervangen door “<=” met “==”
    • Perfect met enkele kleine aanpassingen. 🙂
    • DANK JE, we moeten niet te verlengen ScrollView om zoiets te doen gebruikelijk.
    • Dit dient te worden geaccepteerd antwoord!
    • bedankt man! het is een mooie oplossing

  3. 33

    Al deze antwoorden zijn zo ingewikkeld, maar er is een eenvoudige ingebouwde methode dat dit gebeurt: canScrollVertically(int)

    Bijvoorbeeld:

    @Override
    public void onScrollChanged() {
        if (!scrollView.canScrollVertically(1)) {
            //bottom of scroll view
        }
        if (!scrollView.canScrollVertically(-1)) {
            //top of scroll view
        }
    }

    Dit werkt ook met RecyclerView, ListView, en eigenlijk een andere weergave omdat de methode wordt toegepast op View.

    Als u een horizontale ScrollView, hetzelfde kan worden bereikt met canScrollHorizontally(int)

    • Perfecte antwoord! Getest!
    • echt geholpen.Bedankt!!
    • het moet een GEACCEPTEERD ANTWOORD, het is eenvoudig en werkt perfect
    • Voor de volledigheid, dat is !scrollView.canScrollHorizontally(1) om te controleren of het al bij het juiste eind, en !scrollView.canScrollHorizontally(-1) als het aan de linkerkant.
    • perfecte oplossing!
  4. 16

    Fustigador antwoord was geweldig, maar ik vond sommige toestellen (Zoals Samsung Galaxy Note V) niet bij 0, 2 punt links, na de berekening. Ik stel voor om toe te voegen een beetje buffer, zoals hieronder:

    @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 <= 10) {
            //do stuff
        }
    }
    • Geweldig, man, bedankt voor het toevoegen.
  5. 10

    BEWERKEN

    Met de inhoud van uw XML, ik zie dat u een ScrollView. Als u wilt uw aangepaste weergave, moet u schrijven com.uw.packagename.ScrollViewExt en u zal zitten kundig voor gebruik in uw eigen code.

    <com.your.packagename.ScrollViewExt
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <WebView
            android:id="@+id/textterms"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center_horizontal"
            android:textColor="@android:color/black" />
    
    </com.your.packagename.ScrollViewExt>

    BEWERKEN EIND

    Kon boekt u de xml-inhoud ?

    Ik denk dat je kan gewoon het toevoegen van een scroll luisteraar en controleer of de laatste post liet zien is de nieuwste één van de listview zoals :

    mListView.setOnScrollListener(new OnScrollListener() {      
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            //TODO Auto-generated method stub      
        }
    
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            //TODO Auto-generated method stub
            if(view.getLastVisiblePosition()==(totalItemCount-1)){
                //dosomething
            }
        }
    });
    • Ik doe het morgen, ik ben niet aan het werk nu. Maar ik zie dat je suggereren een ListView. Im niet met behulp van een ListView, op slechts een TextView in een ScrollView.
    • Oh sorry ik was denk van ListView. Zou u plaatst de xm genoemd door setContentViewl met uw eigen mening ?
  6. 4

    Kunt u gebruik maken van de Ondersteuning van de Bibliotheek NestedScrollView en het is NestedScrollView.OnScrollChangeListener interface.

    https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html

    Ook als je de app is gericht op API 23 of hoger, kunt u gebruik maken van de volgende methode op de ScrollView:

    View.setOnScrollChangeListener(OnScrollChangeListener listener) 

    Volg dan het voorbeeld dat @Fustigador beschreven in zijn antwoord. Let er echter op dat het @Wordt beschreven, moet u overwegen het toevoegen van een kleine buffer in het geval dat de gebruiker of het systeem niet in staat zijn om de volledige onderkant van de lijst voor elke reden.

    Ook vermeldenswaard is dat de bladeren veranderen luisteraar wordt soms genoemd worden met negatieve waarden of waarden die groter zijn dan de weergave van de hoogte. Vermoedelijk zijn deze waarden vertegenwoordigen het ‘momentum’ van de scroll-actie. Maar tenzij behandeld adequaat (vloer /abs) ze problemen kunnen veroorzaken voor het detecteren van de scroll-richting als de weergave is verschoven naar de boven-of onderkant van de range.

    https://developer.android.com/reference/android/view/View.html#setOnScrollChangeListener(android.view.View.OnScrollChangeListener)

  7. 3

    Moeten We toevoegen altijd scrollView.getPaddingBottom() overeenkomen met de volledige scrollview hoogte, omdat het enige tijd gaat u uitzicht heeft padding in het xml-bestand dat geval het niet gaat werken.

    scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                if (scrollView != null) {
                   View view = scrollView.getChildAt(scrollView.getChildCount()-1);
                   int diff = (view.getBottom()+scrollView.getPaddingBottom()-(scrollView.getHeight()+scrollView.getScrollY()));
    
              //if diff is zero, then the bottom has been reached
                   if (diff == 0) {
                   //do stuff
                    }
                }
            }
        });
  8. 3
    scrollView = (ScrollView) findViewById(R.id.scrollView);
    
        scrollView.getViewTreeObserver()
                .addOnScrollChangedListener(new 
                ViewTreeObserver.OnScrollChangedListener() {
                    @Override
                    public void onScrollChanged() {
    
                        if (!scrollView.canScrollVertically(1)) {
                            //bottom of scroll view
                        }
                        if (!scrollView.canScrollVertically(-1)) {
                            //top of scroll view
    
    
                        }
                    }
                });
  9. 2

    De meeste antwoorden werkt naast een feit, dat wanneer u naar de onderkant, luisteraar wordt geactiveerd meerdere malen, wat in mijn geval ongewenste. Om dit te voorkomen heb ik toegevoegd vlag scrollPositionChanged dat controleert of scroll positie veranderde zelfs voor de aanroep van de methode weer.

    public class EndDetectingScrollView extends ScrollView {
        private boolean scrollPositionChanged = true;
    
        private ScrollEndingListener scrollEndingListener;
    
        public interface ScrollEndingListener {
            void onScrolledToEnd();
        }
    
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
    
            View view = this.getChildAt(this.getChildCount() - 1);
            int diff = (view.getBottom() - (this.getHeight() + this.getScrollY()));
            if (diff <= 0) {
                if (scrollPositionChanged) {
                    scrollPositionChanged = false;
                    if (scrollEndingListener != null) {
                        scrollEndingListener.onScrolledToEnd();
                    }
                }
            } else {
                scrollPositionChanged = true;
            }
        }
    
        public void setScrollEndingListener(ScrollEndingListener scrollEndingListener) {
            this.scrollEndingListener = scrollEndingListener;
        }
    }

    Dan gewoon luisteraar

    scrollView.setScrollEndingListener(new EndDetectingScrollView.ScrollEndingListener() {
        @Override
        public void onScrolledToEnd() {
            //do your stuff here    
        }
    });

    Je kan hetzelfde doen als u doen als

    scrollView.getViewTreeObserver().addOnScrollChangedListener(...)

    maar je moet vlag van klasse je het toevoegen van dit luisteraar.

    • Leuk! Werkt goed voor pre-API level 23 !
  10. 1

    Om te bepalen of u aan het einde van uw aangepaste ScrollView u kan ook gebruik maken van een van de variabele en het opslaan van de laatste y-positie. Vervolgens kunt u vergelijken met de laatste y-positie met de huidige scroll-positie.

    private int scrollViewPos;
    
    ...
    
    @Override
    public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
    
       //reached end of scrollview
       if (y > 0 && scrollViewPos == y){
          //do something
       }
    
       scrollViewPos = y;
    }
  11. 0

    Ik wilde tonen/verbergen van een FAB met een offset voor de onderkant van de scrollview. Dit is de oplossing die ik bedacht (Kotlin):

    scrollview.viewTreeObserver.addOnScrollChangedListener {
        if (scrollview.scrollY < scrollview.getChildAt(0).bottom - scrollview.height - offset) {
            //fab.hide()
        } else {
            //fab.show()
        }
    }

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *