Disabilitare ScrollView a livello di programmazione?


108

Vorrei abilitare ScrollView e disabilitarlo con un clic del pulsante.
Disabilitare significa come se ScrollView non fosse presente .. e abilitarlo restituisce ScrollView.

Lo voglio perché ho una galleria con immagini di testo e su un pulsante fai clic sull'orientamento dello schermo cambia, quindi in Orizzontale il testo diventa più grande. E voglio ScrollView in modo che l'immagine non si allunghi e il testo diventi illeggibile.

scrollview.Enabled=false / setVisibility(false) non fa niente.

xml:

<ScrollView 
android:id="@+id/QuranGalleryScrollView" 
android:layout_height="fill_parent" 
android:layout_width="fill_parent">
<Gallery android:id="@+id/Gallery" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent"
android:scrollbars="horizontal"></Gallery>
</ScrollView>

Grazie

Edit1: non posso usare Visibility (andato) poiché ciò nasconderebbe anche la Gallery, quello che voglio è nascondere l'effetto di ScrollView. Quando è presente ScrollView, le immagini nella Galleria diventano scorrevoli e non si adattano allo schermo, quindi devi scorrere per vedere l'intera immagine, non voglio disabilitarla / abilitarla con un clic del pulsante.

Ho provato questo:

((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);
                        ((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setHorizontalScrollBarEnabled(false);
                        ((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setVerticalScrollBarEnabled(false);
                        ((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setEnabled(false);

Ma le immagini nella Galleria sono comunque scorrevoli e non si adattano allo schermo .. qual è la soluzione a questo?

Risposte:


187

Diversi punti per cominciare:

  1. Non è possibile disabilitare lo scorrimento di una ScrollView. Dovresti estendere a ScrollView e sovrascrivere il onTouchEventmetodo per tornare falsequando viene soddisfatta una condizione.
  2. Il componente Gallery scorre orizzontalmente indipendentemente dal fatto che sia in ScrollView o meno: ScrollView fornisce solo lo scorrimento verticale (è necessario un HorizontalScrollView per lo scorrimento orizzontale)
  3. Sembra che tu dica di avere un problema con lo stiramento dell'immagine stessa - questo non ha nulla a che fare con ScrollView, puoi cambiare il modo in cui un ImageView scala con la android:scaleTypeproprietà (XML) o il setScaleTypemetodo - per esempio ScaleType.CENTERnon allungherà la tua immagine e lo farà centralo nella sua dimensione originale

È possibile modificare ScrollViewcome segue per disabilitare lo scorrimento

class LockableScrollView extends ScrollView {

    ...

    // true if we can scroll (not locked)
    // false if we cannot scroll (locked)
    private boolean mScrollable = true;

    public void setScrollingEnabled(boolean enabled) {
        mScrollable = enabled;
    }

    public boolean isScrollable() {
        return mScrollable;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // if we can scroll pass the event to the superclass
                return mScrollable && super.onTouchEvent(ev);
            default:
                return super.onTouchEvent(ev);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // Don't do anything with intercepted touch events if
        // we are not scrollable
        return mScrollable && super.onInterceptTouchEvent(ev);
    }

}

Dovresti quindi usare

<com.mypackagename.LockableScrollView 
    android:id="@+id/QuranGalleryScrollView" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent">

    <Gallery android:id="@+id/Gallery" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:scrollbars="horizontal">
    </Gallery>

</com.mypackagename.LockableScrollView>

nel tuo file XML (appena cambiato il ScrollViewnel tuo speciale LockableScrollView).

Allora chiama

((LockableScrollView)findViewById(R.id.QuranGalleryScrollView)).setScrollingEnabled(false);

per disabilitare lo scorrimento della vista.

Penso che tu abbia più del semplice problema di disabilitare lo scorrimento per ottenere il risultato desiderato (la galleria rimarrà scorrevole con il codice sopra per esempio) - Ti consiglio di fare qualche ricerca in più su ciascuno dei tre componenti (Galleria, ScrollView, ImageView) per vedere quali proprietà possiede ciascuno e come si comporta.


Ecco come appare la classe: pastebin.com/dsWSWR4x Ma ottengo l'errore "Il metodo onTouch (View, MotionEvent) di tipo LockableScrollView deve sovrascrivere o implementare un metodo supertype"
Omar

Mi scuso, ho corretto gli errori nel mio codice - avrebbe dovuto essereonTouchEvent(MotionEvent ev)
Joseph Earl

1
Ok ora il codice è conforme, anche se quando eseguo l'app si blocca ... e quando rimuovo questa classe e restituisco il <ScrollView invece della tua classe l'app funziona bene!
Omar

Ciao Omar potresti postare l'errore che ottieni? Assicurati di cambiare com.mypackagename in <com.mypackagename.LockableScrollView> con il tuo personale
Joseph Earl,

1
Buona risposta. Se cambi case MotionEvent.ACTION_DOWN: in case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: sarai anche in grado di disabilitare lo scorrimento anche durante il trascinamento. Ma è ovviamente su tutti come deve usarlo.
Luky

70

Ero andato da questa parte:

        scrollView.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            return isBlockedScrollView;
        }
    });

3
Semplice e funziona alla grande. Il punto chiave è utilizzare una variabile (ad esempio, isBlockedScrollView) per controllare quando si desidera abilitare lo scorrimento. Impostalo su true quando lo scorrimento dovrebbe essere consentito e false in caso contrario.
PeteH

5
@PeteH, non ho idea del perché, ma il mio ListViewfunziona in modo opposto: vero quando lo scorrimento è disabilitato e falso quando è abilitato.
Machado

@Holmes: hai ragione, vero quando vuoi bloccare lo scorrimento
Lily

1
Funziona magnificamente Inoltre, ho visualizzazioni bambini (pulsanti) all'interno della visualizzazione a scorrimento e posso ancora interagire con loro nonostante non sovrascriva onInterceptTouchEvent ()! Soluzione elegante.
Cody

1
@Machado Il motivo per cui devi restituire true per bloccare lo scorrimento è perché l'ascoltatore tattile prende il valore booleano restituito per determinare se l'evento tocco deve essere consumato o meno. Se restituisci false, la visualizzazione a scorrimento procederà quindi a passare l'evento di tocco al suo ascoltatore di scorrimento.
Vince

11

Ho trovato questa semplice soluzione appena impostata

ScrollView.requestDisallowInterceptTouchEvent(true);

5
requestDisallowInterceptTouchEventfunziona solo per il figlio della vista da bloccare. Quindi sarebbe più comemLinearLayout.requestDisallowInterceptTouchEvent(true);
Muz

6

Disabilita ScrollView

ScrollView sw = (ScrollView) findViewById(R.id.scrollView1);
sw.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return true;
    }
});

5

per iniziare, ho utilizzato il codice pubblicato nel primo commento ma l'ho modificato in questo modo:

    public class LockableScrollView extends ScrollView {

    public LockableScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }
    public LockableScrollView(Context context, AttributeSet attrs) 
    {
        super(context, attrs);
    }

    public LockableScrollView(Context context) 
    {
        super(context);
    }

    // true if we can scroll (not locked)
    // false if we cannot scroll (locked)
    private boolean mScrollable = true;

    public void setScrollingEnabled(boolean enabled) {
        mScrollable = enabled;
    }

    public boolean isScrollable() {
        return mScrollable;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // if we can scroll pass the event to the superclass
                if (mScrollable) return super.onTouchEvent(ev);
                // only continue to handle the touch event if scrolling enabled
                return mScrollable; // mScrollable is always false at this point
            default:
                return super.onTouchEvent(ev);
        }
    }



@Override  
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {     
    case MotionEvent.ACTION_DOWN:         
        // if we can scroll pass the event to the superclass      
        if (mScrollable) return super.onInterceptTouchEvent(ev);      
        // only continue to handle the touch event if scrolling enabled    
        return mScrollable; // mScrollable is always false at this point     
        default:          
            return super.onInterceptTouchEvent(ev);      
            }
    }

}

poi l'ho chiamato in questo modo

((LockableScrollView)findViewById(R.id.scrollV)).setScrollingEnabled(false);

perché ho provato

((LockableScrollView)findViewById(R.id.scrollV)).setIsScrollable(false);

ma ha detto che setIsScrollable non è definito

spero che questo ti possa aiutare


Nota: i primi due costruttori sono necessari se il tuo ScrollViewè il contenitore di layout principale della tua classe di layout.
actaram

Se tocchi un pulsante o qualcos'altro che intercetta prima i tocchi, la visualizzazione a scorrimento continuerà a scorrere
Cristi Băluță

3

Ecco una soluzione più semplice. Sostituisci il onTouch()per ScrollView OnTouchListenere restituisci false se desideri ignorare lo scorrimento al tocco. Lo scorrimento programmatico funziona ancora e non è necessario estendere la ScrollViewclasse.

mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
  return isScrollable;
}
});

1
! isScrollable poiché il valore restituito true significa che l'evento è stato intercettato.
goRGon

3

Non ho abbastanza punti per commentare una risposta, ma volevo dire che la risposta di mikec ha funzionato per me tranne che ho dovuto cambiarla per tornare! IsScrollable in questo modo:

mScroller.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return !isScrollable;
    }
});

1
@Override  
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {     
    case MotionEvent.ACTION_DOWN:         
        // if we can scroll pass the event to the superclass      
        if (mScrollable) return super.onInterceptTouchEvent(ev);      
        // only continue to handle the touch event if scrolling enabled    
        return mScrollable; // mScrollable is always false at this point     
        default:          
            return super.onInterceptTouchEvent(ev);      
            }
    }

1

@JosephEarl +1 Qui ha un'ottima soluzione che ha funzionato perfettamente per me con alcune piccole modifiche per farlo in modo programmatico.


Ecco le modifiche minori che ho apportato:

Classe LockableScrollView:

public boolean setScrollingEnabled(boolean enabled) {
    mScrollable = enabled;
    return mScrollable;
}

Attività principale:

LockableScrollView sv;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    sv = new LockableScrollView(this);
    sv.setScrollingEnabled(false);
}

1

Avevo un layout su NestedScrollView che consumava l'evento touch e disabilitava lo scorrimento:

progressBarLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;
            }
        });

e per abilitare:

progressBarLayout.setOnTouchListener(null);

1

È possibile creare un CustomScrollView, per il quale è possibile disabilitare la sua interferenza con altre visualizzazioni. Anche se a volte questo può essere irritante per l'utente finale. Usalo con cautela.

Questo è il codice:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewParent;

public class CustomScrollView extends android.widget.ScrollView {

    public CustomScrollView(Context context) {
        super(context);
    }

    public CustomScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev)
    {
        /* Prevent parent controls from stealing our events once we've gotten a touch down */
        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN)
        {
            ViewParent p = getParent();
            if (p != null)
                p.requestDisallowInterceptTouchEvent(true);
        }

        return false;
    }
}

Come utilizzare CustomScrollView?

Puoi aggiungere CustomScrollView come genitore allo schermo in cui vuoi aggiungere un altro Scrollview come visualizzazione figlio e l'intero schermo è scorrevole. L'ho usato per un RelativeLayout.

<?xml version="1.0" encoding="utf-8"?>
<**package.**CustomScrollView 
xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/some_id"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:tools="http://schemas.android.com/tools">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    #**Inside this I had a TableLayout and TableRow. Inside the TableRow,**
    #**I had a TextView which I made scrollable from Java Code.**
    #**textView.setMovementMethod(new ScrollingMovementMethod());**
    </RelativeLayout>
</ankit.inventory.ankitarora.inventorymanagementsimple.CustomScrollView>

Ha funzionato per il mio caso.


1
public class LockableScrollView extends ScrollView {

    private boolean mScrollable = true;

    public LockableScrollView(Context context) {
        super(context);
    }

    public LockableScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public LockableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public LockableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public void setScrollable(boolean enabled) {
        mScrollable = enabled;
    }

    public boolean isScrollable() {
        return mScrollable;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return mScrollable && super.onTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mScrollable && super.onInterceptTouchEvent(ev);
    }
}

0

questo aiuta?

((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);

1
Non penso che abbia fatto alcuna differenza, ho ancora lo stesso problema
Omar

0

Puoi estendere la galleria e utilizzare alcuni flag per disabilitare lo scorrimento quando vuoi:

public class MyGallery extends Gallery {

public boolean canScroll;

public MyGallery(Context context, AttributeSet attrs) {
    canScroll = true;
    super(context, attrs);
}

public void setCanScroll(boolean flag)
{
    canScroll = flag;
}

@Override
public boolean onScroll(android.view.MotionEvent e1, android.view.MotionEvent e2, float distanceX, float distanceY) {
    if (canScroll)
        return super.onScroll(e1,e2,distancex,distancey);
    else
        return false;
}

@Override
public boolean onSingleTapUp(MotionEvent e)
{
    if (canScroll)
        return super.onSingleTapUp(ey);
    else
        return false;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
    if (canScroll)
        return super.onFling(e1,e2,velocityX,velocityY);
    else
        return false;
}
}

-3

Come puoi vedere nella documentazione , non puoi impostare la visibilità su false. Nel tuo caso dovresti probabilmente usare:

scrollview.setVisibility(Visibility.GONE);

2
Questo nasconderà anche la Galleria quindi non è la soluzione, ho modificato il post con maggiori dettagli
Omar

-6

sull'ascoltatore clic del pulsante basta fare

ScrollView sView = (ScrollView)findViewById(R.id.ScrollView01);

sView.setVerticalScrollBarEnabled(false);
sView.setHorizontalScrollBarEnabled(false);

in modo che la barra di scorrimento non sia abilitata al clic del pulsante


2
Questo nasconde solo le barre immagino .. ma non l'effetto dello scrollview
Omar

1
non ti permetterà di scorrere, inoltre non nasconderà la visualizzazione della galleria
Sumant
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.