22

I want to show left and right arrows over my ViewPager, to indicate swiping.

I added two ImageButtons over the ViewPager-element but those areas then block the ViewPager from triggering the "swiping".

I also want presses on those arrows to trigger the fragment to change accordingly.

In short: The ImageButtons should not interfere with swiping but they should register pressing.

How can I achieve this? Thanks!

distractedhamster
  • 689
  • 2
  • 8
  • 22

5 Answers5

46

The code below worked for me perfectly well. NB: Use FrameLayout as it allows overlapping views

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <android.support.v4.view.ViewPager
                android:id="@+id/viewpager"
                android:layout_width="wrap_content"
                android:layout_height="200dp" />

            <ImageButton
                android:id="@+id/left_nav"
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_gravity="center_vertical|left"
                android:src="@drawable/ic_chevron_left_black_24dp" />

            <ImageButton
                android:id="@+id/right_nav"
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:layout_gravity="center_vertical|right"
                android:src="@drawable/ic_chevron_right_black_24dp" />

        </FrameLayout>

The following part I used to handle ImageButton's click events

viewPager = (ViewPager) view.findViewById(R.id.viewpager);

leftNav = (ImageButton) view.findViewById(R.id.left_nav);
rightNav = (ImageButton) view.findViewById(R.id.right_nav);

// Images left navigation
    leftNav.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int tab = viewPager.getCurrentItem();
            if (tab > 0) {
                tab--;
                viewPager.setCurrentItem(tab);
            } else if (tab == 0) {
                viewPager.setCurrentItem(tab);
            }
        }
    });

    // Images right navigatin
    rightNav.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int tab = viewPager.getCurrentItem();
            tab++;
            viewPager.setCurrentItem(tab);
        }
    });

Output

enter image description here

Christopher Kikoti
  • 2,487
  • 1
  • 24
  • 29
17

No need to manage the current index for this or to handle any swiping manually. Simply call method viewPager.arrowScroll(int direction) method on the click events of left and right arrows.

In a nutshell follow these 2 simple steps:

  1. Implement 2 ImageViews/ImageButtons/Buttons for left and right arrows.
  2. On clicking them, call:

    a) if left arrow is clicked - viewPager.arrowScroll(View.FOCUS_LEFT);

    b) if right arrow is clicked - viewPager.arrowScroll(View.FOCUS_RIGHT);

Dan Lowe
  • 51,713
  • 20
  • 123
  • 112
Keshav Bansal
  • 407
  • 4
  • 6
  • Great! Thanks alot :D – Rohan Taneja Aug 16 '17 at 05:08
  • This is an easy approach if it works, but `arrowScroll()` isn't designed to page left/right unconditionally. It's supposed to move focus left/right, and only page left/right if it gets to the end of the focus chain. So it can fail, in confusing ways, if you have views on the screen that are focusable. See https://stackoverflow.com/a/57679214/423105 about the problem, and @Christopher's answer for the robust way to page left/right. – LarsH Aug 27 '19 at 17:24
10

Implement left & right arrow buttons in your fragment. Then register their onClick in your activity and call viewpager's arrowScroll method to scroll the viewPager programmatically.

public void onRightClick(View view) {
    viewPager.arrowScroll(ViewPager.FOCUS_RIGHT);
}

public void onLeftClick(View view) {
    viewPager.arrowScroll(ViewPager.FOCUS_LEFT);
}

Create a method to toggle left/right arrow visibility in your fragment.

public void toggleArrowVisibility(boolean isAtZeroIndex, boolean isAtLastIndex) {
    if(isAtZeroIndex)
        leftBtn.setVisibility(View.INVISIBLE);
    else
        leftBtn.setVisibility(View.VISIBLE);
    if(isAtLastIndex)
        rightBtn.setVisibility(View.INVISIBLE);
    else
        rightBtn.setVisibility(View.VISIBLE);

}

Now implement ViewPager.OnPageChangeListener in your activity. Use SmartFragmentStatePagerAdapter to keep track of registered fragments in memory.

@Override
public void onPageSelected(int position) {
    MyFragment fragment = (MyFragment) smartAdapter.getRegisteredFragment(position);
    fragment.toggleArrowVisibility(position == 0, position == list.size() - 1);
}
Salil Dhawan
  • 631
  • 6
  • 6
4

Instead of using ImageButtons for displaying the arrows, I now use ImageViews because they pass on any touch events to the layer underneath.

Then, I put transparent Buttons on the fragments themselves instead, that way they won't block the ViewPagers swiping behaviour but they will fire onClick Events!

distractedhamster
  • 689
  • 2
  • 8
  • 22
1

First use relative layout as your parent layout

second then add view pager inside it with match parent attribute on it

third take two image buttons over the view pager but in under the hierarchy of parent layout give them center vertical as a gravity and keep their side as right and left as per your requirement

fourth write functional code for buttons

fifth take static counter to get current view pager page

on left and right button set minus and plus the view pager counter resp. and according to that show data in view pager

this is the simple logic for code you can search it on google you will easily get it