110 votes

Désactiver ScrollView de manière programmatique ?

Je voudrais activer le ScrollView et le désactiver par un clic sur un bouton.
Désactiver signifie comme si le ScrollView n'était pas là, et activer renvoie le ScrollView.

C'est ce que je veux car j'ai une galerie avec des images de texte, et lorsqu'on clique sur un bouton, l'orientation de l'écran change, de sorte qu'en mode paysage, le texte devient plus grand. Et je veux le ScrollView pour que l'image ne s'étire pas et que le texte ne devienne pas illisible.

scrollview.Enabled=false / setVisibility(false) ne fait rien.

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>

Je ne peux pas utiliser Visibilité (disparue) car cela cacherait également la Galerie, ce que je veux c'est cacher l'effet du ScrollView. Lorsqu'il y a un ScrollView, les images de la Galerie deviennent défilables et ne tiennent pas dans l'écran, de sorte que vous devez faire défiler l'image pour la voir en entier. Je ne veux pas désactiver/activer cela en cliquant sur un bouton.

J'ai essayé ça :

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

Mais les images de la galerie peuvent toujours défiler et ne sont pas adaptées à l'écran. Quelle est la solution à ce problème ?

195voto

Joseph Earl Points 11953

Plusieurs points pour commencer :

  1. Vous ne pouvez pas désactiver le défilement d'un ScrollView. Vous devez étendre le ScrollView et remplacer l'attribut onTouchEvent pour retourner false lorsque certaines conditions sont remplies.
  2. Le composant Galerie défile horizontalement, qu'il se trouve ou non dans un ScrollView - un ScrollView ne permet qu'un défilement vertical (vous avez besoin d'un HorizontalScrollView pour un défilement horizontal).
  3. Vous semblez dire que vous avez un problème avec l'étirement de l'image elle-même -- cela n'a rien à voir avec le ScrollView, vous pouvez changer la façon dont une ImageView s'échelonne avec la fonction android:scaleType (XML) ou la propriété setScaleType méthode - par exemple ScaleType.CENTER n'étirera pas votre image et la centrera à sa taille originale.

Vous pourriez modifier ScrollView comme suit pour désactiver le défilement

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

}

Vous utiliserez alors

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

dans votre fichier XML (il suffit de changer le ScrollView à votre spécial LockableScrollView ).

Ensuite, appelez

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

pour désactiver le défilement de la vue.

Je pense qu'il ne suffit pas de désactiver le défilement pour obtenir le résultat souhaité (la galerie restera déroulante avec le code ci-dessus par exemple) - je vous recommande de faire des recherches plus approfondies sur chacun des trois composants (Gallery, ScrollView, ImageView) pour voir quelles sont les propriétés de chacun et comment il se comporte.

0 votes

Voici à quoi ressemble la classe : pastebin.com/dsWSWR4x Mais je reçois l'erreur "La méthode onTouch(View, MotionEvent) du type LockableScrollView doit surcharger ou implémenter une méthode supertype".

0 votes

Mes excuses, j'ai corrigé les erreurs dans mon code - cela aurait dû être onTouchEvent(MotionEvent ev)

1 votes

Ok maintenant le code est conforme, mais quand je lance l'application elle se plante... et quand je supprime cette classe et renvoie le <ScrollView au lieu de votre classe l'application fonctionne bien !

75voto

lily Points 139

J'étais parti par là :

        scrollView.setOnTouchListener(new View.OnTouchListener() {

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

3 votes

Simple et efficace. Le point clé est d'utiliser une variable (par exemple, isBlockedScrollView) pour contrôler quand vous voulez activer le défilement. Attribuez-lui la valeur true lorsque le défilement doit être autorisé et false sinon.

5 votes

@PeteH, je ne sais pas pourquoi, mais mon ListView fonctionne à l'inverse : vrai lorsque le défilement est désactivé et faux lorsqu'il est activé.

0 votes

@Holmes : vous avez raison, c'est vrai quand on veut bloquer le défilement.

23voto

Beowulf Bjornson Points 1166

En complément de la réponse de Joseph Earl ci-dessus, j'ai également dû remplacer la fonction onInterceptTouchEvent() méthode.

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (!mScrollable) return false;
    else return super.onInterceptTouchEvent(ev);
}

5voto

Souhaieb Points 49

Pour commencer, j'ai utilisé le code posté dans le premier commentaire mais je l'ai modifié comme suit :

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

}

alors je l'ai appelé de cette façon

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

parce que j'ai essayé

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

mais il a dit que setIsScrollable est indéfini

J'espère que cela vous aidera

0 votes

Note : les deux premiers constructeurs sont nécessaires si votre ScrollView est le conteneur de mise en page principal de votre classe de mise en page.

0 votes

Si vous touchez un bouton ou autre chose qui intercepte les touches en premier, la vue défilante continuera à défiler.

1voto

mohammad Points 11
@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);      
            }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X