Android: Dikey ViewPager [kapalı]


131

ViewPagerYatay olarak değil de dikey olarak kayan bir a yapmanın bir yolu var mı ?!


1
Dikey bir ViewPager için yeni bir resmi olmayan açık kaynak uygulaması var: Duyuru: plus.google.com/107777704046743444096/posts/1FTJfrvnY8w Kod: github.com/LambergaR/VerticalViewPager
Vasily

Dikey görünüm çağrı cihazı uygulaması, Antoine Merle: github.com/castorflex/VerticalViewPager
micnoy

19 destek kitaplığına dayalı yeni bir uygulama var: github.com/castorflex/VerticalViewPager
Vasily

Bu, benzer bir ada sahip olmasına rağmen github.com/castorflex/VerticalViewPager ile aynı değildir .
Flimm

Yanıtlar:


227

Dikey yanılsaması vermek için ViewPager.PageTransformer kullanabilirsiniz ViewPager. Yatay sürükleme yerine dikey sürükleme ile kaydırmayı başarmak için ViewPagervarsayılan dokunma olaylarını geçersiz kılmanız ve MotionEventbunları işlemeden önce koordinatlarını değiştirmeniz gerekir, örneğin:

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

}

Elbette bu ayarları uygun gördüğünüz şekilde değiştirebilirsiniz. Böyle görünerek biter:

VerticalViewPager demosu


4
@Der Golem bunun için düzen nasıl kullanılır?
bShah

Tam olarak soru nedir? Bu arada, cevabı göndermedim, sadece referans resmi ekledim.
Phantômaxx

1
@Brett bu örnekte sola ve sağa kaydırmada bazı eylemler gerçekleştirmek istiyorum. nasıl yapılır
Prabs

1
@Brett beklendiği gibi çalışıyor, geçiş dikey gidiyor. Ancak sorun şu ki, geçiş yapmak için sağa / sola kaydırmam gerekiyor ve yukarı / aşağı kaydırırken geçiş gerçekleşmiyor.
Karan Khurana

2
@Brett senin çözümünü kullanıyordum. ama şimdi andorid pasta cihazlarında swipping sorununu alıyorum. Aynı sorunla karşılaşan var mı?
Jishant

21

Benim için iki adımda çalışan bir çözümüm var.

  1. onInstantiateItem()arasında PagerAdapter, görünümü oluşturmak ve -90 ile döndürün:

    view.setRotation(-90f)

    Eğer kullanıyorsanız FragmentPagerAdapter, o zaman:

    objFragment.getView().setRotation(-90)
  2. ViewPagerGörünümü 90 derece döndür :

    objViewPager.setRotation(90)

En azından benim ihtiyacım için bir cazibe gibi çalışıyor.


4
bu çözüm işe yarıyor, ANCAK viewPager artık dikey olarak kaydırılırken yine de yatay olarak kaydırmanız gerekiyor
leochab

@Kulai Burada ne yapacağımı bilmiyorum, anlayışıma göre biraz açıklayabilir misiniz, burada public Object instantiateItem (ViewGroup container, int position) var burada container.setRotation (-90f) yapmamız gerekiyor;
varun

1
Bunu yapmak bir cazibe gibi çalışır! Görüntü üst ve alt kısımda kesilse de nedenini anlayamıyorum: - /
Nivaldo Bondança

2
Dikdörtgen için değil kare görüntü için düzgün çalışır. Bir dikdörtgen döndürüldüğünde boyutlar yanlış gider.
Kulai

1
Bu yanıtı kimin artırdığından emin değilim. bu VerticalViewPager değil, bu ViewPager 90 derece döndürülmüş, hareket ve geçiş tam tersi. ve bu hiç de doğal değil
droidev

20

Dikey ViewPager

Buradaki diğer cevapların hepsinin onlarla bazı sorunları var gibiydi. Önerilen açık kaynaklı projeler bile son çekme isteklerini hata düzeltmeleriyle birleştirmiyordu. Sonra VerticalViewPagerGoogle'dan bir DeskClock uygulaması kullandıklarını buldum . Google'ın uygulamasını kullanmaya, burada dolaşan diğer cevaplardan çok daha fazla güveniyorum. (Google'ın sürümü mevcut en çok oylanan yanıta benzer, ancak daha kapsamlı.)

Tam Örnek

Bu örnek, temel ViewPager Örneğimle neredeyse tamamen aynıdır , VerticalViewPagersınıftan yararlanmak için birkaç küçük değişiklik vardır .

görüntü açıklamasını buraya girin

XML

Ana aktivite ve her sayfa (parça) için xml düzenlerini ekleyin. VerticalViewPagerStandart yerine kullandığımızı unutmayın ViewPager. Bunun kodunu aşağıya ekleyeceğim.

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>

kod

İçin kod VerticalViewPagerbenim değil. Yalnızca Google kaynak kodundan (yorum içermeyen) soyulmuş bir sürümdür. En güncel sürüm için buna göz atın. Buradaki yorumlar, neler olduğunu anlamak için de yararlıdır.

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

Sadece takas VerticalViewPageriçin 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;
        }
    }
}

bitmiş

Uygulamayı çalıştırabilmeli ve sonucu yukarıdaki animasyonda görebilmelisiniz.

Ayrıca bakınız


3
Kod iyi çalışıyor, sadece 1 küçük yardıma ihtiyacımız var Mevcut Kod'da bir sonraki sayfaya geçmek için aşağıdan yukarıya kaydırmamız gerekiyor, ancak küçük kaydırmanın bile bir sonraki sayfayı almasını istiyorum.
AMIT

14

Dikey ViewPager'ın yatay olarak nasıl çalışacağı konusunda mücadele eden biri için, aşağıdaki işlemleri yapmanız yeterlidir:

Dikey ViewPager

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

}

Yatay ViewPager

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

}

Bu yatay ve dikey görüntülü çağrı cihazını görünümüme nasıl ekleyebilirim?
user1810931


Yukarıdaki Yatay ve Dikey görünüm çağrı cihazı sınıflarını kendi görünümüme nasıl uygulayabilirim? Kod parçacığı yardımcı olur
user1810931

ViewPager zaten görüntüleniyor, ne sorduğunuzu anlamıyorum.
Dalgıçlar

"Material Calendar View" ( github.com/prolificinteractive/material-calendarview ) adlı bir kitaplık kullanıyorum ve içinde zaten yatay görüntüleyici var ve içine dikey görüntüleyici eklemek istedim.
user1810931

8

Bu yanıtın küçük bir uzantısı, ihtiyacımı karşılamama yardımcı oldu ( Inshorts'taki gibi benzer animasyon yapmak için Dikey Görünüm Çağrı Cihazı - 60 kelimeyle Haberler )

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

Umarım bu başka birine yardımcı olabilir.


1
MIN_SCALE için ideal değer?
divyenduz


Neden birisi hızlıca yukarı kaydırsın?
Amrut Bidri

Açıklığa kavuşturmak için sadece bir yorum: Bu çözüm, animasyonu yeni sayfanın aşağıdan değil, eski sayfanın arkasından gelecek şekilde değiştirir. Yani temelde yan yana duran sayfalarınız yok, bunun yerine birbirinin üzerine yerleştirilmiş bir yığın sayfa var. Dolayısıyla bu çözüm, asıl sorunun yapmaya çalıştığı şey olmayabilir.
Benjamin Basmaci

4

Bunu yaptığını iddia eden birkaç açık kaynaklı proje var. İşte buradalar:

Bunlar, yazarları tarafından kullanımdan kaldırıldı olarak işaretlendi:

Ve bir şey daha:


3

2
Unutulmaması gereken bir şey, DirectionalViewPageruzun bir süredir güncellenmemiş ve bu nedenle ViewPagerdestek kitaplığındaki bazı yeni özelliklerin eksik olmasıdır ; yani setPageMargin(int). Genelde işi yapmalı. Ve değilse, kaynak kodunu ViewPageralıp tüm x / y ve genişlik / yükseklik mantığını değiştirmek çok zor değil .
MH.

Zaten dikkate aldım, DirectionalViewPagerancak MH'nin söylediği gibi güncellenmedi (geliştiricisi bunu KULLANIMDAN KALDIRILDI olarak kabul ediyor) !! Android geliştiricilerinin topluluğa bir dikey ViewPagerdeğil, yalnızca yatay bir alan sağlamış olması inanılmaz . Android'de daha yeniyim, dikey ViewPagergeçişimi geliştirmek x / y benim için o kadar kolay değil .. zaten oluşturulmuş bir çözümü tercih ederim .. neyse, teşekkür ederim
user1709805

2
merhaba, dikey görüntüleyiciyi yapmayı başardınız mı? thansk
Paul

3

Cihaz ekranları dikdörtgen olduğundan koordinatları (X, Y) (Y, X) 'e doğru şekilde dönüştürmek için @Brett ve @ Salman666'dan gelen yanıtlarda bir iyileştirme :

...

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

...

Bununla birlikte, dokunmatik ekran duyarlılığını iyileştirmek için hala bir şeyler yapılması gerekiyor. Sorun, @msdark'ın @ Salman666'nın cevabına yaptığı yorumla ilgili olabilir.


Hep döndürerek bazı geliştirmeler var trueiçinde onInterceptTouchEventve ben de, Anahtar bağlamaları modifiye yüzden YUKARI / AŞAĞI ile kaydırma tetikleyen bir DPAD'yi kullanarak yerine sol / sağ ettik: gist.github.com/zevektor/fbacf4f4f6c39fd6e409
Vektor88

@ Vektor88'in her zaman doğruya dönmesi, iç görüşlerin dokunma olaylarını almasını engelleyecektir .. en iyi çözüm brett cevabındaki gibidir ..
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
Bu çok iyi çalışıyor, ancak öğelerde veya solda / kaydırma olaylarında
touchEvent'i kaybediyorum

0

Aslında Android kaynağında zaten bir tane var . Yine de daha iyi çalışması için değiştirdim:

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

bu düzgün çalışmıyor .. android kaynak versiyonu bile arızalı ve sadece sağ / sol hareketler için çalışıyor .. yukarı / aşağı yaparsanız kaymıyor .. en azından benim için ..
Mohammad Zekrallah


0

Bu, dikey kaydırılabilir bir ViewPager uygulamasıdır. RecyclerView ve ListView ile iyi çalışır. guochong / VerticalViewPager .

ViewPager.PageTransformer'ı, ViewPager'ın dikey olarak kaydırmasını sağlamak için kullanın ve ayrıca kaydırma çakışmasıyla başa çıkmak için bir View.OnTouchListener sağlayın.

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

StackOverflow'a hoş geldiniz ve yardımınız için teşekkürler. Biraz kod ekleyerek cevabınızı daha da iyi hale getirmek isteyebilirsiniz.
Elias MP

0

Ben bile X ve Y'yi değiştirerek ViewPager'ı dikey yapmakla aynı problemle karşı karşıyaydım. Hiç de pürüzsüz değildi.

Bunun nedeni, yalnızca kaydırma açısı 7.125 derece = arktan (1/8) iken kesişme ve dokunma sırasında 14 derece = arktan (1/4) 'den az olduğunda çalışıyordu; orijinal ViewPager yatay olarak biri, kaydırma açısı 26,565 derece = arktan (1/2) iken kesişme ve 45 derece = arktan (1) dokunma açısında olduğunda çalışır.

Bu yüzden Android support-core-ui kodunu kopyaladım ve değerleri yansıma kullanarak çarptığım değişkenlere taşıdım.

Lütfen kodu ve README'yi https://github.com/deepakmishra/verticalviewpager ve VerticalViewPager adresinde https://github.com/deepakmishra/verticalviewpager/blob/master/app/src/main/java/com/viewpager/VerticalViewPager adresinde bulun .java


0

daha iyi yol, görüntüleyiciyi 90 derece döndürmek ve konumu ayarlamak için constraintLayout kullanmaktır.


0

Dikey veya yatay olarak kaydırabilen yeni bir DirectionalViewPager oluşturdum çünkü burada gördüğüm tüm çözümlerin kusurları var:

  1. Mevcut VerticalViewPager uygulamaları (castorflex ve LambergaR tarafından)

    • Çok eski destek kitaplığı sürümlerine dayalıdırlar.
  2. Koordinat değişimiyle dönüşüm hilesi

    • Aşırı kaydırıcı hala sol / sağ kenarlardan gösterilmektedir.
    • Sayfa fırlatma düzgün çalışmıyor, çünkü koordinatlar değiştirilse bile VelocityTracker.computeCurrentVelocity, hızı X ekseniyle hesaplamaya devam ediyor, çünkü bu muhtemelen dahili olarak koordinat değişimini yok sayan yerel bir çağrı kullanıyor.
  3. Rotasyonu görüntüle

    • Her çocuk görüşünün de döndürülmesini gerektiren bir hack.
    • Koordinatları başka bir şey için okumak istiyorsanız, ekseni değiştirmelisiniz.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.