Изменение направления смахивания viewPager

Я использую TabLayout и viewPager с возможностью смахивать viewPager влево или вправо, чтобы перемещаться между страницами.

Моя проблема в том, что мое приложение основано на RTL (справа налево), а направление смахивания обратное.

Я пытаюсь изменить направление смахивания со значения по умолчанию на обратное. Я много искал в Интернете и не мог найти способ, как это сделать.

Я использую android.support.v4.view.ViewPager;

и вот как я инициализирую свой TabLayout с помощью viewPager:

// View Page Adapter
        final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
        final PagerAdapter adapter = new PagerAdapter
                (getSupportFragmentManager(), tabLayout.getTabCount());
        //View Page Adapter Configuration
        viewPager.setAdapter(adapter);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        viewPager.setOffscreenPageLimit(3);
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition());
            }

Сводка: в настоящее время, когда я смахиваю viewPager влево, отображается следующая страница. в RTL, когда вы проводите viewPager вправо, он показывает следующую страницу.

Это может быть трудно понять, но вот оно. Проведите пальцем вправо, чтобы перейти к следующей странице

Смахивание вправо показывает  следующая страница

а мне нужно провести вправо, чтобы открыть предыдущую страницу.


person Eliran    schedule 07.09.2015    source источник
comment
Разве это не вопрос того, чтобы содержимое PagerAdapter было в обратном порядке?   -  person CommonsWare    schedule 07.09.2015
comment
Почему бы просто не установить CurrentItem на последний элемент?   -  person Chris    schedule 07.09.2015
comment
@CommonsWare А что будет, если я проведу пальцем влево? Разве мне не нужно для этого менять onScrollListener? (тот же ответ вам, Крис) Мне нужно изменить направление прокрутки viewPager (смахивание вправо - следующая страница, смахивание влево - предыдущая страница). теперь все наоборот. Вкладки работают отлично, если я выберу одну. смахивание viewPager не работает.   -  person Eliran    schedule 07.09.2015
comment
А что произойдет, если я проведу пальцем влево? - все, что обычно происходит, когда вы проводите пальцем влево. Судя по вашему изменению, изменение содержания PagerAdapter на противоположное - это то, что вам нужно. На самом деле в ViewPager нет концепции следующей или предыдущей страницы, поскольку она заботится только о значениях индекса страницы. Вы должны упорядочить содержимое вашего PagerAdapter таким образом, чтобы следующая страница означала то, что вы хотите. Это также может означать, что вам нужно установить индекс начальной страницы в конце, согласно комментарию Криса, в зависимости от того, каким вы хотите, чтобы ваше начальное состояние было.   -  person CommonsWare    schedule 07.09.2015
comment
@CommonsWare Я думаю, вы неправильно поняли мой вопрос, или я не объяснил, что мне нужно хорошо. Я отредактировал свой комментарий-ответ вам новой информацией, надеюсь, вы понимаете.   -  person Eliran    schedule 07.09.2015
comment
ViewPager не имеет следующего. ViewPager не имеет предыдущего. Это ваши условия, которые вы накладываете поверх того, что предлагает ViewPager API. Пока вы не решите, что означает «следующий» и «предыдущий» с точки зрения ViewPager API и его значений индекса страницы, никто не сможет вам действительно помочь. То, как я перевел бы следующее и предыдущее с точки зрения ViewPager API, совпадает с тем, что я предлагал в своих предыдущих комментариях.   -  person CommonsWare    schedule 07.09.2015
comment
Ну, я подумал, и это может сработать, но потом я закончу тем, что третья вкладка действует как первая, а первая вкладка действует как третья. Кроме того, в моем макете вкладок по умолчанию будет выбрана последняя вкладка.   -  person Eliran    schedule 07.09.2015
comment
@Chris и последний элемент будет выделен в TabLayout вместо первого ..   -  person Eliran    schedule 10.09.2015
comment
@CommonsWare Решение этого вопроса не работает для уровня Api 28. Не могли бы вы проверить: stackoverflow.com/q/54129324/3484668 < / а>   -  person Rushi M Thakker    schedule 11.01.2019


Ответы (5)


Это очень простой способ изменить направление движения окна просмотра.

Есть два простых шага, которые вам нужно выполнить:

1. Измените поворот пейджера просмотра,

viewpager.setRotationY(180);

2. Затем снова измените направление контейнера фрагмента, который является дочерним элементом окна просмотра,

recyclerView.setRotationY(180);

Примечание. В моем случае я использовал recyclerview в качестве дочернего элемента пейджера просмотра.

У меня это на 100% сработало.

person Aman Gupta - ΔMΔN    schedule 23.01.2017
comment
это перевернуть все представления внутри окна просмотра - person ; 07.02.2017
comment
Потому что, возможно, вы повернули макет только один раз. Вам нужно дважды повернуться. Один раз родительский макет, чем дочерний макет. Однозначно, он будет работать правильно. - person Aman Gupta - ΔMΔN; 05.07.2017
comment
Любая идея, как повернуть текст в PagerTitleStrip обратно в нормальное состояние, получила ожидаемое поведение при повороте представлений дважды .... но полоса заголовка пейджера при повороте на 180 переключает родительское направление просмотра только для полосы заголовка, но не для текста - person skryshtafovych; 30.08.2017
comment
это решение работает нормально, но на некоторых устройствах Huawei это вызовет белый экран, но элементы просмотра ресайклера по-прежнему доступны для кликов, но невидимы Idk, почему, но это происходит со мной, и когда я удаляю setRotationY Его работает - person Biro Nader; 10.08.2018
comment
У этого решения проблемы с устройствами Android P. - person Rushi M Thakker; 11.01.2019
comment
@ AmanGupta-ShOoTeR - любой способ обхода пирога. stackoverflow.com/q/54129324/3484668 - person Rushi M Thakker; 11.01.2019
comment
@RushiMThakker, вы можете проверить новый ответ: stackoverflow.com/a/54440185/5333711 - person Aman Gupta - ΔMΔN; 30.01.2019

Я столкнулся с той же проблемой месяц назад, но думаю, что нашел отличное решение. 1) Измените направление TabLayout на ltr в xml:

<android.support.design.widget.TabLayout
    android:id="@+id/tl_activity_main"
    android:layout_below="@id/toolbar_activity_main"
    android:layoutDirection="ltr"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/DisionTabLayout" />

2) Создайте собственный адаптер для ViewPager и переопределите методы getItem (int position) и getPageTitle (int position):

@Override
public Fragment getItem(int position) {
    if (mIsRtlOrientation && mTabs != null && mTabs.length > 0) {
        return mTabs[mTabs.length - position - 1].getFragment();
    } else {
        return mTabs[position].getFragment();
    }
}

@Override
public int getCount() {
    return mTabs.length;
}

@Override
public CharSequence getPageTitle(int position) {
    if (mIsRtlOrientation && mTabs != null && mTabs.length > 0) {
        return mTabs[mTabs.length - position - 1].getTitle();
    } else {
        return mTabs[position].getTitle();
    }
}

3) Установите адаптер на ViewPager, а затем примените этот ViewPager к TabLayout.

private void setAdapters() {
    // initialize adapter
    mTabsAdapter = new TabsAdapter(getSupportFragmentManager(), mTabs, true);
    // set adapter to ViewPager
    vp.setAdapter(mTabsAdapter);
    // set ViewPager to TabLayout
    tl.setupWithViewPager(vp);
    // if RTL orientation, go to last item
    vp.setCurrentItem(vp.getAdapter().getCount() - 1, false);
}

4) Я создал сообщение в блоге, которое содержит более подробную информацию и полный код - здесь < / а>

person Stefan Tsekov    schedule 20.01.2016

Я знаю, что уже поздно, но это умный вопрос. как @CommonsWare сказал, что это вопрос изменения порядка элементов в методе getItem () в адаптере страницы. но этого недостаточно. поскольку вы меняете порядок в методе getitem (), вы также НЕ должны изменять порядок в методе getPageTitle (). что-то вроде этого:

public static class AppSectionsPagerAdapter extends FragmentStatePagerAdapter {
        public AppSectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return new page1();
                case 1:
                    return new page2();
                case 2:
                    return new page3();
            }
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "page 3 title";
                case 1:
                    return "page 2 title";
                case 2:
                    return "page 1 title";
                }
        }

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

Теперь наступает сложная часть. вам следует использовать этот простой метод, который преобразует порядок индекса с нулевым отсчетом в обратном порядке с использованием максимального индекса и текущего индекса.

public int calculateReverse(int maxIndex,int currentIndex){
        return maxIndex-currentIndex;
    }

чем вы должны использовать этот метод в onTabSelected () следующим образом: имейте в виду, что вы должны использовать свой собственный максимальный индекс:

@Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        mViewPager.setCurrentItem(calculateReverse(2,tab.getPosition()));
    }

вторая часть - изменить прослушиватель страниц на адаптере страницы. еще раз вы должны использовать свой собственный максимальный номер индекса:

mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(calculateReverse(2,position));  // reversing the tab selection
            }
        });

Я старался быть как можно более подробным. надеюсь это поможет :)

person hadi    schedule 15.10.2015

Если вы используете viewpager2 с фрагментами. ты можешь использовать.

<androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="0dp"
        android:layout_height="0dp"
        **android:orientation="vertical"**
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

Надеюсь, это кому-нибудь поможет.

person David Innocent    schedule 15.07.2020

Вы можете использовать ViewPager2, он поддерживает направление справа налево. чтобы сделать возможным:

  1. Добавить android: supportsRtl = true в манифест приложения
  2. Сделайте направление компоновки родительской группы просмотра viewpager2 ltr (android: layoutDirection = ltr)
  3. Теперь установите для viewpager2 layoutDirection ltr (android: layoutDirection = rtl)
  4. также установите макет адаптера на layoutDirection ltr (android: layoutDirection = ltr)
person Abu Nayem    schedule 02.03.2021