ScrollView Programlı Olarak Devre Dışı Bırakılsın mı?


108

ScrollView'ı etkinleştirmek ve bir Düğme Tıklamasıyla devre dışı bırakmak istiyorum.
Devre dışı bırak, ScrollView orada olmasaydı .. ve etkinleştirmek ScrollView döndürürse anlamına gelir.

Bunu istiyorum çünkü metin resimleri olan bir galerim var ve bir düğmede ekran yönü değişiyor, bu yüzden Yatay'da metin büyüyor. Ve ScrollView'ı, görüntünün kendi kendine uzanmaması ve metnin okunamaz hale gelmesi için istiyorum.

scrollview.Enabled=false / setVisibility(false) hiçbir şey yapmaz.

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>

Teşekkürler

Düzenleme1: Görünürlük (gitti) özelliğini kullanamıyorum çünkü bu Galeri'yi de gizleyecektir, istediğim ScrollView efektini gizlemek. ScrollView olduğunda, Galeri'deki görüntüler kaydırılabilir hale gelir ve ekrana sığmaz, bu nedenle tüm görüntüyü görmek için kaydırmanız gerekir, bunu bir düğmeye tıklayarak devre dışı bırakmak / etkinleştirmek istemiyorum.

Bunu denedim:

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

Ama yine de Galerideki resimler kaydırılabilir durumda ve ekrana sığmıyor .. Bunun çözümü nedir?

Yanıtlar:


187

Başlamak için birkaç nokta:

  1. Bir ScrollView’un kaydırmasını devre dışı bırakamazsınız. ScrollView'a genişletmeniz ve bazı koşullar eşleştiğinde onTouchEventgeri dönmek için yöntemi geçersiz kılmanız gerekir false.
  2. Galeri bileşeni, ScrollView'da olup olmadığına bakılmaksızın yatay olarak kaydırılır - ScrollView yalnızca dikey kaydırma sağlar (yatay kaydırma için bir HorizontalScrollView gerekir)
  3. Görüntünün kendisini uzatmasıyla ilgili bir sorununuz olduğunu söylüyorsunuz - bunun ScrollView ile hiçbir ilgisi yoktur, bir ImageView android:scaleTypeözelliğiyle (XML) veya setScaleTypeyöntemle nasıl ölçekleneceğini değiştirebilirsiniz - örneğin ScaleType.CENTERgörüntünüzü uzatmaz ve orijinal boyutunda ortalayın

ScrollViewKaydırmayı devre dışı bırakmak için aşağıdaki gibi değiştirebilirsiniz

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

}

Daha sonra kullanırsın

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

XML dosyasında (sadece değişti ScrollViewsizin özel kapsamında LockableScrollView).

Sonra ara

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

görünümün kaydırılmasını devre dışı bırakmak için.

İstediğiniz sonucu elde etmek için kaydırmayı devre dışı bırakmaktan daha fazlasına sahip olduğunuzu düşünüyorum (örneğin, galeri yukarıdaki kodla kaydırılabilir durumda kalacaktır) - üç bileşenin her biri için biraz daha araştırma yapmanızı tavsiye ederim (Galeri, ScrollView, ImageView) her birinin hangi özelliklere sahip olduğunu ve nasıl davrandığını görmek için.


Sınıf şu şekilde görünüyor: pastebin.com/dsWSWR4x Ama 'LockableScrollView türünün onTouch (View, MotionEvent) yöntemi bir süper tip yöntemini geçersiz kılmalı veya uygulamalı' '
Omar

Özür dilerim, kodumdaki hataları düzelttim - öyle olmalıydıonTouchEvent(MotionEvent ev)
Joseph Earl

1
Tamam, şimdi kod uyumlu, ancak uygulamayı çalıştırdığımda çöküyor ... ve bu sınıfı kaldırıp sınıfınız yerine <ScrollView döndürdüğümde uygulama iyi çalışıyor!
Omar

Merhaba Ömer, aldığınız hatayı gönderebilir misiniz? <Com.mypackagename.LockableScrollView> içindeki com.mypackagename değerini kendi adınızla değiştirdiğinizden emin olun
Joseph Earl

1
İyi cevap. MotionEvent.ACTION_DOWN durumunu değiştirirseniz: MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: Sürüklerken de kaydırmayı devre dışı bırakabilirsiniz. Ama elbette onu nasıl kullanacağı herkes için.
luky

70

Ben şu tarafa gitmiştim:

        scrollView.setOnTouchListener(new View.OnTouchListener() {

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

3
Basit ve harika çalışıyor. Kilit nokta, kaydırmayı ne zaman etkinleştirmek istediğinizi kontrol etmek için bir değişken (örneğin, isBlockedScrollView) kullanmaktır. Kaydırmaya izin verilmesi gerektiğinde true, aksi takdirde false olarak ayarlayın.
PeteH

5
@PeteH, neden olduğuna dair hiçbir fikrim yok, ama ListViewtam tersi şekilde çalışıyor: kaydırma devre dışı bırakıldığında doğru ve etkinleştirildiğinde yanlış.
Machado

@Holmes: Kaydırmayı engellemek istediğinizde doğru, haklısınız
lily

1
Güzel çalışıyor Ayrıca, kaydırma görünümünde çocuk görünümlerim (düğmeler) var ve onlarla etkileşime girebiliyorum, onInterceptTouchEvent ()! Zarif çözüm.
Cody,

1
@Machado Kaydırmayı engellemek için true döndürmeniz gerekmesinin nedeni, dokunmatik dinleyicinin, dokunma olayının tüketilip tüketilmeyeceğini belirlemek için döndürülen boole değerini almasıdır. Yanlış döndürürseniz, kaydırma görünümü dokunma olayını kaydırma dinleyicisine iletmeye devam edecektir.
Vince

11

Az önce bu basit çözümü buldum

ScrollView.requestDisallowInterceptTouchEvent(true);

5
requestDisallowInterceptTouchEventyalnızca Görünümün alt öğesi kilitlenecek şekilde çalışır. Yani daha çokmLinearLayout.requestDisallowInterceptTouchEvent(true);
Muz

6

Disablend ScrollView

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

5

Başlamak için ilk Yorumda yayınlanan Kodu kullandım ancak şu şekilde değiştirdim:

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

}

sonra bu şekilde aradım

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

çünkü denedim

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

ancak setIsScrollable'ın tanımsız olduğunu söyledi

umarım bu sana yardımcı olmuştur


Not: İlk iki kurucu, ScrollViewdüzen sınıfınızın ana düzen taşıyıcısıysa gereklidir .
actaram

Önce dokunuşları engelleyen bir düğmeye veya başka bir şeye dokunursanız, kaydırma
görünümü

3

İşte daha basit bir çözüm. Dokunarak kaydırmayı atlamak istiyorsanız onTouch()for için geçersiz kılın ScrollView OnTouchListenerve yanlış döndür. Programlı kaydırma hala çalışıyor ve ScrollViewsınıfı genişletmeye gerek yok .

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

1
! isScrollable çünkü gerçek dönüş değeri, olayın yakalandığı anlamına gelir.
goRGon

3

Bir cevaba yorum yapmak için yeterli puanım yok, ancak mikec'in cevabının benim için işe yaradığını söylemek istedim, ancak geri dönmek için onu değiştirmek zorunda kaldım!

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 Burada, programlı olarak yapmak için bazı küçük değişikliklerle benim için mükemmel çalışan harika bir çözümü var.


İşte yaptığım küçük değişiklikler:

LockableScrollView Sınıfı:

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

Ana aktivite:

LockableScrollView sv;

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

1

NestedScrollView üzerinde dokunma olayını tüketen ve kaydırmayı devre dışı bırakan bir düzenim vardı:

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

ve etkinleştirmek için:

progressBarLayout.setOnTouchListener(null);

1

Diğer görünümlerle etkileşimini devre dışı bırakabileceğiniz bir CustomScrollView yapabilirsiniz. Bu bazen son kullanıcı için rahatsız edici olabilir. Dikkatli kullanın.

Kod bu:

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

CustomScrollView nasıl kullanılır?

Bir alt görünüm olarak başka bir Kaydırma görünümü eklemek istediğiniz ekrana bir üst öğe olarak CustomScrollView ekleyebilirsiniz ve tüm ekran kaydırılabilir. Bunu RelativeLayout için kullandım.

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

Benim durumum için çalıştı.


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

Bu yardımcı olur mu?

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

1
Herhangi bir fark yarattığını sanmıyorum, hala aynı sorun var
Omar

0

Galeriyi genişletebilir ve istediğiniz zaman kaydırmayı devre dışı bırakmak için bazı işaretler kullanabilirsiniz:

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

Belgelerde görebileceğiniz gibi , görünürlüğü yanlış olarak ayarlayamazsınız. Sizin durumunuzda muhtemelen şunları kullanmalısınız:

scrollview.setVisibility(Visibility.GONE);

2
Bu aynı zamanda Galeriyi de gizleyecek, bu yüzden çözüm değil,
Omar

-6

düğmeye tıklandığında dinleyici sadece yap

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

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

böylece kaydırma çubuğu düğme tıklandığında etkinleştirilmez


2
Bu sadece tahmin ettiğim çubukları gizler ama kaydırma görünümünün etkisi değil
Omar

1
kaydırmanıza izin vermez ayrıca galeri görünümünü gizlemeyecektir
Sumant
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.