Bagaimana cara menonaktifkan paging dengan menggesekkan dengan jari di ViewPager tetapi masih dapat menggesek secara terprogram?

550

Saya memiliki ViewPager dan di bawahnya saya memiliki 10 tombol. Dengan mengklik tombol, misalnya # 4, halaman segera menuju ke halaman # 4 mPager.setCurrentItem(3);. Tapi, saya ingin menonaktifkan paging dengan menggesekkan jari secara horizontal. Dengan demikian, paging dilakukan HANYA dengan mengklik tombol. Jadi, bagaimana saya bisa menonaktifkan gesek dengan jari?

theateist
sumber
Bagaimana kalau menggunakan ViewFlipper ? Ini akan menghemat banyak sakit kepala.
Alex Semeniuk

Jawaban:

885

Anda perlu subkelas ViewPager. onTouchEventmemiliki banyak hal baik di dalamnya yang tidak ingin Anda ubah seperti membiarkan pandangan anak untuk disentuh. onInterceptTouchEventadalah apa yang ingin Anda ubah. Jika Anda melihat kode untuk ViewPager, Anda akan melihat komentar:

    /*
     * This method JUST determines whether we want to intercept the motion.
     * If we return true, onMotionEvent will be called and we do the actual
     * scrolling there.
     */

Inilah solusi lengkapnya:

Pertama, tambahkan kelas ini ke srcfolder Anda :

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
import java.lang.reflect.Field;

public class NonSwipeableViewPager extends ViewPager {

    public NonSwipeableViewPager(Context context) {
        super(context);
        setMyScroller();
    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    //down one is added for smooth scrolling

    private void setMyScroller() {
        try {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            scroller.set(this, new MyScroller(getContext()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class MyScroller extends Scroller {
        public MyScroller(Context context) {
            super(context, new DecelerateInterpolator());
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
        }
    }
}

Selanjutnya, pastikan untuk menggunakan kelas ini daripada yang biasa ViewPager, yang mungkin Anda tentukan sebagai android.support.v4.view.ViewPager. Di file tata letak Anda, Anda ingin menentukannya dengan sesuatu seperti:

<com.yourcompany.NonSwipeableViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

Contoh khusus ini dalam a LinearLayoutdan dimaksudkan untuk mengambil seluruh layar, itulah sebabnya layout_weight1 dan layout_height0dp.

Dan setMyScroller();metode untuk transisi yang mulus

louielouie
sumber
3
@louielouie Sebagai catatan: apakah ada alasan khusus, mengapa Anda memilih solusi 0dptinggi / 1berat daripada match_parenttinggi untuk mencapai efek layar penuh? Apakah Anda memperoleh peningkatan kinerja dengan melakukannya?
ubuntudroid
29
Jawaban ini tidak mencegah gesekan halaman saat menggunakan tombol kiri / kanan keyboard (coba di emulator). Mungkin tidak menjadi masalah untuk perangkat sentuh tetapi dengan TV dan laptop mungkin menjadi satu.
Vincent Mimoun-Prat
8
@MarvinLabs @Thorbear Cara yang benar untuk menonaktifkan gulir halaman dengan keyboard adalah dengan menimpanya executeKeyEvent() . Ini adalah metode yang kemudian memanggil allowScroll(). // Never allow swiping by keyboard LEFT, RIGHT, TAB and SHIFT+TAB keys @Override public boolean executeKeyEvent(KeyEvent event) { return false; }
araks
6
baik, ini menonaktifkan juga pengguliran vertikal ... ini buruk, jika Anda menggunakan tampilan daftar.
maysi
5
Saya harap Google bisa saja menyediakan metode yang kami berikan metode antarmuka kami tentang cara menangani sentuhan / menggesek karena saya percaya itu tidak akan sakit?
Neon Warge
466

Ekstensi yang lebih umum ViewPageradalah membuat SetPagingEnabledmetode sehingga kita dapat mengaktifkan dan menonaktifkan paging dengan cepat. Untuk mengaktifkan / menonaktifkan gesekan, cukup taruh dua metode: onTouchEventdan onInterceptTouchEvent. Keduanya akan mengembalikan "false" jika paging dinonaktifkan.

public class CustomViewPager extends ViewPager {

    private boolean enabled;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onTouchEvent(event);
        }

        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onInterceptTouchEvent(event);
        }

        return false;
    }

    public void setPagingEnabled(boolean enabled) {
        this.enabled = enabled;
    } 
}

Kemudian pilih ini sebagai ganti viewpager built-in dalam XML

<mypackage.CustomViewPager 
    android:id="@+id/myViewPager" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent" />

Anda hanya perlu memanggil setPagingEnabledmetode dengan falsedan pengguna tidak akan dapat menggesek paginasi.

Rajul
sumber
3
Berfungsi sempurna untuk tampilan yang memiliki beberapa subview di mana orang menggunakan pengguliran horizontal (mis. AChartEngine chart). Dalam fragmen saya, saya menggunakan panggilan balik ke aktivitas saya untuk mengaktifkan atau menonaktifkan halaman tergantung pada apakah pengguna menyentuh (ACTION_MOVE) grafik atau meninggalkannya (ACTION_CANCEL). Terima kasih banyak!
riper
32
Anda dapat menyederhanakan onTouchEventdan onInterceptTouchEventmetode Anda denganreturn enabled && super.onTouchEvent(event);
nbarraille
2
@nbarraille itu hanya masalah gaya. Anda dapat menggunakan gaya apa pun yang tampak lebih mudah dibaca oleh Anda.
Rajul
7
Saya juga merekomendasikan mengubah nama bidang dari "diaktifkan" menjadi "swipePageChangeEnabled" atau sesuatu seperti itu. Sebulan setelah menulis kode Anda tidak akan ingat apa artinya "diaktifkan", terutama ketika kelas Anda disebut "CustomViewPager", di mana tidak jelas apa kustomisasi itu. Itu juga masalah gaya, tetapi gaya penting jika Anda tidak ingin berakhir dengan proyek yang tidak didukung, itu lebih mudah untuk menulis ulang sepenuhnya daripada memperbaikinya.
bytefu
4
Di mana saya memanggil setPagingEnabled? ._.
Ntikki 6-15
107

Cara termudah adalah dengan setOnTouchListenerdan kembali trueuntuk ViewPager.

mPager.setOnTouchListener(new OnTouchListener()
    {           
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            return true;
        }
    });
Wayne
sumber
53
Kadang tidak berfungsi. Saya menggunakan ViewPager dengan FragmentPagerAdapter dan beberapa Fragment. Setelah mengatur OnTouchListener ke pager, jika saya melemparkan kiri, UI masih akan bergerak ke kiri sedikit.
Chris.Zou
16
Ini berfungsi saat Anda menambahkan pager.setCurrentItem(pager.getCurrentItem());sebelum kembali true.
dng
1
itu bekerja untuk saya sebelumnya. tidak tahu mengapa itu tidak berfungsi dengan baik lagi.
pengembang android
sepertinya bekerja untuk saya. Untuk mengatasi beberapa gangguan tata letak yang saya miliki public int getItemPosition(Object object) { return POSITION_NONE; }di adaptor saya, yang memaksa rekreasi halaman dan mungkin memecahkan masalah lain juga.
r-tahan
6
Ini adalah solusi BAGIAN yang berfungsi. Babatan horizontal ditangani dengan cara yang aneh. Saya menguji ini dengan Drag'n Drop Gridview sebagai bagian dari ViewPager. Saat menyeret menggunakan solusi ini, menyeret dari kiri ke kanan dan kanan ke kiri gagal. Secara pribadi saya menemukan pendekatan Rajul yang terbaik.
Ton Snoei
58

Lebih baik mendeklarasikannya dengan gaya, sehingga Anda dapat mengubah propertinya dari xml:

private boolean swipeable;

public MyViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyViewPager);
    try {
        swipeable = a.getBoolean(R.styleable.MyViewPager_swipeable, true);
    } finally {
        a.recycle();
    }
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return swipeable ? super.onInterceptTouchEvent(event) : false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return swipeable ? super.onTouchEvent(event) : false;
}

Dan dalam nilai Anda / attr.xml:

<declare-styleable name="MyViewPager">
  <attr name="swipeable" format="boolean" />
</declare-styleable>

sehingga Anda dapat menggunakannya di tata letak Anda xml:

<mypackage.MyViewPager
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:swipeable="false" />

Tentu saja, Anda masih dapat memiliki properti get / set.

Pietro
sumber
58

Hanya mengesampingkan onTouchEventdanonInterceptTouchEvent tidak mencukupi jika Anda memiliki ViewPager sendiri di dalam ViewPager lain. Child ViewPager akan mencuri peristiwa sentuh gulir horizontal dari ViewPager induk kecuali jika diposisikan pada halaman pertama / terakhir.

Untuk membuat pengaturan ini berfungsi dengan baik, Anda perlu mengganti juga canScrollHorizontallymetode ini.

Lihat LockableViewPagerimplementasi di bawah ini.

public class LockableViewPager extends ViewPager {

    private boolean swipeLocked;

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

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

    public boolean getSwipeLocked() {
        return swipeLocked;
    }

    public void setSwipeLocked(boolean swipeLocked) {
        this.swipeLocked = swipeLocked;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return !swipeLocked && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return !swipeLocked && super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        return !swipeLocked && super.canScrollHorizontally(direction);
    }

}
sidon
sumber
3
Terima kasih, ini bekerja dengan sangat baik pada ViewPager di dalam ViewPager lain.
Fernanda Bari
1
Ini berfungsi untuk saya, juga untuk ViewPager di dalam ViewPager lain. Solusi yang benar tidak berhasil untuk saya dalam kasus itu.
Rafael Ruiz Muñoz
berhenti animasi juga saat digunakan di tab.
Rishabh Srivastava
Jika saya menonaktifkannya dan anggap saya ingin mengaktifkannya lalu di mana saya bisa meminta acara memanggil setSwipeLocked (false)?
Ravi Yadav
58

Sekarang kita tidak perlu membuat custom ViewPager

ViewPager2 Nama baru Lihat tersedia di android

Dukungan orientasi vertikal

  • ViewPager2mendukung paging vertikal selain paging horizontal tradisional. Anda dapat mengaktifkan paging vertikal untuk suatu ViewPager2elemen dengan mengatur android:orientationatributnya

Menggunakan XML

<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:orientation="vertical" />

Menggunakan kode

Untuk menonaktifkan menggesek viewpager2digunakan

viewPager2.setUserInputEnabled(false);

Untuk mengaktifkan gesek yang viewpager2Digunakan

viewPager2.setUserInputEnabled(true);

untuk informasi lebih lanjut, periksa ini

MEMPERBARUI

Nilesh Rathod
sumber
3
Sangat bagus, tetapi masih terlihat tidak lengkap. Saya sudah mencobanya dengan 5 fragmen berbeda dan setelah beralih antar halaman salah satu fragmennya hilang, yaitu tampilan tidak dipulihkan atau
diperbesar
@Toochka menyesal mendengar bahwa bagi saya itu berfungsi dengan baik, Anda dapat menemukan contoh kode kerja dari sini stackoverflow.com/a/54643817/7666442 jika memungkinkan silakan bagikan kode Anda
Nilesh Rathod
1
Saya dapat dengan sukses menonaktifkan swiping pada ViewPager2 menggunakan metode ini
voghDev
1
@voghDev senang mendengarnya
Nilesh Rathod
1
@PhaniRithvij silahkan cek jawaban ini stackoverflow.com/a/54643817/7666442 saya Apakah menambahkan semua rincian bagaimana menggunakan viewpager2denganRecyclerView.Adapter
Nilesh Rathod
35

Jika Anda memperpanjang dari ViewPager, Anda juga harus menggantiexecuteKeyEvent seperti yang ditunjukkan sebelumnya oleh @araks

@Override
public boolean executeKeyEvent(KeyEvent event)
{
    return isPagingEnabled ? super.executeKeyEvent(event) : false;
}

Karena beberapa perangkat seperti Galaxy Tab 4 10 'menunjukkan tombol-tombol ini di mana sebagian besar perangkat tidak pernah menunjukkannya:

Tombol keyboard

Lemak
sumber
50
Samsung selalu mengacaukan segalanya untuk pengembang Android.
toobsco42
2
@ toobsco42 Samsung tidak sendirian dalam hal ini. SwiftKey (aplikasi papan ketik populer) memungkinkan pengguna untuk menempatkan panah di papan ketik mereka.
Sufian
1
Ini juga merupakan perbaikan jika Anda ingin menghentikan seseorang menggunakan keyboard / trackball dari pager halaman Anda.
lihat
28

Untuk menonaktifkan geser

mViewPager.beginFakeDrag();

Untuk mengaktifkan gesek

mViewPager.endFakeDrag();
KAMAL VERMA
sumber
22
Ini bukan solusi yang baik karena memungkinkan gerakan dalam porsi kecil, setidaknya di aplikasi saya.
koras
Bekerja dengan baik untuk saya. Apa kerugiannya dibandingkan dengan solusi lain yang disediakan?
userM1433372
13

Saya perlu menonaktifkan menggesek pada satu halaman tertentu, dan memberikan animasi karet-band yang bagus, begini caranya:

    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageScrolled(int position, float positionOffset,
                                   int positionOffsetPixels) {
            if (position == MANDATORY_PAGE_LOCATION && positionOffset > 0.5) {
                mViewPager.setCurrentItem(MANDATORY_PAGE_LOCATION, true);
            }
        }
Oded Breiner
sumber
Ia menunggu hingga halaman berikutnya terlihat sebagian. Kode untuk halaman selanjutnya onPageSelectedakan dieksekusi. Bahkan halaman selanjutnya akan berganti. Jadi, kode ini tidak diperlukan.
CoolMind
13

Saya tahu ini sangat terlambat untuk memposting ini, tetapi ini adalah hack kecil untuk mencapai hasil Anda;)

Cukup tambahkan tampilan dummy di bawah viewpager Anda:

<android.support.v4.view.ViewPager
     android:layout_width="match_parent"
     android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

<RelativeLayout
     android:id="@+id/dummyView"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
</RelativeLayout>

Kemudian tambahkan OnClickListenerke RelativeLayout.

dummyView = (RelativeLayout) findViewById(R.id.dummyView);

dummyView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
         //Just leave this empty
    }
});

Dapatkan sedikit kreatif dengan tata letak, penempatan mereka dan perilaku mereka dan Anda akan belajar untuk menemukan cara untuk melakukan apa pun yang Anda bayangkan :)

Semoga berhasil!

Dinuka Jay
sumber
Cara yang lebih mudah adalah menggunakan setClickablealih-alih setOnClickListener, jika Anda tidak perlu menangani onClickacara.
Kekacauan
bukankah ini juga memblokir sentuhan dalam viewpager?
pengembang android
Ya, tentu saja. Itu perilaku yang diharapkan yang diperlukan oleh OP
@androiddeveloper
@ RickGrimesTheCoder Saya tidak berpikir Anda mengerti pertanyaan saya. Maksud saya pandangan dalam fragmen viewpager. Apakah mereka masih bisa disentuh?
pengembang android
Tidak, itu tidak akan terjadi karena viewpager itu sendiri memiliki pendengar klik. Ini hanya cocok untuk contoh di mana Anda tidak memiliki elemen interaktif di dalam fragmen. Misalnya, Welcome ViewPager yang mengubah fragmennya secara dinamis
@androiddeveloper
12

Saya menulis CustomViewPagerdengan kontrol swiping:

public class ScrollableViewPager extends ViewPager {
    private boolean canScroll = true;
    public ScrollableViewPager(Context context) {
        super(context);
    }
    public ScrollableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public void setCanScroll(boolean canScroll) {
        this.canScroll = canScroll;
    }
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return canScroll && super.onTouchEvent(ev);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return canScroll && super.onInterceptTouchEvent(ev);
    }
}

Jika Anda mengatur canScrollke true, ini ViewPagerbisa menggesekkan dengan jari, falsesebaliknya.

Saya menggunakan ini dalam proyek saya, dan itu berfungsi dengan baik sampai sekarang.

L. Swifter
sumber
1
Bagaimana jika saya memiliki tombol di dalam ViewPager dan saya ingin klik? solusi ini menghentikan semua yang ada di bawah viewpager untuk diklik ..
aimiliano
6

Saya menggunakan kelas ini dengan sukses. Override executeKeyEvent diperlukan untuk menghindari menggesekkan menggunakan panah di beberapa perangkat atau untuk aksesibilitas:

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;

public class ViewPagerNoSwipe extends ViewPager {
    /**
     * Is swipe enabled
     */
    private boolean enabled;

    public ViewPagerNoSwipe(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = false; // By default swiping is disabled
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.enabled ? super.onTouchEvent(event) : false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.enabled ? super.onInterceptTouchEvent(event) : false;
    }

    @Override
    public boolean executeKeyEvent(KeyEvent event) {
        return this.enabled ? super.executeKeyEvent(event) : false;
    }

    public void setSwipeEnabled(boolean enabled) {
        this.enabled = enabled;
    }

}

Dan di xml sebut seperti ini:

<package.path.ViewPagerNoSwipe
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
madx
sumber
Berhasil. Hanya gesek yang dinonaktifkan dan mengklik tab diaktifkan. SEPERTI memperingatkan bahwa performClick()metode tidak diganti.
CoolMind
5

Di Kotlin, solusi saya, menggabungkan jawaban di atas.

class CustomViewPager(context: Context, attrs: AttributeSet): ViewPager(context, attrs) {
    var swipeEnabled = false

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onTouchEvent(ev) else false
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onInterceptTouchEvent(ev) else false
    }

    override fun executeKeyEvent(event: KeyEvent): Boolean {
        return if (swipeEnabled) super.executeKeyEvent(event) else false
    }
}
Jeff Padgett
sumber
Mengesampingkan onInterceptTouchEvent()akan mencegah pandangan anak untuk menerima input. Dalam kebanyakan kasus ini bukan perilaku yang dimaksudkan.
Alex Semeniuk
Saya dapat berinteraksi dengan pandangan anak dari setiap fragmen. Tidak yakin apa yang Anda maksud.
Jeff Padgett
5

Di kotlin, kita bisa menyelesaikan ini dengan membuat widget khusus yang mewarisi kelas ViewPager dan menambahkan nilai flag untuk mengendalikan perilaku swipe.

NoSwipePager.kt

class NoSwipePager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) {

    var pagingEnabled: Boolean = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onTouchEvent(event)
        } else false
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onInterceptTouchEvent(event)
        } else false
    }
}

Dalam xml

<your.package.NoSwipePager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/tab_layout" />

Nonaktifkan menggesek secara pemrograman. Jika kotlin-android-extensionsplugin diterapkan di build.gradle , menggesekkan dapat dinonaktifkan dengan menulis kode di bawah ini.

view_pager.pagingEnabled = false

Kalau tidak, kita dapat menonaktifkan menggesek menggunakan kode di bawah ini:

val viewPager : ViewPager = findViewById(R.id.view_pager)
viewPager.pagingEnabled = false
Sagar Chapagain
sumber
Mengesampingkan onInterceptTouchEvent()akan mencegah pandangan anak untuk menerima input. Dalam kebanyakan kasus ini bukan perilaku yang dimaksudkan.
Alex Semeniuk
@AlexSemeniuk Sudahkah Anda mengamati masalah setelah menerapkan ini? Saya telah mengaktifkan swiping pada item tampilan pendaur ulang untuk beberapa tindakan dan itu berfungsi dengan baik. Jadi implementasinya bekerja dengan baik dalam kasus saya.
Sagar Chapagain
Sagar Chapagain: atau tentu saja saya lakukan. Setiap halaman saya berisi tampilan khusus, yang memproses sentuhan dengan berbagai cara (termasuk menggulir, menarik, mengetuk tunggal dan panjang). Tidak memanggil super.onInterceptTouchEvent(event)hasil dalam tampilan ini tidak menerima input apa pun (yang merupakan tujuan onInterceptTouchEventmetode yang didokumentasikan ).
Alex Semeniuk
Jika demikian, Anda sebaiknya menggunakan fragmen anak dan mempertahankan backstack.
Sagar Chapagain
Bagaimana ini relevan dengan pertanyaan saat ini? Fragmen ditempatkan di dalam beberapa wadah (yaitu Views ) dan tata letaknya sendiri berisi Views . Apa pun konten yang saya miliki di dalam ViewPager, saya masih berurusan dengan fakta bahwa onInterceptTouchEvent()metode utama mencegahnya (konten) menerima input.
Alex Semeniuk
4

Cobalah mengesampingkan dan mengembalikan true dari onInterceptTouchEvent () dan / atau onTouchEvent () , yang akan mengkonsumsi acara sentuh pada pager.

AdamK
sumber
1
tidakkah dia ingin kembali trueuntuk menyiratkan bahwa acara sentuhan telah ditangani?
edthethird
1

Solusi mudah lain untuk menonaktifkan menggesekkan pada halaman tertentu (dalam contoh ini, halaman 2):

int PAGE = 2;
viewPager.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
        if (viewPager.getCurrentItem() == PAGE) {
                viewPager.setCurrentItem(PAGE-1, false);
                viewPager.setCurrentItem(PAGE, false);
                return  true;
        }
        return false;
}
Ofir
sumber
1
This worked for me

viewPager.setOnTouchListener(new View.OnTouchListener() {
                                         @Override
                                         public boolean onTouch(View v, MotionEvent event) {
                                             if (viewPager.getCurrentItem() == 0) {
                                                 viewPager.setCurrentItem(-1, false);
                                                 return true;
                                             }
                                             else if (viewPager.getCurrentItem() == 1) {
                                                 viewPager.setCurrentItem(1, false);
                                                 return true;
                                             }
                                             else if (viewPager.getCurrentItem() == 2) {
                                                 viewPager.setCurrentItem(2, false);
                                                 return true;
                                             }
                                             return true;
                                         }
                                     });
Princewill Iroka
sumber
1

Jika Anda menulis galeri gambar dengan ImageViews dan ViewPager, yang mendukung zoom dan pan, lihat solusi sederhana yang dijelaskan di sini: Menerapkan ImageView yang dapat diperbesar dengan Memperluas ViewPager Default di Phimpme Android (dan sampel Github - PhotoView ). Solusi ini tidak bekerja dengan ViewPagersendirian.

public class CustomViewPager extends ViewPager {
    public CustomViewPager(Context context) {
        super(context);
    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        try {
            return super.onInterceptTouchEvent(event);
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}
CoolMind
sumber
1

Jika Anda menggunakan ViewPager2, Anda hanya perlu menggunakan:

viewpager.setUserInputEnabled(false);

Dari dokumen :

Aktifkan atau nonaktifkan pengguliran yang dimulai pengguna. Ini termasuk input sentuh (gulir dan gerakan melempar) dan input aksesibilitas. Menonaktifkan input keyboard belum didukung. Ketika pengguliran yang dimulai pengguna dinonaktifkan, gulir terprogram melalui setCurrentItem masih berfungsi. Secara default, pengguliran yang dimulai pengguna diaktifkan.

Terima kasih kepada: https://stackoverflow.com/a/61685871/9026710

Tayyab Mazhar
sumber
0

Jika Anda ingin menerapkan hal yang sama untuk Android di Xamarin, berikut adalah terjemahan ke C #

Saya memilih untuk memberi nama atribut " ScrollEnabled ". Karena iOS hanya menggunakan penamaan yang sama excat. Jadi, Anda memiliki penamaan yang sama di kedua platform, membuatnya lebih mudah bagi pengembang.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V4.View;
using Android.Util;

namespace YourNameSpace.ViewPackage {

    // Need to disable swiping for ViewPager, if user performs Pre DSA and the dsa is not completed yet
    // http://stackoverflow.com/questions/9650265/how-do-disable-paging-by-swiping-with-finger-in-viewpager-but-still-be-able-to-s
    public class CustomViewPager: ViewPager {
        public bool ScrollEnabled;

        public CustomViewPager(Context context, IAttributeSet attrs) : base(context, attrs) {
            this.ScrollEnabled = true;
        }

        public override bool OnTouchEvent(MotionEvent e) {
            if (this.ScrollEnabled) {
                return base.OnTouchEvent(e);
            }
            return false;
        }

        public override bool OnInterceptTouchEvent(MotionEvent e) {
            if (this.ScrollEnabled) {
                return base.OnInterceptTouchEvent(e);
            }
            return false;
        }

        // For ViewPager inside another ViewPager
        public override bool CanScrollHorizontally(int direction) {
            return this.ScrollEnabled && base.CanScrollHorizontally(direction);
        }

        // Some devices like the Galaxy Tab 4 10' show swipe buttons where most devices never show them
        // So, you could still swipe through the ViewPager with your keyboard keys
        public override bool ExecuteKeyEvent(KeyEvent evt) {
            return this.ScrollEnabled ? base.ExecuteKeyEvent(evt) : false;
        }
    }
}

Dalam file .axml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <YourNameSpace.ViewPackage.CustomViewPager
      android:id="@+id/pager"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@android:color/white"
      android:layout_alignParentTop="true" />
</LinearLayout>
Lepidopteron
sumber
0

Tidak satu pun dari kode di atas yang berfungsi dengan lancar. Saya mencoba ini

<HorizontalScrollView
                    android:id="@+id/horizontalScrollView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:fillViewport="true">

                    <android.support.v4.view.ViewPager
                        android:id="@+id/pager"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent" />
                </HorizontalScrollView>
Nandan Singh
sumber
0

di sini adalah implementasi saya
bahwa jika Anda ingin menonaktifkan animasi gesek Anda dapat menggunakan swipeListener kiri dan kanan dan masih ingin gulir dengan jari tetapi tanpa animasi

ViewpagerMetode 1-Override onInterceptTouchEventdanonTouchEvent

2- buat milik Anda sendiri GestureDetector

3 - mendeteksi gerakan menggesek dan menggunakan setCurrentItem(item, false)

ViewPager

public class ViewPagerNoSwipe extends ViewPager {
    private final GestureDetector gestureDetector;
    private OnSwipeListener mOnSwipeListener;

    public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
        mOnSwipeListener = onSwipeListener;
    }

    public ViewPagerNoSwipe(@NonNull Context context) {
        super(context);
        gestureDetector = new GestureDetector(context, new GestureListener());

    }

    public ViewPagerNoSwipe(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(context, new GestureListener());


    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        gestureDetector.onTouchEvent(ev);
        return false;
    }

    public class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeRight();
                        } else {
                            if(mOnSwipeListener!=null)
                                mOnSwipeListener.onSwipeLeft();
                        }
                        result = true;
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeBottom();
                    } else {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public interface OnSwipeListener {

         void onSwipeRight();

        void onSwipeLeft();

        void onSwipeTop();

        void onSwipeBottom();
    }
}

ketika Anda mengatur ViewPager mengatur swipeListener

postsPager.setOnSwipeListener(new ViewPagerNoSwipe.OnSwipeListener() {
            @Override
            public void onSwipeRight() {

              postsPager.setCurrentItem(postsPager.getCurrentItem() + 1,false);

            }

            @Override
            public void onSwipeLeft() {

            postsPager.setCurrentItem(postsPager.getCurrentItem() - 1, false);

            }
             ...
           }
tamtom
sumber
0

Saya hanya mengkustomisasi viewpager sedikit dan menonaktifkan swiping dengan mudah.

public class CustomViewPager extends ViewPager {

private boolean swipeLocked;

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

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

public boolean getSwipeLocked() {
    return swipeLocked;
}

public void setSwipeLocked(boolean swipeLocked) {
    this.swipeLocked = swipeLocked;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return !swipeLocked && super.onTouchEvent(event);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return !swipeLocked && super.onInterceptTouchEvent(event);
}

@Override
public boolean canScrollHorizontally(int direction) {
    return !swipeLocked && super.canScrollHorizontally(direction);
}
}
Shivam Yadav
sumber
-1
shareViewPager?.setOnTouchListener(object :View.OnTouchListener{
            override fun onTouch(v: View?, event: MotionEvent?): Boolean {
                for (PAGE in 0..shareViewPager.adapter!!.count){
                    if (shareViewPager.currentItem==PAGE){
                        shareViewPager.setCurrentItem(PAGE-1,false)
                        shareViewPager.setCurrentItem(PAGE,false)
                    }}
                return true
            }

        })
Cihat Baydan
sumber