ScrollView programmgesteuert deaktivieren?


108

Ich möchte ScrollView aktivieren und durch Klicken auf eine Schaltfläche deaktivieren.
Deaktivieren bedeutet, dass die ScrollView nicht vorhanden war. Wenn Sie sie aktivieren, wird die ScrollView zurückgegeben.

Ich möchte das, weil ich eine Galerie mit Textbildern habe und auf eine Schaltfläche klicke, ändert sich die Bildschirmausrichtung, sodass der Text im Querformat größer wird. Und ich möchte die ScrollView, damit sich das Bild nicht selbst dehnt und der Text unlesbar wird.

scrollview.Enabled=false / setVisibility(false) macht nichts.

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>

Vielen Dank

Edit1: Ich kann Visibility (weg) nicht verwenden, da dadurch auch die Galerie ausgeblendet wird. Ich möchte den Effekt von ScrollView ausblenden. Wenn es ScrollView gibt, werden die Bilder in der Galerie scrollabale und passen nicht in den Bildschirm, so dass Sie scrollen müssen, um das gesamte Bild zu sehen. Ich möchte das nicht deaktivieren / aktivieren, wenn Sie auf eine Schaltfläche klicken.

Ich habe es versucht:

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

Trotzdem sind die Bilder in der Galerie scrollbar und passen nicht auf den Bildschirm. Was ist die Lösung dafür?

Antworten:


186

Zunächst einige Punkte:

  1. Sie können das Scrollen einer ScrollView nicht deaktivieren. Sie müssten auf ScrollView erweitern und die onTouchEventMethode überschreiben , um zurückzukehren, falsewenn eine Bedingung erfüllt ist.
  2. Die Galeriekomponente scrollt horizontal, unabhängig davon, ob sie sich in einer ScrollView befindet oder nicht - eine ScrollView bietet nur vertikales Scrollen (Sie benötigen eine HorizontalScrollView für das horizontale Scrollen).
  3. Sie scheinen zu sagen, dass Sie ein Problem mit der Bilddehnung selbst haben - dies hat nichts mit der ScrollView zu tun. Sie können ändern, wie eine ImageView mit der android:scaleTypeEigenschaft (XML) oder der setScaleTypeMethode skaliert wird - zum Beispiel ScaleType.CENTERwird Ihr Bild nicht gedehnt und wird es auch nicht zentrieren Sie es auf seiner Originalgröße

Sie können ScrollViewFolgendes ändern , um das Scrollen zu deaktivieren

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

}

Sie würden dann verwenden

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

in Ihrer XML-Datei (gerade geändert ScrollViewin Ihre spezielle LockableScrollView).

Dann ruf an

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

um das Scrollen der Ansicht zu deaktivieren.

Ich denke, Sie haben jedoch mehr als nur das Problem, das Scrollen zu deaktivieren, um das gewünschte Ergebnis zu erzielen (die Galerie bleibt beispielsweise mit dem obigen Code scrollbar). Ich würde empfehlen, mehr Nachforschungen über jede der drei Komponenten anzustellen (Galerie, ScrollView, ImageView), um zu sehen, welche Eigenschaften jeder hat und wie er sich verhält.


So sieht die Klasse aus: pastebin.com/dsWSWR4x Aber ich erhalte die Fehlermeldung 'Die Methode onTouch (View, MotionEvent) vom Typ LockableScrollView muss eine Supertyp-Methode überschreiben oder implementieren'
Omar

Entschuldigung, korrigiert die Fehler in meinem Code - es hätte sein sollenonTouchEvent(MotionEvent ev)
Joseph Earl

1
Ok, jetzt stimmt der Code überein, aber wenn ich die App starte, stürzt er ab ... und wenn ich diese Klasse entferne und die <ScrollView anstelle Ihrer Klasse zurückgebe, funktioniert die App einwandfrei!
Omar

Hallo Omar, könntest du den Fehler posten, den du bekommst? Stellen Sie sicher, dass Sie den com.mypackagename in <com.mypackagename.LockableScrollView> in Ihren eigenen ändern
Joseph Earl

1
Gute Antwort. Wenn Sie case MotionEvent.ACTION_DOWN: in case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN ändern, können Sie den Bildlauf auch beim Ziehen deaktivieren. Aber es liegt natürlich bei jedem, wie er es benutzen muss.
luky

70

Ich war diesen Weg gegangen:

        scrollView.setOnTouchListener(new View.OnTouchListener() {

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

3
Einfach und funktioniert super. Der wichtigste Punkt ist die Verwendung einer Variablen (z. B. isBlockedScrollView), um zu steuern, wann Sie das Scrollen aktivieren möchten. Setzen Sie es auf true, wenn das Scrollen erlaubt sein soll, andernfalls auf false.
PeteH

4
@PeteH, ich habe keine Ahnung warum, aber ich ListViewarbeite umgekehrt: true, wenn das Scrollen deaktiviert ist, und false, wenn es aktiviert ist.
Machado

@ Holmes: Sie haben Recht, wahr, wenn Sie das Scrollen blockieren möchten
Lilie

1
Funktioniert wunderbar. Außerdem habe ich untergeordnete Ansichten (Schaltflächen) in der Bildlaufansicht und kann trotzdem mit ihnen interagieren, obwohl onInterceptTouchEvent () nicht überschrieben wird! Elegante Lösung.
Cody

@tardoandre es funktioniert perfekt mit mir mit dem gleichen Trick, komisch!
Ibrahim AbdelGawad

11

Fand diese einfache Lösung gerade eingestellt

ScrollView.requestDisallowInterceptTouchEvent(true);

5
requestDisallowInterceptTouchEventfunktioniert nur für das untergeordnete Element der Ansicht, das gesperrt werden soll. Also wäre es eher somLinearLayout.requestDisallowInterceptTouchEvent(true);
Muz

6

Deaktivieren Sie ScrollView

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

5

Zu Beginn habe ich den Code verwendet, der im ersten Kommentar veröffentlicht wurde, aber ich habe ihn folgendermaßen geändert:

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

}

dann habe ich es auf diese Weise angerufen

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

weil ich es versucht habe

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

aber es hieß, dass setIsScrollable undefiniert ist

ich hoffe, dies wird dir helfen


Hinweis: Die ersten beiden Konstruktoren werden benötigt, wenn Sie ScrollViewder Hauptlayoutcontainer Ihrer Layoutklasse sind.
Actaram

Wenn Sie eine Taste oder etwas anderes berühren, das die Berührungen zuerst abfängt, wird die Bildlaufansicht weiterhin
gescrollt

3

Ich habe nicht genug Punkte, um eine Antwort zu kommentieren, aber ich wollte sagen, dass die Antwort von mikec für mich funktioniert hat, außer dass ich sie ändern musste, um zurückzukehren! IsScrollable wie folgt:

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

2

Hier ist eine einfachere Lösung. Überschreiben Sie das onTouch()für ScrollView OnTouchListenerund geben Sie false zurück, wenn Sie den Bildlauf durch Berühren umgehen möchten. Das programmatische Scrollen funktioniert weiterhin und die ScrollViewKlasse muss nicht erweitert werden .

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

! isScrollable, da true return value bedeutet, dass das Ereignis abgefangen wurde.
GoRGon

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 Er hat hier eine großartige Lösung, die mit einigen geringfügigen Änderungen für die programmgesteuerte Ausführung perfekt für mich funktioniert hat.


Hier sind die kleinen Änderungen, die ich vorgenommen habe:

LockableScrollView-Klasse:

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

Hauptaktivität:

LockableScrollView sv;

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

1

Ich hatte ein Layout über der NestedScrollView, das das Berührungsereignis verbrauchte und den Bildlauf deaktivierte:

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

und zu aktivieren:

progressBarLayout.setOnTouchListener(null);

1

Sie können eine CustomScrollView erstellen, für die Sie die Interferenz mit anderen Ansichten deaktivieren können. Dies kann jedoch für den Endbenutzer manchmal irritierend sein. Verwenden Sie es mit Vorsicht.

Dies ist der Code:

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

Wie verwende ich CustomScrollView?

Sie können CustomScrollView als übergeordnetes Element zu dem Bildschirm hinzufügen, in dem Sie eine weitere Bildlaufansicht als untergeordnete Ansicht hinzufügen möchten, und der gesamte Bildschirm kann gescrollt werden. Ich habe dies für ein RelativeLayout verwendet.

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

Es hat für meinen Fall funktioniert.


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

Hilft das?

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

1
Ich glaube nicht, dass es einen Unterschied gemacht hat, ich habe immer noch das gleiche Problem
Omar

0

Sie können die Galerie erweitern und mit einem Flag das Scrollen deaktivieren, wenn Sie möchten:

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

Wie Sie in der Dokumentation sehen können , können Sie die Sichtbarkeit nicht auf false setzen. In Ihrem Fall sollten Sie wahrscheinlich verwenden:

scrollview.setVisibility(Visibility.GONE);

2
Dies wird auch die Galerie verbergen, so dass es nicht die Lösung ist. Ich habe den Beitrag mit weiteren Details bearbeitet
Omar

-6

auf Schaltfläche klicken Listener einfach tun

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

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

Damit wird die Bildlaufleiste beim Klicken auf die Schaltfläche nicht aktiviert


2
Dies verbirgt nur die Balken, denke ich .. aber nicht die Wirkung der Bildlaufansicht
Omar

1
Sie können nicht scrollen und die Galerie-Ansicht wird nicht
ausgeblendet
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.