Nonaktifkan ScrollView Secara Terprogram?

108

Saya ingin mengaktifkan ScrollView dan menonaktifkannya dengan Tombol Klik.
Disable artinya jika ScrollView tidak ada di sana .. dan mengaktifkannya mengembalikan ScrollView.

Saya menginginkannya karena saya memiliki galeri dengan gambar teks, dan pada satu tombol klik orientasi layar berubah, jadi dalam Lansekap teks menjadi lebih besar. Dan saya ingin ScrollView agar gambar tidak meregang sendiri dan teks menjadi tidak dapat dibaca.

scrollview.Enabled=false / setVisibility(false) tidak membuat apapun.

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>

Terima kasih

Edit1: Saya tidak dapat menggunakan Visibilitas (hilang) karena itu juga akan menyembunyikan Galeri, yang saya inginkan adalah menyembunyikan efek ScrollView. Ketika ada ScrollView, gambar di Galeri menjadi scrollabale dan tidak muat di layar sehingga Anda harus menggulir untuk melihat seluruh gambar, saya tidak ingin menonaktifkan / mengaktifkannya dengan satu klik tombol.

Saya mencoba ini:

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

Tapi tetap saja gambar di Galeri dapat digulir dan tidak sesuai dengan layar .. apa solusinya?

Omar
sumber

Jawaban:

187

Beberapa poin untuk memulai:

  1. Anda tidak dapat menonaktifkan pengguliran ScrollView. Anda perlu memperluas ke ScrollView dan mengganti onTouchEventmetode untuk kembali falseketika beberapa kondisi cocok.
  2. Komponen Galeri menggulir secara horizontal terlepas dari apakah itu di ScrollView atau tidak - ScrollView hanya menyediakan pengguliran vertikal (Anda memerlukan HorizontalScrollView untuk pengguliran horizontal)
  3. Anda sepertinya mengatakan Anda memiliki masalah dengan gambar yang meregang itu sendiri - ini tidak ada hubungannya dengan ScrollView, Anda dapat mengubah bagaimana ImageView berskala dengan android:scaleTypeproperti (XML) atau setScaleTypemetode - misalnya ScaleType.CENTERtidak akan meregangkan gambar Anda dan akan pusatkan pada ukuran aslinya

Anda dapat memodifikasi ScrollViewsebagai berikut untuk menonaktifkan pengguliran

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

}

Anda kemudian akan menggunakan

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

dalam file XML Anda (baru saja diubah ScrollViewmenjadi khusus Anda LockableScrollView).

Kemudian panggil

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

untuk menonaktifkan pengguliran tampilan.

Saya pikir Anda memiliki lebih dari sekadar masalah menonaktifkan pengguliran untuk mencapai hasil yang Anda inginkan (galeri akan tetap dapat digulir dengan kode di atas misalnya) - Saya akan merekomendasikan melakukan beberapa penelitian lebih lanjut tentang masing-masing dari tiga komponen (Galeri, ScrollView, ImageView) untuk melihat properti apa yang dimiliki masing-masing dan bagaimana perilakunya.

Joseph Earl
sumber
Berikut adalah tampilan kelas: pastebin.com/dsWSWR4x Tapi saya mendapatkan kesalahan 'Metode onTouch (View, MotionEvent) tipe LockableScrollView harus mengganti atau menerapkan metode supertipe'
Omar
Maaf, mengoreksi kesalahan dalam kode saya - seharusnyaonTouchEvent(MotionEvent ev)
Joseph Earl
1
Ok sekarang kodenya sesuai, meskipun ketika saya menjalankan aplikasi itu macet ... dan ketika saya menghapus kelas ini dan mengembalikan <ScrollView, bukan kelas Anda, aplikasi berfungsi dengan baik!
Omar
Hai Omar, bisakah Anda memposting kesalahan yang Anda dapatkan? Pastikan mengubah com.mypackagename di <com.mypackagename.LockableScrollView> menjadi milik Anda
Joseph Earl
1
Jawaban yang bagus. Jika Anda mengubah huruf besar MotionEvent.ACTION_DOWN: menjadi huruf besar / kecil MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: Anda juga dapat menonaktifkan pengguliran saat menyeret. Tapi tentu saja pada setiap orang bagaimana dia perlu menggunakannya.
luky
70

Saya telah pergi dengan cara ini:

        scrollView.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            return isBlockedScrollView;
        }
    });
bunga bakung
sumber
3
Sederhana dan berfungsi dengan baik. Poin utamanya adalah menggunakan variabel (mis., IsBlockedScrollView) untuk mengontrol kapan Anda ingin mengaktifkan scrolling. Setel ke benar saat pengguliran harus diizinkan dan salah jika tidak.
PeteH
5
@PeteH, saya tidak tahu kenapa, tapi saya ListViewbekerja sebaliknya: true saat scrolling dinonaktifkan dan false saat diaktifkan.
Machado
@ Holmes: Anda benar, benar ketika Anda ingin memblokir pengguliran
lily
1
Bekerja dengan baik. Selain itu, saya memiliki tampilan anak (tombol) dalam scrollview dan saya masih dapat berinteraksi dengan mereka meskipun tidak menimpa onInterceptTouchEvent ()! Solusi elegan.
Cody
1
@Machado Alasan Anda harus mengembalikan nilai true untuk memblokir pengguliran adalah karena pendengar sentuh mengambil nilai boolean yang dikembalikan untuk menentukan apakah peristiwa sentuh harus dikonsumsi atau tidak. Jika Anda mengembalikan false, tampilan gulir kemudian akan melanjutkan untuk meneruskan peristiwa sentuh ke pendengar gulirnya.
Vince
11

Menemukan solusi sederhana ini baru saja ditetapkan

ScrollView.requestDisallowInterceptTouchEvent(true);
JWqvist
sumber
5
requestDisallowInterceptTouchEventhanya berfungsi untuk anak dari View yang akan dikunci. Jadi akan lebih sepertimLinearLayout.requestDisallowInterceptTouchEvent(true);
Muz
6

Nonaktifkan ScrollView

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

untuk memulai, saya menggunakan Kode yang diposting di Komentar pertama tetapi saya mengubahnya seperti ini:

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

}

lalu saya memanggilnya dengan cara ini

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

karena saya sudah mencoba

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

tetapi dikatakan bahwa setIsScrollable tidak ditentukan

Saya harap ini akan membantu Anda

Souhaieb
sumber
Catatan: dua konstruktor pertama diperlukan jika Anda ScrollViewadalah container tata letak utama kelas tata letak Anda.
actaram
Jika Anda menyentuh tombol atau sesuatu yang menghalangi sentuhan terlebih dahulu, tampilan gulir akan tetap bergulir
Cristi Băluță
3

Ini solusi yang lebih sederhana. Timpa onTouch()untuk ScrollView OnTouchListenerdan kembalikan salah jika Anda ingin mengabaikan gulir dengan sentuhan. Pengguliran terprogram masih berfungsi dan tidak perlu memperluas ScrollViewkelas.

mScroller.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
  return isScrollable;
}
});
mikec
sumber
1
! isScrollable karena nilai pengembalian benar berarti bahwa peristiwa itu dicegat.
goRGon
3

Saya tidak memiliki cukup poin untuk mengomentari sebuah jawaban, tetapi saya ingin mengatakan bahwa jawaban mikec berfungsi untuk saya kecuali saya harus mengubahnya untuk kembali! IsScrollable seperti:

mScroller.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return !isScrollable;
    }
});
Dave
sumber
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);      
            }
    }
mohammad
sumber
1

@JosephEarl +1 Dia memiliki solusi hebat di sini yang berfungsi sempurna untuk saya dengan beberapa modifikasi kecil untuk melakukannya secara terprogram.


Berikut adalah perubahan kecil yang saya buat:

Kelas LockableScrollView:

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

Aktifitas utama:

LockableScrollView sv;

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

Saya memiliki tata letak di atas NestedScrollView yang memakan peristiwa sentuh dan menonaktifkan scroll:

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

dan untuk mengaktifkan:

progressBarLayout.setOnTouchListener(null);
SpyZip
sumber
1

Anda bisa membuat CustomScrollView, yang dapat menonaktifkan interferensi dengan tampilan lain. Padahal ini terkadang bisa menjengkelkan bagi pengguna akhir. Gunakan dengan hati-hati.

Ini kodenya:

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

Bagaimana cara menggunakan CustomScrollView?

Anda dapat menambahkan CustomScrollView sebagai induk ke layar tempat Anda ingin menambahkan Scrollview lain sebagai tampilan anak, dan seluruh layar dapat digulir. Saya menggunakan ini untuk 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>

Ini berhasil untuk kasus saya.

Ankit Arora
sumber
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);
    }
}
Menandai
sumber
0

Apakah ini membantu?

((ScrollView)findViewById(R.id.QuranGalleryScrollView)).setOnTouchListener(null);
rajath
sumber
1
Saya tidak berpikir itu ada bedanya, saya masih memiliki masalah yang sama
Omar
0

Anda dapat memperluas galeri dan menggunakan beberapa bendera untuk menonaktifkan pengguliran saat Anda ingin:

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;
}
}
Megarushing
sumber
-3

Seperti yang Anda lihat di dokumentasi , Anda tidak dapat mengatur visibilitas ke false. Dalam kasus Anda, Anda mungkin harus menggunakan:

scrollview.setVisibility(Visibility.GONE);

sumber
2
Ini juga akan menyembunyikan Galeri jadi ini bukan solusinya, saya mengedit posting dengan lebih detail
Omar
-6

pada pendengar klik tombol lakukan saja

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

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

sehingga bilah gulir tidak diaktifkan pada klik tombol

Sumant
sumber
2
Ini hanya menyembunyikan bar yang kurasa .. tapi bukan efek scrollview
Omar
1
itu tidak akan memungkinkan Anda untuk menggulir juga tidak akan menyembunyikan tampilan galeri
Sumant