Android: вертикальний переглядач [закрито]


130

Чи є спосіб зробити таке ViewPager, яке прокручується не по горизонталі, а по вертикалі ?!


1
З'явилася нова неофіційна реалізація вертикального коду з відкритим кодом: Повідомлення: plus.google.com/107777704046743444096/posts/1FTJfrvnY8w Код: github.com/LambergaR/VerticalViewPager
Василь Сочинський

Реалізація пейджера вертикального перегляду від Антуана Мерле: github.com/castorflex/VerticalViewPager
micnoy

Існує нова реалізація, заснована на 19 бібліотеці підтримки: github.com/castorflex/VerticalViewPager
Василь Сочинський

Це не те саме, що github.com/castorflex/VerticalViewPager , незважаючи на те, що має схожу назву.
Flimm

1
Існує контроль під назвою ViewPager2 перевірити тут на демо stackoverflow.com/a/54643817/7666442
Nilesh Rathod

Відповіді:


227

Ви можете використовувати ViewPager.PageTransformer, щоб створити ілюзію вертикалі ViewPager. Щоб досягти прокрутки вертикальною замість горизонтального перетягування, вам доведеться переосмислити ViewPagerподії, що торкаються за замовчуванням, і поміняти координати MotionEvents перед початком обробки, наприклад:

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

}

Звичайно, ви можете налаштувати ці налаштування так, як вважаєте за потрібне. Закінчується так:

Демонстрація VerticalViewPager


3
@Der Golem як використовувати макет для цього?
bShah

Яке саме питання? До речі, відповіді я не розмістив, просто додав згадане зображення.
Phantômaxx

1
@Brett у цьому прикладі я хочу виконати деяку дію пальцем ліворуч та праворуч. як це зробити
Prabs

1
@Brett працює як слід, перехід бере вертикально. Але проблема полягає в тому, що мені потрібно провести пальцем вправо / вліво, щоб зробити перехід, і при проведенні пальцем зверху / знизу перехід не відбудеться.
Каран Хурана

2
@Brett Я використовував ваше рішення. але зараз я переживаю проблему прокручування в пристроях з андроїдним пирогом. Хтось стикається з тим же питанням?
Джишант

20

Вертикальний ViewPager

Інші відповіді тут, здавалося, мали деякі проблеми з ними. Навіть рекомендовані проекти з відкритим кодом не об'єднували останні запити на витяг із виправленнями помилок. Потім я виявив VerticalViewPagerвід Google, що вони використовували якийсь додаток DeskClock. Я вірю, що використовую впровадження Google набагато більше, ніж інші відповіді, що плавають тут. (Версія Google схожа на поточну відповідь, де голосують, але більш ретельно.)

Повний приклад

Цей приклад майже точно такий же, як і в моєму базовому прикладі ViewPager , з декількома незначними змінами для використання VerticalViewPagerкласу.

введіть тут опис зображення

XML

Додайте макети xml для основної діяльності та для кожної сторінки (фрагмента). Зауважте, що ми використовуємо, VerticalViewPagerа не стандарт ViewPager. Я включу код для цього нижче.

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>

Код

Код для VerticalViewPagerне мій. Це лише знята версія (без коментарів) з вихідного коду Google. Ознайомтеся з цією найновішою версією. Зауваження там також корисні для розуміння того, що відбувається.

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

Я тільки вивантажено VerticalViewPagerна 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;
        }
    }
}

Готово

Ви повинні мати змогу запустити додаток і побачити результат у анімації вище.

Дивитися також


3
Код добре прокидається, просто потрібна 1 невелика допомога. У поточному Кодексі нам потрібно провести знизу вгору, щоб отримати наступну сторінку, але я хочу, щоб навіть невеликий пальцем також мав отримати наступну сторінку.
AMIT

20

У мене є рішення, яке працює для мене в два кроки.

  1. onInstantiateItem()з PagerAdapter, створити уявлення і повернути його на -90:

    view.setRotation(-90f)

    Якщо ви використовуєте FragmentPagerAdapter, то:

    objFragment.getView().setRotation(-90)
  2. Повернути ViewPagerпогляд на 90 градусів:

    objViewPager.setRotation(90)

Працює як шарм принаймні для моєї вимоги.


4
це рішення працює, Але вам все одно потрібно пальцем по горизонталі, тоді як viewPager зараз прокручується вертикально
leochab

@Kulai Мені не зрозуміло, що тут робити. Чи можете ви, будь ласка, пояснити трохи, наскільки я розумію, у нас є загальнодоступний Object instantiateItem (контейнер ViewGroup, int position), тут нам потрібно зробити контейнер.setRotation (-90f);
varun

1
Це працює як шарм! Але все-таки вигляд розрізається у верхній та нижній частині, і я не можу зрозуміти, чому: - /
Нівальдо Бонданьча

2
Він працює правильно для квадратного зображення, а не для прямокутного. Розміри йдуть неправильно при обертанні прямокутника.
Кулай

1
Я не впевнений, хто голосував за цю відповідь. це не VerticalViewPager, це ViewPager з поворотом на 90 градусів, жест і перехід - навпаки. і це зовсім не природно
droidev

14

Для тих, хто бореться з тим, як зробити так, щоб вертикальний ViewPager працював всередині горизонталі, просто виконайте такі дії:

Вертикальний 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));
    }

}

Горизонтальний переглядач

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

}

Як додати цей горизонтальний та вертикальний пейджер для перегляду?
користувач1810931

Почніть з підручника - vogella.com/tutorials/AndroidCustomViews/article.html
Дайвери

Як я можу реалізувати наведені вище горизонтальні та вертикальні класи пейджера перегляду? Фрагмент коду допомагає
користувач1810931

ViewPager вже переглядає, я не розумію, про що ви питаєте.
Дайвери

Я використовую бібліотеку під назвою "Перегляд матеріального календаря" ( github.com/prolificinteractive/material-calendarview ), і в неї вже є горизонтальний переглядач, і я хотів додати в неї вертикальний переглядач.
користувач1810931

8

Невелике розширення ця відповідь допомогла мені досягти моєї вимоги (Вертикальний Пейджер перегляду для анімації подібних, як у Inshorts - Новини в 60 слів )

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

Я сподіваюся, що це може бути корисним для когось іншого.


1
Ідеальне значення для MIN_SCALE?
divyenduz

Хіба ви не знайшли проблеми з швидким
розгортанням,

Чому на землі хтось швидко бив?
Amrut Bidri

Лише коментар для уточнення: Це рішення змінює анімацію таким чином, що нова сторінка виходить не знизу, а ззаду старої сторінки. Отже, у вас немає сторінок, що лежать поруч, а колоди сторінок, що лежать одна над одною. Отже, це рішення може бути не тим, що намагається зробити оригінальне питання.
Бенджамін Басмачі

4

Є кілька проектів з відкритим кодом, які претендують на це. Ось вони:

Їх автори були позначені застарілими:

І ще одне:

  • У джерелі Android з deskclockпрограми також є ім'я файлу VerticalViewPager.java , але воно, схоже, офіційно не підтримується, оскільки я не можу знайти документацію на нього.

3

Перевірте це: https://github.com/JakeWharton/Android-DirectionalViewPager

Або наступне питання може вам допомогти: Вертикальний "Gridview зі сторінками" або "Viewpager"


2
Що слід пам’ятати, - це те, що DirectionalViewPagerвоно не оновлювалося довгий час, і, отже, відсутні деякі новіші функції ViewPagerбібліотеки підтримки; тобто setPageMargin(int). Як правило, він повинен робити цю роботу. А якщо ні, то не надто складно захопити вихідний код ViewPagerі замінити всю логіку x / y та ширину / висоту.
МЗ.

Я вже брав до уваги, DirectionalViewPagerале, як сказав МЗ, він не оновлюється (його розробник вважає це ОБЛАДЕНОЮ) !! Неймовірно, що розробники Android не надали спільноті вертикальну ViewPager, а лише горизонтальну. Я новіший для Android, розробити свою вертикальну ViewPagerзаміну x / y для мене не так просто. Я б віддав перевагу вже вбудованому рішенню .. все одно, дякую
user1709805

2
привіт, вам вдалося зробити вертикальний переглядач ?? thansk
Павло

3

Просто поліпшення відповідей від @Brett та @ Salman666 щодо правильного перетворення координат (X, Y) у (Y, X), оскільки дисплеї пристроїв прямокутні:

...

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

...

Однак щось ще потрібно зробити, щоб покращити чутливість сенсорного екрану. Проблема може бути пов’язана з тим, що @msdark прокоментував відповідь @ Salman666.


У мене є деякі поліпшення, завжди повертаючись trueв onInterceptTouchEventі я також змінив прив'язок клавіш, так що з допомогою DPad це викликає сувій з UP / DOWN , а не вліво / вправо: gist.github.com/zevektor/fbacf4f4f6c39fd6e409
Vektor88

@ Vektor88 завжди повертає правду, заважає внутрішнім поглядам отримувати сенсорні події .. найкраще рішення - як у відповіді
Бретта

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
Це дуже добре, але я втрачаю дотик до елементів або подій зліва / проведіть пальцем ...
matiasfha

0

Насправді він вже є в джерелі Android . Я змінив його, щоб він працював краще:

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

це не працює належним чином .. навіть версія Android-джерела не працює .. її глюкіт і працює лише для правого / лівого жестів .. якщо ви робите вгору / вниз, вона не прокручується .. принаймні для мене ..
Мохаммед Зекрала

0

Наразі більш активним сховищем є lsjwzh / RecyclerViewPager .

  • останній комітет 12 серпня 2016 р., 16 учасників, 1840 зірок
  • на основі RecyclerView

0

Це вертикальна реалізація ViewPager, що прокручується. Добре працює з RecyclerView та ListView. guochong / VerticalViewPager .

використовуйте ViewPager.PageTransformer, щоб змусити ViewPager прокручувати вертикально, а також надайте View.OnTouchListener для вирішення конфлікту прокрутки.

/**
 * 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 і дякуємо за вашу допомогу. Ви можете зробити свою відповідь ще кращою, додавши якийсь код.
Еліас МП

0

Навіть я зіткнувся з тією ж проблемою, щоб зробити ViewPager вертикальним, поміняючи X і Y. Це було зовсім не гладко.

Це тому, що він працював лише тоді, коли кут ковзання був менше 7,125 градусів = арктан (1/8) при перехопленні і 14 градусів = арктан (1/4) при дотику; як оригінал ViewPager, горизонтальний - це одна робота, коли кут повороту менше 26,565 градусів = арктан (1/2) при перехопленні і 45 градусів = арктан (1) під час дотику.

Ось чому я скопіював код Android support-core-ui та перемістив значення на змінні, які я помножив за допомогою відображення.

Знайдіть код та README на веб- сайті https://github.com/deepakmishra/verticalviewpager та VerticalViewPager за адресою https://github.com/deepakmishra/verticalviewpager/blob/master/app/src/main/java/com/viewpager/VerticalViewPager .java


0

кращий спосіб - повернути панель перегляду на 90 градусів і використовувати constraintLayout для налаштування місця розташування.


0

Я в кінцевому підсумку створив новий DirectionalViewPager, який може прокручуватися вертикально або горизонтально, оскільки всі рішення, які я тут бачив, мають вади:

  1. Існуючі реалізації VerticalViewPager (від castorflex та LambergaR)

    • Вони засновані на дуже старих версіях бібліотеки підтримки.
  2. Трансформаційний трюк з заміною координат

    • Зліва / правий край все ще відображається.
    • Перегортання сторінки не працює належним чином, оскільки навіть при змінених координатах VelocityTracker.computeCurrentVelocityвсе-таки обчислюється швидкість по осі X, можливо, тому, що для цього використовується внутрішній виклик, який ігнорує підкачки координат.
  3. Перегляд обертання

    • Хак, який потребує кожного дитячого зору, також має бути повернутий.
    • Якщо ви хочете прочитати координати для чогось іншого, вам доведеться поміняти вісь.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.