Android: ViewPager verticale [chiuso]


131

C'è un modo per creare un oggetto ViewPagerche non scorre in orizzontale, ma in verticale ?!


1
Esiste una nuova implementazione non ufficiale open source di un ViewPager verticale: Annuncio: plus.google.com/107777704046743444096/posts/1FTJfrvnY8w Codice: github.com/LambergaR/VerticalViewPager
Vasily Sochinsky

Implementazione del cercapersone con vista verticale di Antoine Merle: github.com/castorflex/VerticalViewPager
micnoy

C'è una nuova implementazione basata sulla libreria di supporto 19: github.com/castorflex/VerticalViewPager
Vasily Sochinsky

Non è lo stesso di github.com/castorflex/VerticalViewPager , nonostante abbia un nome simile.
Flimm,

1
C'è un controllo chiamato ViewPager2 che controlla qui per demo stackoverflow.com/a/54643817/7666442
Nilesh Rathod

Risposte:


227

È possibile utilizzare un ViewPager.PageTransformer per dare l'illusione di una verticale ViewPager. Per ottenere lo scorrimento con un trascinamento verticale anziché orizzontale, dovrai sovrascrivere ViewPagergli eventi tocco predefiniti e scambiare le coordinate di MotionEvents prima di gestirli, ad esempio:

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

}

Ovviamente puoi modificare queste impostazioni come ritieni opportuno. Finisce così:

Demo di VerticalViewPager


4
@Der Golem come utilizzare il layout per questo?
bShah,

Qual è la domanda esatta? A proposito, non ho pubblicato la risposta, ho solo aggiunto l'immagine di riferimento.
Phantômaxx,

1
@ Brett in questo esempio, voglio eseguire alcune azioni scorrendo verso sinistra e verso destra. come farlo
Prabs,

1
@Brett funziona come previsto, la transizione sta prendendo in verticale. Ma il problema è che devo scorrere verso destra / sinistra per eseguire la transizione e al passaggio superiore / inferiore non si verifica alcuna transizione.
Karan Khurana,

2
@Brett Stavo usando la tua soluzione. ma ora sto riscontrando il problema di swipping nei dispositivi a torta andorid. Qualcuno ha affrontato lo stesso problema?
Jishant,

21

Ho una soluzione che funziona per me in due passaggi.

  1. onInstantiateItem()di PagerAdapter, crea la vista e ruotala di -90:

    view.setRotation(-90f)

    Se si utilizza FragmentPagerAdapter, quindi:

    objFragment.getView().setRotation(-90)
  2. Ruota la ViewPagervista di 90 gradi:

    objViewPager.setRotation(90)

Funziona come un fascino almeno per le mie esigenze.


4
questa soluzione funziona, MA devi comunque scorrere orizzontalmente mentre viewPager ora scorre verticalmente
leochab

@Kulai non sono chiaro cosa fare qui, per favore, puoi spiegarci un po ', per quanto ho capito, abbiamo un oggetto pubblico instantiateItem (contenitore ViewGroup, posizione int) qui dobbiamo fare container.setRotation (-90f);
Varun,

1
Farlo funziona come un incantesimo! Althoug la vista viene tagliata nella parte superiore e inferiore e non riesco a capire perché: - /
Nivaldo Bondança,

2
Funziona correttamente per un'immagine quadrata e non per un rettangolare. Le dimensioni vanno male quando viene ruotato un rettangolo.
Kulai,

1
Non sono sicuro chi abbia votato a favore di questa risposta. questo non è VerticalViewPager, questo è ViewPager con rotazione di 90 gradi, il gesto e la transizione sono esattamente opposti. e non è affatto naturale
droidev il

20

ViewPager verticale

Le altre risposte qui sembravano avere dei problemi con loro. Persino i progetti open source raccomandati non univano le recenti richieste pull a correzioni di errori. Poi ho trovato VerticalViewPagerda Google che hanno usato alcune app DeskClock. Confido nell'utilizzare l'implementazione di Google molto più delle altre risposte che fluttuano qui. (La versione di Google è simile all'attuale risposta più votata, ma più approfondita.)

Esempio completo

Questo esempio è quasi identico al mio esempio Basic ViewPager , con alcune piccole modifiche per utilizzare la VerticalViewPagerclasse.

inserisci qui la descrizione dell'immagine

XML

Aggiungi i layout xml per l'attività principale e per ogni pagina (frammento). Nota che usiamo VerticalViewPagerpiuttosto che lo standard ViewPager. Includerò il codice per quello qui sotto.

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>

Codice

Il codice per il VerticalViewPagernon è mio. È solo una versione ridotta (senza commenti) dal codice sorgente di Google. Dai un'occhiata a quello per la versione più aggiornata. I commenti ci sono anche utili per capire cosa sta succedendo.

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

Ho scambiato solo VerticalViewPagerper 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;
        }
    }
}

Finito

Dovresti essere in grado di eseguire l'app e vedere il risultato nell'animazione sopra.

Guarda anche


3
Il codice sta funzionando bene, ho solo bisogno di un piccolo aiuto. Nel codice corrente dobbiamo scorrere dal basso verso l'alto per ottenere la pagina successiva, ma voglio anche un piccolo tocco dovrebbe anche ottenere la pagina successiva.
AMIT

14

Per qualcuno che sta lottando su come far funzionare ViewPager verticale all'interno orizzontale, basta fare le seguenti cose:

ViewPager verticale

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

}

ViewPager orizzontale

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

}

Come posso aggiungere questo cercapersone vista orizzontale e verticale alla mia vista?
user1810931,


Come posso implementare le suddette classi di cercapersone nella vista Orizzontale e Verticale nella mia vista? Lo snippet di codice aiuta
user1810931,

ViewPager è già vista, non capisco cosa stai chiedendo.
Divers

Sto usando una libreria chiamata "Material Calendar View" ( github.com/prolificinteractive/material-calendarview ) e contiene già viewpager orizzontale e volevo aggiungere viewpager verticale.
user1810931,

8

Una leggera estensione di questa risposta mi ha aiutato a raggiungere il mio requisito (Vertical View Pager per animare simili come in Inshorts - Notizie in 60 parole )

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

Spero che questo possa essere utile a qualcun altro.


1
Valore ideale per MIN_SCALE?
divyenduz,

Non hai riscontrato problemi con lo scorrimento veloce della transizione non è regolare
Praneeth,

Perché mai qualcuno dovrebbe scorrere rapidamente?
Amrut Bidri,

Solo un commento per chiarire: questa soluzione modifica l'animazione in modo che la nuova pagina non provenga dal basso ma piuttosto da dietro la vecchia pagina. Quindi in pratica non hai pagine disposte una accanto all'altra, ma piuttosto un mazzo di pagine, sovrapposte. Quindi, questa soluzione potrebbe non essere ciò che la domanda originale sta cercando di fare.
Benjamin Basmaci

4

Ci sono alcuni progetti open source che affermano di farlo. Eccoli:

Questi sono stati contrassegnati come deprecati dai loro autori:

E un'altra cosa:


3

2
Qualcosa da tenere a mente è che DirectionalViewPagernon è stato aggiornato per un po 'di tempo e quindi mancano alcune delle nuove funzionalità di ViewPagernella libreria di supporto; vale a dire setPageMargin(int). Generalmente dovrebbe fare il lavoro però. Altrimenti, non è troppo complicato prendere il codice sorgente ViewPagere scambiare tutta la logica x / y e larghezza / altezza.
MH.

Ho già preso in considerazione il DirectionalViewPagerma, come ha detto MH, non è aggiornato (il suo sviluppatore lo considera DEPRECATO) !! È incredibile che gli sviluppatori Android non abbiano fornito alla community un verticale ViewPager, ma solo orizzontale. Sono più recente di Android, sviluppare il mio ViewPagerscambio verticale x / y non è così facile per me .. Preferirei una soluzione già costruita .. comunque, grazie
user1709805

2
ciao, sei riuscito a fare il viewpager verticale ?? grazie
Paul

3

Solo un miglioramento delle risposte di @Brett e @ Salman666 per trasformare correttamente le coordinate (X, Y) in (Y, X) poiché i display del dispositivo sono rettangolari:

...

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

...

Tuttavia, è ancora necessario fare qualcosa per migliorare la reattività del touchscreen. Il problema potrebbe essere correlato a ciò che @msdark ha commentato sulla risposta di @ Salman666.


Ho dei miglioramenti ritornando sempre true in onInterceptTouchEvente ho anche modificato le associazioni dei tasti, in modo che l'utilizzo di un DPAD innesca scorrere con UP / DOWN invece che a sinistra / destra: gist.github.com/zevektor/fbacf4f4f6c39fd6e409
Vektor88

@ Vektor88 sempre il ritorno vero impedirà alle visioni interne di ricevere eventi tattili .. la migliore soluzione è come nella risposta 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);
    }
}

1
Funziona molto bene, ma perdo il touchEvent sugli elementi o sugli eventi left / swipe ...
matiasfha

0

Ce n'è già uno nella fonte Android . L'ho modificato per funzionare meglio però:

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

questo non funziona correttamente .. anche la versione di Android non funziona .. è glitch e funziona solo con gesti destra / sinistra .. se fai su / giù non scorre .. almeno per me ..
Mohammad Zekrallah,


0

Questa è un'implementazione ViewPager scorrevole verticale. Funziona bene con RecyclerView ed ListView. guochong / VerticalViewPager .

utilizzare ViewPager.PageTransformer per far scorrere ViewPager verticalmente e fornire anche View.OnTouchListener per gestire il conflitto di scorrimento.

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

Benvenuto in StackOverflow e grazie per il tuo aiuto. Potresti voler migliorare la tua risposta aggiungendo del codice.
Elias MP

0

Anche io stavo affrontando lo stesso problema nel rendere ViewPager verticale scambiando X e Y. Non era affatto fluido.

Questo perché funzionava solo quando l'angolo di scorrimento era inferiore a 7.125 gradi = arctan (1/8) mentre intercetta e 14 gradi = arctan (1/4) mentre tocca; come l'originale ViewPager orizzontale funziona quando l'angolo di scorrimento è inferiore a 26.565 gradi = arctan (1/2) mentre intercetta e 45 gradi = arctan (1) mentre tocca.

Ecco perché ho copiato il codice di Android support-core-ui e ho spostato i valori in variabili, che ho moltiplicato usando reflection.

Si prega di trovare il codice e il file README su https://github.com/deepakmishra/verticalviewpager e VerticalViewPager su https://github.com/deepakmishra/verticalviewpager/blob/master/app/src/main/java/com/viewpager/VerticalViewPager .Giava


0

il modo migliore è di ruotare il viewpager di 90 gradi e utilizzare la disposizione di vincolo per regolare la posizione.


0

Ho finito per creare un nuovo DirectionalViewPager che può scorrere sia verticalmente che orizzontalmente perché tutte le soluzioni che ho visto qui hanno dei difetti:

  1. Implementazioni esistenti di VerticalViewPager (di castorflex e LambergaR)

    • Si basano su versioni di librerie di supporto molto vecchie.
  2. Trucco di trasformazione con scambio di coordinate

    • Il overscroller è ancora mostrato dai bordi sinistro / destro.
    • Il flinging della pagina non funziona correttamente, perché anche con le coordinate scambiate, VelocityTracker.computeCurrentVelocitycalcola comunque la velocità con l'asse X, probabilmente perché utilizza internamente una chiamata nativa che ignora lo scambio di coordinate.
  3. Visualizza rotazione

    • Hack che ha bisogno di ruotare anche la vista di ogni bambino.
    • Se vuoi leggere le coordinate per qualcos'altro devi scambiare l'asse.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.