Come scorrere fino alla cima del layout lungo ScrollView?


162

Per parte della mia app, all'utente viene presentato un elenco di nomi e viene chiesto di raggrupparli come meglio crede.

(Nota, il codice ListView è stato copiato alla lettera dal tutorial di Android Views. Non l'ho ancora personalizzato in base alle mie esigenze, sto solo cercando di capire come farlo funzionare.)

Il layout di base è un LinearLayout, contenente un ScrollView (chiamato "groupsScrollView" nel codice seguente), contenente un RelativeLayout. Ho alcuni pulsanti e testo, e poi il mio ListView sotto quello, che mostra l'elenco dei nomi. Tutto questo è più alto dell'area dello schermo visibile, quindi all'utente è consentito scorrere verticalmente per vedere tutto.

Tutto funziona magnificamente, tranne quando la pagina viene caricata è sempre pre-scrollata all'inizio del mio ListView - al centro della pagina. Il testo e i pulsanti che ho creato che indicano all'utente cosa fare non sono visibili.

Posso afferrare lo schermo e scorrere verso l'alto, che funziona bene, ma vorrei che lo schermo si caricasse essendo già stato fatto scorrere verso l'alto. L'utente non dovrebbe scorrere verso SU per vedere la parte superiore di una pagina appena caricata. Ma tutto ciò che ho provato a scorrere programmaticamente nella parte superiore dello schermo non è riuscito.

Ecco il mio metodo 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();
        }
      });
}

La riga "mainScrollView.pageScroll (View.FOCUS_UP); è il problema. Non causa un errore, ma non sembra fare nulla. Ho provato scrollTo (0,0), scrollDirection (View.FOCUS_UP ) e tutto ciò a cui riesco a pensare.

Dal momento che non ricevo un errore, devo presumere che questi comandi di scorrimento stiano effettivamente funzionando, ma che stiano scorrendo verso la parte superiore di ListView, anziché verso la parte superiore di ScrollView o RelativeLayout che lo contiene. Ciò sembra essere confermato dalla descrizione di Google del metodo scrollTo (int x, int y) in cui si dice "Questa versione blocca anche lo scorrimento fino ai limiti di nostro figlio".

Quindi, per rendere ancora più lunga una lunga domanda, come faccio a caricare un sacco di visualizzazioni sullo schermo contenuto in uno ScrollView, e quindi scorrere a livello di codice l'intera cosa nella parte superiore della pagina in modo che l'utente possa interagire con essa?

Grazie!

Risposte:


264

Provare

mainScrollView.fullScroll(ScrollView.FOCUS_UP);

dovrebbe funzionare.


Funziona anche per me. : D
Muntasir Aonik,

1
Ho trovato ScrollView # fullScroll () cambiare lo stato attivo attuale. Ho provato con EditText.
illusionJJ

175

Aveva lo stesso problema, probabilmente una specie di bug.

Persino fullScroll(ScrollView.FOCUS_UP)dall'altra risposta non ha funzionato.
L'unica cosa che ha funzionato per me era chiamare scroll_view.smoothScrollTo(0,0)subito dopo la visualizzazione della finestra di dialogo.


Inizialmente ha funzionato, ma in seguito, quando ho provato a farlo ancora e ancora, questo approccio non ha dato risultati soddisfacenti.
JaydeepW,

16
risolvo da scroll_view.smoothScrollTo (0,0), quando abbiamo listview a lato la scrollview in quel momento fullScroll (ScrollView.FOCUS_UP) non funzionerà.
Kirtikumar A.

1
scroll_view.smoothScrollTo (0,0) ha funzionato meglio per me rispetto a mainScrollView.fullScroll (ScrollView.FOCUS_UP); GRAZIE!
marienke,

2
Sulla maggior parte dei dispositivi fullScroll (ScrollView.FOCUS_UP) ha funzionato, ma sul Nexus 5 e sui dispositivi in ​​cui avevo la dimensione del testo invertita: fullSscroll si spostava sotto la barra delle azioni, smoothScrollTo (0,0) funzionava meglio su tutti i dispositivi.
jt-gilkeson,

Ciò ha anche il vantaggio fullScroll()di mantenere l'elemento selezionato ancora selezionato dopo lo spostamento. Con fullScroll(), il primo elemento nella vista di scorrimento è stato nuovamente selezionato ogni volta nel mio caso, indipendentemente dall'elemento selezionato prima che lo scorrimento si spostasse verso l'alto.
GeertVc,

97

ho avuto lo stesso problema e questo è stato risolto. Spero che ti aiuti.

listView.setFocusable(false);

3
Questa è la soluzione corretta anche per le visualizzazioni griglia. Succede quando si hanno più di una vista nello stesso gruppo di vista, specialmente un'altra vista elenco in cima alla lista o vista griglia. Poiché l'adattatore notifica il thread dell'interfaccia utente, la vista viene ricreata e scorre fino al primo elemento. Basta chiamare listView.setFocusable (false) / gridView.setFocusable (false). Se lo fai dal file xml, tuttavia non funzionerà.
Omersem,

Questa soluzione ha funzionato anche nel mio caso, avevo RecyclerView all'interno di NestedScrollView, quindi scorreva automaticamente verso il basso. Grazie uomo!
Nilesh Rathore,

Ho dovuto aggiungere questo prima di impostare l'adattatore, ma dopo funziona come un incantesimo. Grazie
Community

spiegazione perfetta !!
Borja López,

Grazie a Miguel e in particolare a Omersem per la spiegazione, in particolare la parte su come non funzionerà se impostato in XML, questo mi ha risparmiato un po 'di mal di testa
buradd

53

scrollViewObject.fullScroll(ScrollView.FOCUS_UP)funziona benissimo, ma solo il problema con questa linea è che, quando i dati vengono popolati in scrollViewObject, è stato chiamato immediatamente. Devi attendere alcuni millisecondi fino a quando i dati non vengono popolati. Prova questo codice:

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

O

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

Stavo affrontando lo stesso problema in cui si supponeva che la vista di scorrimento scorresse fino alla fine della pagina, risolto proprio in alto!
Machine Tribe,

1
Invece di indovinare il "magico" x numero di millisecondi che dovresti aspettare, Visualizza gli oggetti offre un metodo post (Runnable) che potresti usare che pubblicherà il runnable una volta eseguito il rendering del widget sull'IU.
Ryan

@Ryan: post (Runnable) non funziona sempre per me su Nexus 5 (Genymotion)
Dika,

post (eseguibile) potrebbe non funzionare perché se si recuperano i dati dopo il passaggio di visualizzazione della vista, poiché il primo scorrimento verso l'alto funziona e i dati vengono popolati alla vista. Quindi o dovresti usare postDelayed (Runnable, dummyMillis) o dovresti usare scroll.fullScroll (ScrollView.FOCUS_UP) dopo i processi popolati di dati.
Oguzhan,

La tua prima soluzione in cui dai millis statici è un cattivo approccio.
Malwinder Singh,

35

Il problema principale di tutte queste soluzioni valide è che stai provando a spostare verso l'alto lo scorrimento quando non è ancora disegnato sullo schermo.

È necessario attendere che la vista di scorrimento sia sullo schermo, quindi spostarla verso l'alto con una di queste soluzioni. Questa è la soluzione migliore di un post-ritardo, perché non ti dispiace per il ritardo.

    // 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
Bella soluzione - Non dimenticare di rimuovere il listener globale alla fine della onGlobalLayoutchiamata del metodo scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Nilhcem,

30

Molto facile

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

3
per me non ha funzionato (la terza riga), la soluzione era: scroll.fullScroll (View.FOCUS_UP); (con l'inclusione delle prime 2 righe)
medskill

@medskill, Ciao, hai scritto questi nel tuo file XML? Ho trovato che questo funziona solo in onCreate().
noto il

@ imknownJ.Kimu Funziona per me nel file xml
Paglian,

Questo ha funzionato per me. Hai bisogno sia della seconda che della terza riga. Non funzionerebbe nell'XML per me.
ET,

2
Ti bacerei se potessi! Abbiamo trascorso 1-2 ore su questo. Il migliore in attesa del caricamento di due visualizzazioni elenco e non ha voluto concentrarsi su di esse. Aggiunto a onResume ().
John T,

24

Ho riscontrato lo stesso problema quando sto usando Scrollview all'interno di View Flipper o Dialog quel caso scrollViewObject.fullScroll(ScrollView.FOCUS_UP)restituisce false in modo che il caso scrollViewObject.smoothScrollTo(0, 0)funzioni per me

Scorri il fuoco in alto


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

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

9
runOnUiThread( new Runnable(){
   @Override
   public void run(){
      mainScrollView.fullScroll(ScrollView.FOCUS_UP);
   }
}

9

Questo ha funzionato per me

scroll_view.smoothScrollTo(0,0); // scroll to top of screen

6

Questo è force scroll per scrollview :

            scrollView.post(new Runnable() {
                @Override
                public void run() {
                    scrollView.scrollTo(0, 0);
                    scrollView.pageScroll(View.FOCUS_UP);
                    scrollView.smoothScrollTo(0,0);
                }
            });

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

1

Ho risolto il mio problema in Kotlin in questo modo:

scrollview.isFocusableInTouchMode = true
scrollview.fullScroll(View.FOCUS_UP)
scrollview.smoothScrollTo(0,0)

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

questo funzionerà di sicuro,
Ajeet Gour, il

Fornire una breve spiegazione di come questa risposta risolva il problema.
Ayberk Özgür,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.