Left-right arrow indicators over a ViewPager
Asked Answered
B

5

23

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!

Burkhardt answered 6/8, 2014 at 9:43 Comment(0)
B
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!

Burkhardt answered 6/8, 2014 at 15:37 Comment(7)
Hello! I was wondering if you could elaborate on how or which arrows did you use to display via ImageViews. Would like to do the same thing for my project. Thanks!Blunder
Hi! Not sure I understand the question:) I designed the arrows in photoshopBurkhardt
Ok, were there any specific image format (jpeg, png, bmp... Etc) that is has to be done with?Blunder
.png is probably your best option since it supports transparency!Burkhardt
Cool! And one more question, the last paragraph you wrote on your answer is to make the arrows funtionable with a click to switch pages right?Blunder
Awesome... Thanks! Would you mind if I contact you again if I have issues implementing it?Blunder
No problem! Feel freeBurkhardt
O
47

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

Oakie answered 7/2, 2016 at 12:49 Comment(1)
perfect solutionSuspicion
N
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);

Nowhither answered 2/2, 2017 at 1:1 Comment(2)
Great! Thanks alot :DMalagasy
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://mcmap.net/q/282801/-how-can-i-make-viewpager-arrowscroll-work-the-first-time about the problem, and @Christopher's answer for the robust way to page left/right.Happygolucky
T
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);
}
Toddle answered 15/12, 2017 at 15:12 Comment(1)
Thank you for also adding the toggle visibility. Very useful as well.Helles
B
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!

Burkhardt answered 6/8, 2014 at 15:37 Comment(7)
Hello! I was wondering if you could elaborate on how or which arrows did you use to display via ImageViews. Would like to do the same thing for my project. Thanks!Blunder
Hi! Not sure I understand the question:) I designed the arrows in photoshopBurkhardt
Ok, were there any specific image format (jpeg, png, bmp... Etc) that is has to be done with?Blunder
.png is probably your best option since it supports transparency!Burkhardt
Cool! And one more question, the last paragraph you wrote on your answer is to make the arrows funtionable with a click to switch pages right?Blunder
Awesome... Thanks! Would you mind if I contact you again if I have issues implementing it?Blunder
No problem! Feel freeBurkhardt
F
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

Flirtation answered 6/8, 2014 at 9:55 Comment(8)
can u elobrate in brief what is mean by interfere? you want to change page by clickng on buttons?Flirtation
When I start the swiping-motion with my finger on one of the ImageButtons, the ViewPager won't register the swipe. Sorry if unclear!Burkhardt
have you register your listner for image button?Flirtation
No, will that make a difference?Burkhardt
yes if you implemented the onClickListner for your activity and your trying to access onClick event then you must register your onClickListner for the object of that view ex. imgBtn.setOnClickListener(this);Flirtation
I tried it. Didn't make a difference. I am not trying to access onClick for the ImageButton, I am trying to make the ImageButton not prevent the ViewPager from getting the swipe.Burkhardt
@Androidiseverythingforme, I have a similar problem with the person above: #26263306Willtrude
for anyone still interest: check this also: github.com/sembozdemir/ViewPagerArrowIndicatorAbrasive

© 2022 - 2024 — McMap. All rights reserved.