Navigating Pages with Ease (Tap Left/Right) : A Custom ViewPager in Android
Tags: android, ux, viewpager, ui
Published: 2023-06-06 15:47:58

## Introduction

Android provides a range of components that allow developers to create engaging and intuitive user interfaces. One such component is the ViewPager, a layout manager that allows users to flip through pages of data, akin to sliding through pages of a book. But what if we could make this navigation even more intuitive? What if a simple tap could transport you through pages? In this blog post, we'll explore how to create a custom ViewPager that responds to single-tap events for page navigation.

## Purpose

The traditional ViewPager in Android responds to swipe gestures for moving between pages. However, there might be cases where you want a simpler interaction, such as a single tap. Our aim here is to create a custom ViewPager that responds to single-tap events. Tapping on the left half of the screen will take the user to the previous page, while tapping on the right half navigates to the next page.

## How to Achieve That

To achieve this, we will extend the default ViewPager class and customize it to handle our desired tap events. This involves using Android's GestureDetector, which will enable us to listen for single-tap events and respond accordingly.

## Code Sample

Here's a sample code of a custom ViewPager in Java:

```java
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import androidx.viewpager.widget.ViewPager;
import java.util.Objects;

public class CustomViewPager extends ViewPager {
    private GestureDetector gestureDetector;

    public CustomViewPager(Context context) {
        super(context);
        init(context);
    }

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                float halfWidth = getWidth() / 2.0f;
                if (e.getX() < halfWidth) {
                    if (getCurrentItem() > 0) {
                        setCurrentItem(getCurrentItem() - 1, true);
                    }
                } else {
                    if (getCurrentItem() < Objects.requireNonNull(getAdapter()).getCount() - 1) {
                        setCurrentItem(getCurrentItem() + 1, true);
                    }
                }
                performClick();
                return super.onSingleTapConfirmed(e);
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        performClick();
        gestureDetector.onTouchEvent(ev);
        return super.onTouchEvent(ev);
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }
}
```

## Code Breakdown

The `CustomViewPager` class extends the default `ViewPager` and modifies its behavior through overriding certain methods and adding a GestureDetector. The GestureDetector is set up to detect single-tap events, and based on the location of the tap (left or right half of the screen), the ViewPager navigates to the previous or next page respectively. This is done in the `init()` method which is called from both constructors.

The `onTouchEvent()` is overridden to ensure that each touch event is also sent to the GestureDetector for processing, and a click action is performed for possible use by other components or accessibility services.

## How to Use the Custom ViewPager

The custom ViewPager can be used in your application just like any other view component. Here's a guide on how to do it:

**Java**

First, you need to create an instance of the CustomViewPager in your activity and set an adapter to it:

```java
CustomViewPager customViewPager = new CustomViewPager(this);
PagerAdapter adapter = new CustomPagerAdapter(); // This should be your custom PagerAdapter
customViewPager.setAdapter(adapter);

setContentView(customViewPager);
```
You can also get the current item, and set the current item programmatically:

```java
int currentItem = customViewPager.getCurrentItem();
customViewPager.setCurrentItem(currentItem + 1, true); 
```
**XML**

Alternatively, you can declare the CustomViewPager in your layout XML file and reference it in your activity:

```xml
<com.example.yourapp.CustomViewPager
    android:id="@+id/customViewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
```

Then, in your activity:

```java
CustomViewPager customViewPager = (CustomViewPager) findViewById(R.id.customViewPager);
PagerAdapter adapter = new CustomPagerAdapter(); // This should be your custom PagerAdapter
customViewPager.setAdapter(adapter);
```

Remember, in order for the `ViewPager` to display anything, you will need to set a `PagerAdapter` to it that supplies the views representing each page.

Also, please replace `com.example.yourapp` with your actual package name in XML usage.

## Use Cases

The custom ViewPager is perfect for applications where users prefer minimal hand movement or find swiping through pages inconvenient. It can also be beneficial for applications targeting users with accessibility needs, as the single-tap navigation may be easier for them to use. For example, in a digital book reading app, this would allow users to navigate between pages with a single tap, mimicking the act of flipping a book's page on either side.

## Conclusion

Enhancing the user experience is a crucial aspect of Android development. By customizing a ViewPager to respond to single-tap events, we can make navigation through an app's pages easier and more intuitive. While this post focused on single-tap events, Android's GestureDetector offers a wide range of gesture detection capabilities that developers can leverage to build engaging and user-friendly interfaces.

## Documentation References

1. [ViewPager | Android Developers](https://developer.android.com/reference/androidx/viewpager/widget/ViewPager)
2. [GestureDetector | Android Developers](https://developer.android.com/reference/android/view/GestureDetector)
3. [MotionEvent | Android Developers](https://developer.android.com/reference/android/view/MotionEvent)
4. [Building a Custom Component | Android Developers](https://developer.android.com/guide/topics/ui/custom-components)

Remember, the code is just a tool to serve your user's needs. By understanding your users and tailoring the code to their preferences, you can build an application that truly stands out. Happy coding!

## More
- [RecyclerView Last Item Extra Bottom Margin](https://blog.rejowan.com/tutorial/code/java/recyclerview-last-item-extra-bottom-margin/)
- [Making Android Views Draggable: A Practical Guide](https://blog.rejowan.com/tutorial/code/java/making-android-views-draggable-a-practical-guide/)
- [Hide the Soft Keyboard and Remove Focus from EditText in Android](https://blog.rejowan.com/tutorial/code/java/hide-the-soft-keyboard-and-remove-focus-from-edittext-in-android/)
- [Building a Visual Password Strength Meter in Android: A Simple Guide](https://blog.rejowan.com/tutorial/code/java/building-a-visual-password-strength-meter-in-android-a-simple-guide/)
- [Android SearchView OnCloseListener Not Working? Here’s How to Fix It](https://blog.rejowan.com/tutorial/code/java/android-searchview-oncloselistener-not-working-here-is-how-to-fix-it/)
- [CardView vs. MaterialCardView](https://blog.rejowan.com/tutorial/design/cardview-vs-materialcardview/)
- [Android 13’s Restricted Setting: A Stronghold Against Malicious Apps](https://blog.rejowan.com/news/android-news/android-13s-restricted-setting-a-stronghold-against-malicious-apps/)
- [Boost Your Android Development with ADB Idea Plugin](https://blog.rejowan.com/tutorial/android-studio/boost-your-android-development-with-adb-idea-plugin/)
-  [Troubleshooting “Execution Failed for Task app:mergeDebugResources” Error in Android XML Files](https://blog.rejowan.com/qa/android-qa/troubleshooting-execution-failed-for-task-appmergedebugresources-error-in-android-xml-files/)
- [Android Activity Lifecycle: A Comprehensive Guide](https://blog.rejowan.com/tutorial/series/android-basics/android-activity-lifecycle-a-comprehensive-guide/)