Android: ViewPager Vertikal [ditutup]

131

Apakah ada cara untuk membuat ViewPageryang tidak menggulir secara horizontal, tetapi secara vertikal ?!

pengguna1709805
sumber
1
Ada implementasi open source baru tidak resmi dari ViewPager vertikal: Pengumuman: plus.google.com/107777704046743444096/posts/1FTJfrvnY8w Kode: github.com/LambergaR/VerticalViewPager
Vasily Sochinsky
Implementasi pager tampilan vertikal oleh Antoine Merle: github.com/castorflex/VerticalViewPager
micnoy
Ada implementasi baru berdasarkan 19 perpustakaan pendukung: github.com/castorflex/VerticalViewPager
Vasily Sochinsky
Ini tidak sama dengan github.com/castorflex/VerticalViewPager , meskipun memiliki nama yang mirip.
Flimm
1
Ada kontrol yang disebut ViewPager2 periksa di sini untuk demo stackoverflow.com/a/54643817/7666442
Nilesh Rathod

Jawaban:

227

Anda dapat menggunakan ViewPager.PageTransformer untuk memberikan ilusi vertikal ViewPager. Untuk mencapai pengguliran dengan vertikal alih-alih seret horizontal, Anda harus mengganti ViewPagerevent sentuh default dan menukar koordinat MotionEventsebelum menangani, misalnya:

/**
 * Uses a combination of a PageTransformer and swapping X & Y coordinates
 * of touch events to create the illusion of a vertically scrolling ViewPager. 
 * 
 * Requires API 11+
 * 
 */
public class VerticalViewPager extends ViewPager {

    public VerticalViewPager(Context context) {
        super(context);
        init();
    }

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

    private void init() {
        // The majority of the magic happens here
        setPageTransformer(true, new VerticalPageTransformer());
        // The easiest way to get rid of the overscroll drawing that happens on the left and right
        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    private class VerticalPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View view, float position) {

            if (position < -1) { // [-Infinity,-1)
                // This page is way off-screen to the left.
                view.setAlpha(0);

            } else if (position <= 1) { // [-1,1]
                view.setAlpha(1);

                // Counteract the default slide transition
                view.setTranslationX(view.getWidth() * -position);

                //set Y position to swipe in from top
                float yPosition = position * view.getHeight();
                view.setTranslationY(yPosition);

            } else { // (1,+Infinity]
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    }

    /**
     * Swaps the X and Y coordinates of your touch event.
     */
    private MotionEvent swapXY(MotionEvent ev) {
        float width = getWidth();
        float height = getHeight();

        float newX = (ev.getY() / height) * width;
        float newY = (ev.getX() / width) * height;

        ev.setLocation(newX, newY);

        return ev;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev){
        boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
        swapXY(ev); // return touch coordinates to original reference frame for any child views
        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(swapXY(ev));
    }

}

Tentu saja Anda dapat mengubah pengaturan ini sesuai keinginan Anda. Berakhir tampak seperti ini:

Demo VerticalViewPager

Brett
sumber
4
@ Der Golem bagaimana cara menggunakan tata letak untuk ini?
bShah
Apa pertanyaan tepatnya? Omong-omong, saya tidak memposting jawaban, hanya menambahkan gambar yang dimaksud.
Phantômaxx
1
@ Brett dalam contoh ini saya ingin melakukan beberapa tindakan pada gesek ke kiri dan ke kanan. bagaimana melakukan itu
Prab
1
@ Bret berfungsi seperti yang diharapkan, transisi dilakukan secara vertikal. Tetapi masalahnya adalah saya harus menggesek kanan / kiri untuk melakukan transisi dan pada swiping atas / bawah tidak ada transisi yang terjadi.
Karan Khurana
2
@ Brett saya menggunakan solusi Anda. tapi sekarang saya mendapatkan masalah swipping di perangkat pie andorid. Apakah ada yang menghadapi masalah yang sama?
Jishant
21

Saya punya solusi yang berfungsi untuk saya dalam dua langkah.

  1. onInstantiateItem()dari PagerAdapter, buat tampilan dan putar dengan -90:

    view.setRotation(-90f)

    Jika Anda menggunakan FragmentPagerAdapter, maka:

    objFragment.getView().setRotation(-90)
  2. Putar ViewPagertampilan 90 derajat:

    objViewPager.setRotation(90)

Bekerja seperti jimat setidaknya untuk kebutuhan saya.

Kulai
sumber
4
solusi ini berfungsi, TETAPI Anda masih harus menggesek secara horizontal sedangkan viewPager sekarang bergulir secara vertikal
leochab
@Kulai saya tidak jelas apa yang harus dilakukan di sini dapatkah Anda jelaskan sedikit sesuai pemahaman saya, kami memiliki objek publik instantiateItem (wadah ViewGroup, posisi int) di sini kita perlu melakukan container.setRotation (-90f);
varun
1
Melakukannya bekerja seperti pesona! Meskipun pandangan menjadi terpotong di bagian atas dan bawah, dan saya tidak tahu mengapa: - /
Nivaldo Bondança
2
Ini berfungsi dengan baik untuk gambar persegi dan bukan untuk persegi panjang. Dimensi salah ketika persegi panjang diputar.
Kulai
1
Saya tidak yakin siapa yang memilih jawaban ini. ini bukan VerticalViewPager, ini adalah ViewPager dengan rotasi 90 derajat, gerakan dan transisinya hanya berseberangan. dan itu sama sekali tidak alami
droidev
20

ViewPager Vertikal

Jawaban lain di sini semua tampaknya memiliki beberapa masalah dengan mereka. Bahkan proyek open source yang direkomendasikan tidak menggabungkan permintaan tarikan terbaru dengan perbaikan bug. Kemudian saya menemukan VerticalViewPagerdari Google bahwa mereka menggunakan beberapa aplikasi DeskClock. Saya percaya menggunakan implementasi Google jauh lebih banyak daripada jawaban lain yang beredar di sini. (Versi Google mirip dengan jawaban terpilih saat ini, tetapi lebih menyeluruh.)

Contoh Lengkap

Contoh ini hampir persis sama dengan Contoh ViewPager Dasar saya , dengan beberapa perubahan kecil untuk menggunakan VerticalViewPagerkelas.

masukkan deskripsi gambar di sini

XML

Tambahkan tata letak xml untuk aktivitas utama dan untuk setiap halaman (fragmen). Perhatikan bahwa kami menggunakan VerticalViewPagerdaripada standar ViewPager. Saya akan memasukkan kode untuk itu di bawah ini.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.verticalviewpager.MainActivity">

    <com.example.myapp.VerticalViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

fragment_one.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

    <TextView
        android:id="@+id/textview"
        android:textSize="30sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

</RelativeLayout>

Kode

Kode untuk VerticalViewPagerbukan milikku. Ini hanya versi singkat (tanpa komentar) dari kode sumber Google. Lihat yang itu untuk versi yang paling baru. Komentar di sana juga bermanfaat untuk memahami apa yang terjadi.

VerticalViewPager.java

import android.support.v4.view.ViewPager;    

public class VerticalViewPager extends ViewPager {

    public VerticalViewPager(Context context) {
        this(context, null);
    }

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

    @Override
    public boolean canScrollHorizontally(int direction) {
        return false;
    }

    @Override
    public boolean canScrollVertically(int direction) {
        return super.canScrollHorizontally(direction);
    }

    private void init() {
        setPageTransformer(true, new VerticalPageTransformer());
        setOverScrollMode(View.OVER_SCROLL_NEVER);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final boolean toIntercept = super.onInterceptTouchEvent(flipXY(ev));
        flipXY(ev);
        return toIntercept;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        final boolean toHandle = super.onTouchEvent(flipXY(ev));
        flipXY(ev);
        return toHandle;
    }

    private MotionEvent flipXY(MotionEvent ev) {
        final float width = getWidth();
        final float height = getHeight();
        final float x = (ev.getY() / height) * width;
        final float y = (ev.getX() / width) * height;
        ev.setLocation(x, y);
        return ev;
    }

    private static final class VerticalPageTransformer implements ViewPager.PageTransformer {
        @Override
        public void transformPage(View view, float position) {
            final int pageWidth = view.getWidth();
            final int pageHeight = view.getHeight();
            if (position < -1) {
                view.setAlpha(0);
            } else if (position <= 1) {
                view.setAlpha(1);
                view.setTranslationX(pageWidth * -position);
                float yPosition = position * pageHeight;
                view.setTranslationY(yPosition);
            } else {
                view.setAlpha(0);
            }
        }
    }
}

MainActivity.java

Saya hanya bertukar VerticalViewPageruntuk ViewPager.

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

public class MainActivity extends AppCompatActivity {

    static final int NUMBER_OF_PAGES = 2;

    MyAdapter mAdapter;
    VerticalViewPager mPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mAdapter = new MyAdapter(getSupportFragmentManager());
        mPager = findViewById(R.id.viewpager);
        mPager.setAdapter(mAdapter);
    }

    public static class MyAdapter extends FragmentPagerAdapter {
        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public int getCount() {
            return NUMBER_OF_PAGES;
        }

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return FragmentOne.newInstance(0, Color.WHITE);
                case 1:
                    // return a different Fragment class here
                    // if you want want a completely different layout
                    return FragmentOne.newInstance(1, Color.CYAN);
                default:
                    return null;
            }
        }
    }

    public static class FragmentOne extends Fragment {

        private static final String MY_NUM_KEY = "num";
        private static final String MY_COLOR_KEY = "color";

        private int mNum;
        private int mColor;

        // You can modify the parameters to pass in whatever you want
        static FragmentOne newInstance(int num, int color) {
            FragmentOne f = new FragmentOne();
            Bundle args = new Bundle();
            args.putInt(MY_NUM_KEY, num);
            args.putInt(MY_COLOR_KEY, color);
            f.setArguments(args);
            return f;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mNum = getArguments() != null ? getArguments().getInt(MY_NUM_KEY) : 0;
            mColor = getArguments() != null ? getArguments().getInt(MY_COLOR_KEY) : Color.BLACK;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_one, container, false);
            v.setBackgroundColor(mColor);
            TextView textView = v.findViewById(R.id.textview);
            textView.setText("Page " + mNum);
            return v;
        }
    }
}

Jadi

Anda harus dapat menjalankan aplikasi dan melihat hasilnya di animasi di atas.

Lihat juga

Suragch
sumber
3
Kode terbangun dengan baik, hanya perlu 1 bantuan kecil. Dalam Kode saat ini kita perlu menggesek dari bawah ke atas untuk mendapatkan halaman berikutnya, tetapi saya ingin bahkan menggesek kecil juga harus mendapatkan halaman berikutnya.
AMIT
14

Untuk seseorang yang berjuang dengan cara membuat ViewPager vertikal bekerja di dalam horisontal, lakukan saja hal-hal berikut:

ViewPager Vertikal

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

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

    private void init() {
        setPageTransformer(true, new VerticalPageTransformer());
        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    private class VerticalPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View view, float position) {

            if (position < -1) {
                view.setAlpha(0);
            } else if (position <= 1) {
                view.setAlpha(1);

                view.setTranslationX(view.getWidth() * -position);

                float yPosition = position * view.getHeight();
                view.setTranslationY(yPosition);
            } else {
                view.setAlpha(0);
            }
        }
    }

    private MotionEvent swapXY(MotionEvent ev) {
        float width = getWidth();
        float height = getHeight();

        float newX = (ev.getY() / height) * width;
        float newY = (ev.getX() / width) * height;

        ev.setLocation(newX, newY);

        return ev;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
        swapXY(ev);
        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(swapXY(ev));
    }

}

Tampilan Halaman Horisontal

public class HorizontalViewPager extends ViewPager {
    private GestureDetector xScrollDetector;

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

    public HorizontalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        xScrollDetector = new GestureDetector(getContext(), new XScrollDetector());
    }

    class XScrollDetector extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return Math.abs(distanceX) > Math.abs(distanceY);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (xScrollDetector.onTouchEvent(ev)) {
            super.onInterceptTouchEvent(ev);
            return true;
        }

        return super.onInterceptTouchEvent(ev);
    }

}
Penyelam
sumber
Bagaimana saya bisa menambahkan pager tampilan horisontal dan vertikal ini ke tampilan saya?
user1810931
Mulailah dengan tutorial - vogella.com/tutorials/AndroidCustomViews/article.html
Penyelam
Bagaimana cara menerapkan kelas pager tampilan Horizontal dan Vertikal di atas dalam pandangan saya? Cuplikan kode membantu
user1810931
ViewPager sudah melihat, saya tidak mengerti apa yang Anda tanyakan.
Penyelam
Saya menggunakan perpustakaan yang disebut "Tampilan Kalender Bahan" ( github.com/prolificinteractive/material-calendarview ) dan sudah memiliki viewpager horizontal di dalamnya dan saya ingin menambahkan viewpager vertikal di dalamnya.
user1810931
8

Sedikit ekstensi jawaban ini membantu saya mencapai persyaratan saya (Pager Tampilan Vertikal untuk menghidupkan serupa seperti di Inshorts - Berita dalam 60 kata )

public class VerticalViewPager extends ViewPager {

public VerticalViewPager(Context context) {
    super(context);
    init();
}

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

private void init() {
    // The majority of the magic happens here
    setPageTransformer(true, new VerticalPageTransformer());
    // The easiest way to get rid of the overscroll drawing that happens on the left and right
    setOverScrollMode(OVER_SCROLL_NEVER);
}

private class VerticalPageTransformer implements ViewPager.PageTransformer {
 private static final float MIN_SCALE = 0.75f;
    @Override
    public void transformPage(View view, float position) {

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        }  else if (position <= 0) { // [-1,0]
            // Use the default slide transition when moving to the left page
            view.setAlpha(1);
            // Counteract the default slide transition
            view.setTranslationX(view.getWidth() * -position);

            //set Y position to swipe in from top
            float yPosition = position * view.getHeight();
            view.setTranslationY(yPosition);
            view.setScaleX(1);
            view.setScaleY(1);

        } else if (position <= 1) { // [0,1]
            view.setAlpha(1);

            // Counteract the default slide transition
            view.setTranslationX(view.getWidth() * -position);


            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }

    }

}

/**
 * Swaps the X and Y coordinates of your touch event.
 */
private MotionEvent swapXY(MotionEvent ev) {
    float width = getWidth();
    float height = getHeight();

    float newX = (ev.getY() / height) * width;
    float newY = (ev.getX() / width) * height;

    ev.setLocation(newX, newY);

    return ev;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev){
    boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
    swapXY(ev); // return touch coordinates to original reference frame for any child views
    return intercepted;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    return super.onTouchEvent(swapXY(ev));
}
}

Saya harap ini bisa membantu orang lain.

Amrut Bidri
sumber
1
Nilai ideal untuk MIN_SCALE?
divyenduz
Tidakkah Anda menemukan masalah dengan menggesek dengan cepat transisi tidak mulus
Praneeth
Mengapa seseorang menggesek dengan cepat?
Amrut Bidri
Hanya komentar untuk diklarifikasi: Solusi ini mengubah animasi sedemikian rupa sehingga halaman baru tidak berasal dari bawah tetapi dari belakang halaman lama. Jadi pada dasarnya Anda tidak memiliki halaman yang diletakkan bersebelahan, melainkan setumpuk halaman, saling bertumpukan. Jadi, solusi ini mungkin bukan apa yang coba dilakukan oleh pertanyaan awal.
Benjamin Basmaci
4

Ada beberapa proyek open source yang mengklaim melakukan ini. Di sini mereka:

Ini telah ditandai tidak digunakan oleh penulisnya:

Dan satu hal lagi:

Flimm
sumber
3

Lihat ini: https://github.com/JakeWharton/Android-DirectionalViewPager

Atau pertanyaan berikut dapat membantu Anda: 'Gridview with pages' atau 'Viewpager' Vertikal

sdabet
sumber
2
Yang perlu diingat adalah bahwa DirectionalViewPagerbelum diperbarui untuk beberapa waktu dan karenanya kehilangan beberapa fitur yang lebih baru ViewPagerdi perpustakaan dukungan; yaitu setPageMargin(int). Secara umum itu harus melakukan pekerjaannya. Dan jika tidak, tidak terlalu sulit untuk mengambil kode sumber ViewPagerdan menukar semua x / y dan logika lebar / tinggi.
MH.
Saya sudah mempertimbangkan, DirectionalViewPagertetapi, seperti yang dikatakan MH, itu tidak diperbarui (pengembangnya menganggapnya TERGANGGU) !! Sungguh luar biasa bahwa pengembang Android tidak menyediakan untuk komunitas secara vertikal ViewPager, tetapi hanya horisontal. Saya lebih baru ke Android, mengembangkan ViewPagerpertukaran vertikal saya x / y tidak begitu mudah bagi saya .. saya lebih suka solusi yang sudah dibangun .. lagi pula, terima kasih
user1709805
2
hai, apakah Anda berhasil melakukan viewpager vertikal ?? thansk
Paul
3

Hanya peningkatan pada jawaban dari @ Brett dan @ Salman666 untuk mengubah koordinat (X, Y) menjadi (Y, X) dengan benar karena tampilan perangkat berbentuk persegi panjang:

...

/**
 * Swaps the X and Y coordinates of your touch event
 */
@Override
public boolean onTouchEvent(MotionEvent ev) {
    return super.onTouchEvent(swapXY(ev));
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return super.onInterceptTouchEvent(swapXY(ev));
}

private MotionEvent swapXY(MotionEvent ev) {

    //Get display dimensions
    float displayWidth=this.getWidth();
    float displayHeight=this.getHeight();

    //Get current touch position
    float posX=ev.getX();
    float posY=ev.getY();

    //Transform (X,Y) into (Y,X) taking display dimensions into account
    float newPosX=(posY/displayHeight)*displayWidth;
    float newPosY=(1-posX/displayWidth)*displayHeight;

    //swap the x and y coords of the touch event
    ev.setLocation(newPosX, newPosY);

    return ev;
}

...

Namun, masih ada sesuatu yang perlu dilakukan untuk lebih responsif layar sentuh. Masalahnya mungkin terkait dengan apa yang @msdark mengomentari jawaban @ Salman666.

Anonim
sumber
Saya memiliki beberapa perbaikan dengan selalu kembali truedi onInterceptTouchEventdan saya juga telah memodifikasi binding kunci, sehingga menggunakan DPAD itu memicu scroll dengan UP / DOWN bukannya kiri / kanan: gist.github.com/zevektor/fbacf4f4f6c39fd6e409
Vektor88
@ Vektor88 selalu kembali benar akan mencegah pandangan dalam menerima acara sentuh .. solusi terbaik adalah seperti dalam jawaban brett ..
Mohammad Zekrallah
2
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class VerticalViewPager extends ViewPager {

    public VerticalViewPager(Context context) {
        super(context);
        init();
    }


    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    private void init() {

        setPageTransformer(true, new VerticalPageTransformer());

        setOverScrollMode(OVER_SCROLL_NEVER);
    }

    private class VerticalPageTransformer implements PageTransformer {

        @Override
        public void transformPage(View view, float position) {
            int pageWidth = view.getWidth();
            int pageHeight = view.getHeight();

            if (position < -1) {

                view.setAlpha(0);

            } else if (position <= 1) {
                view.setAlpha(1);


                view.setTranslationX(pageWidth * -position);


                float yPosition = position * pageHeight;
                view.setTranslationY(yPosition);

            } else {

                view.setAlpha(0);
            }
        }
    }
        @Override
    public boolean onTouchEvent(MotionEvent ev) {

        ev.setLocation(ev.getY(), ev.getX());

        return super.onTouchEvent(ev);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        ev.setLocation(ev.getY(), ev.getX());
        return super.onInterceptTouchEvent(ev);
    }
}
Salman666
sumber
1
Ini bekerja sangat bagus, tetapi saya kehilangan touchEvent pada elemen atau peristiwa menggesek kiri / ...
matiasfha
0

Sebenarnya sudah ada satu di sumber Android . Saya telah memodifikasinya agar berfungsi lebih baik:

package com.crnlgcs.sdk.widgets;



import android.content.Context;
import android.support.v4.view.ViewConfigurationCompat;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewParent;

public class VerticalViewPager extends ViewPager {
    private static final String TAG = "VerticalViewPager";
    private static final boolean DEBUG = true;

    private float mLastMotionX;
    private float mLastMotionY;
    private float mTouchSlop;
    private boolean mVerticalDrag;
    private boolean mHorizontalDrag;

    // Vertical transit page transformer
    private final ViewPager.PageTransformer mPageTransformer = new ViewPager.PageTransformer() {
        @Override
        public void transformPage(View view, float position) {
            final int pageWidth = view.getWidth();
            final int pageHeight = view.getHeight();
            if (position < -1) {
                // This page is way off-screen to the left.
                view.setAlpha(0);
            } else if (position <= 1) {
                view.setAlpha(1);
                // Counteract the default slide transition
                view.setTranslationX(pageWidth * -position);
                // set Y position to swipe in from top
                float yPosition = position * pageHeight;
                view.setTranslationY(yPosition);
            } else {
                // This page is way off-screen to the right.
                view.setAlpha(0);
            }
        }
    };

    public VerticalViewPager(Context context) {
        super(context, null);
    }

    public VerticalViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        final ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
        init();
    }

    private void init() {
        // Make page transit vertical
        setPageTransformer(true, mPageTransformer);
        // Get rid of the overscroll drawing that happens on the left and right (the ripple)
        setOverScrollMode(View.OVER_SCROLL_NEVER);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        final float x = ev.getX();
        final float y = ev.getY();

        if (DEBUG) Log.v(TAG, "onTouchEvent " + x + ", " + y);

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                mLastMotionX = x;
                mLastMotionY = y;
                if (!super.onTouchEvent(ev))
                    return false;
                return verticalDrag(ev);
            }
            case MotionEvent.ACTION_MOVE: {
                final float xDiff = Math.abs(x - mLastMotionX);
                final float yDiff = Math.abs(y - mLastMotionY);
                if (!mHorizontalDrag && !mVerticalDrag) {
                    if (xDiff > mTouchSlop && xDiff > yDiff) { // Swiping left and right
                        mHorizontalDrag = true;
                    } else if (yDiff > mTouchSlop && yDiff > xDiff) { //Swiping up and down
                        mVerticalDrag = true;
                    }
                }
                if (mHorizontalDrag) {
                    return super.onTouchEvent(ev);
                } else if (mVerticalDrag) {
                    return verticalDrag(ev);
                }
            }
            case MotionEvent.ACTION_UP: {
                if (mHorizontalDrag) {
                    mHorizontalDrag = false;
                    return super.onTouchEvent(ev);
                }
                if (mVerticalDrag) {
                    mVerticalDrag = false;
                    return verticalDrag(ev);
                }
            }
        }
        // Set both flags to false in case user lifted finger in the parent view pager
        mHorizontalDrag = false;
        mVerticalDrag = false;

        return false;
    }


    private boolean verticalDrag(MotionEvent ev) {
        final float x = ev.getX();
        final float y = ev.getY();
        ev.setLocation(y, x);
        return super.onTouchEvent(ev);
    }
}
phreakhead
sumber
ini tidak berfungsi sebagaimana mestinya .. bahkan versi sumber android tidak .. glitchy dan hanya berfungsi untuk gerakan kanan / kiri .. jika Anda melakukan naik / turun itu tidak menggulir .. setidaknya untuk saya ..
Mohammad Zekrallah
0

Repositori yang saat ini lebih aktif adalah lsjwzh / RecyclerViewPager .

  • komit terakhir 12 Agustus 2016, 16 Kontributor, 1840 bintang
  • berdasarkan RecyclerView
ford04
sumber
0

Ini adalah implementasi ViewPager yang dapat digulir vertikal. Bekerja dengan baik dengan RecyclerView dan ListView. guochong / VerticalViewPager .

gunakan ViewPager.PageTransformer untuk membuat gulir ViewPager secara vertikal, dan juga menyediakan View.OnTouchListener untuk menangani konflik gulir.

/**
 * 1.dispatch ACTION_DOWN,ACTION_UP,ACTION_CANCEL to child<br>
 * 2.hack ACTION_MOVE
 *
 * @param v
 * @param e
 * @return
 */
@Override
public boolean onTouch(View v, MotionEvent e) {
    Log.i(TAG, "onTouchEvent " + ", action " + e.getAction() + ", e.rawY " + e.getRawY() + ",lastMotionY " + lastMotionY + ",downY " + downY);
    switch (e.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downY = e.getRawY();
            break;
        case MotionEvent.ACTION_MOVE:

            if (downY == Float.MIN_VALUE && lastMotionY == Float.MIN_VALUE) {
                //not start from MOTION_DOWN, the child dispatch this first motion
                downY = e.getRawY();
                break;
            }

            float diff = e.getRawY() - (lastMotionY == Float.MIN_VALUE ? downY : lastMotionY);
            lastMotionY = e.getRawY();
            diff = diff / 2; //slow down viewpager scroll
            Log.e(TAG, "scrollX " + dummyViewPager.getScrollX() + ",basescrollX " + dummyViewPager.getBaseScrollX());

            if (dummyViewPager.getScrollX() != dummyViewPager.getBaseScrollX()) {
                if (fakeDragVp(v, e, diff)) return true;
            } else {
                if (ViewCompat.canScrollVertically(v, (-diff) > 0 ? 1 : -1)) {
                    Log.e(TAG, "scroll vertically  " + diff + ", move.lastMotionY " + e.getY());
                    break;
                } else {
                    dummyViewPager.beginFakeDrag();
                    fakeDragVp(v, e, diff);
                    adjustDownMotion(v, e);
                    return true;
                }
            }

            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            if (dummyViewPager.isFakeDragging()) {
                try {
                    dummyViewPager.endFakeDrag();
                } catch (Exception e1) {
                    Log.e(TAG, "", e1);
                }
            }
            reset();
            break;
    }

    return false;
}
chad
sumber
Selamat datang di StackOverflow dan terima kasih atas bantuan Anda. Anda mungkin ingin membuat jawaban Anda lebih baik dengan menambahkan beberapa kode.
Elias MP
0

Bahkan saya menghadapi masalah yang sama dengan membuat ViewPager vertikal dengan menukar X dan Y. Itu sama sekali tidak mulus.

Itu karena dulu hanya bekerja ketika sudut menggesekkan kurang dari 7,125 derajat = arctan (1/8) saat mencegat dan 14 derajat = arctan (1/4) saat disentuh; sebagai ViewPager horizontal asli berfungsi ketika sudut gesek kurang dari 26,565 derajat = arctan (1/2) saat mencegat dan 45 derajat = arctan (1) saat disentuh.

Itu sebabnya saya menyalin kode Android support-core-ui dan memindahkan nilai ke variabel, yang saya kalikan menggunakan refleksi.

Silakan cari kode dan README di https://github.com/deepakmishra/verticalviewpager dan VerticalViewPager di https://github.com/deepakmishra/verticalviewpager/blob/master/app/src/main/java/com/viewpager/VerticalViewPager .Jawa

Deepak
sumber
0

cara yang lebih baik adalah memutar viewpager dengan 90 derajat, dan menggunakan constraintLayout untuk menyesuaikan lokasi.

Jackui
sumber
0

Saya akhirnya menciptakan DirectionalViewPager baru yang dapat menggulir baik secara vertikal maupun horizontal karena semua solusi yang saya lihat di sini memiliki kekurangan:

  1. Implementasi VerticalViewPager yang ada (oleh castorflex dan LambergaR)

    • Mereka didasarkan pada versi perpustakaan dukungan yang sangat lama.
  2. Trik transformasi dengan koordinat swapping

    • Overscroller masih ditampilkan dari tepi kiri / kanan.
    • Halaman melempar tidak berfungsi dengan baik, karena bahkan dengan koordinat yang ditukar, VelocityTracker.computeCurrentVelocitymasih menghitung kecepatan dengan sumbu X, mungkin karena ini secara internal menggunakan panggilan asli yang mengabaikan pertukaran koordinat.
  3. Lihat rotasi

    • Peretasan yang membutuhkan tampilan setiap anak untuk diputar juga.
    • Jika Anda ingin membaca koordinat untuk hal lain, Anda harus menukar sumbu.
inorichi
sumber