Android’s ViewPager (and ViewPager2) is designed to work with integer-based page indices. By default, it always starts at position 0, representing the first page. However, in modern UI designs—such as carousels, card sliders, or preview-based layouts—developers often want the pager to start partially scrolled, for example at 0.5, so the first item appears centered or partially visible.
Since ViewPager does not natively support fractional start positions, achieving this effect requires a controlled workaround. This article explains why this limitation exists, and provides robust, production-ready techniques to simulate a fractional starting position like 0.5.
Why ViewPager Does Not Support Fractional Positions
Internally, ViewPager operates using:
- Integer page indices
- Fixed page widths (fractions are applied per page, not per position)
- Scroll offsets computed relative to the current page
As a result:
setCurrentItem()only accepts integers- There is no API like
setCurrentItem(0.5f)
To solve this, we must combine adapter configuration + manual scrolling.
Recommended Strategy (Stable & Production-Safe)
The most reliable approach is a two-step initialization:
- Start at an integer page
- Manually scroll by a fractional offset (e.g. 50% of page width)
This method works with:
- Standard ViewPager
- Infinite / looping adapters
- Custom PageTransformers
- Carousel layouts
Step 1: Configure Page Width (Optional but Recommended)
If you are building a carousel (e.g. 3 items visible), override getPageWidth() in your adapter.
override fun getPageWidth(position: Int): Float {
return 1f / 3f // 3 items visible
}
This ensures predictable geometry when applying a fractional offset.
Step 2: Set the Initial Integer Position
Set the ViewPager to an integer position without animation.
carouselViewPager.setCurrentItem(startPosition, false)
For infinite carousels, startPosition is usually a large number centered around your dataset.
Step 3: Apply a Fractional Offset (0.5 Page)
Once the ViewPager is laid out, apply a horizontal scroll equal to half a page width.
carouselViewPager.post {
val pageWidth = carouselViewPager.width / 3 // adjust to your page width logic
val halfPageOffset = pageWidth / 2
carouselViewPager.scrollBy(halfPageOffset, 0)
}
Why post {} Is Required
- ViewPager width is only known after layout
- Calling
scrollBy()earlier will have no effect
Result
Visually, the ViewPager now appears to start at position 0.5:
- The first page is centered or partially visible
- Neighboring pages are previewed
- Swipe behavior remains natural
Alternative: Using Padding Instead of scrollBy
In some carousel designs, you can simulate a fractional start by applying padding:
carouselViewPager.apply {
clipToPadding = false
setPadding(width / 6, 0, width / 6, 0)
}
This works well for static previews, but is less precise than scrollBy().
ViewPager2 Considerations
With ViewPager2, the same idea applies, but you must access the internal RecyclerView:
val recyclerView = carouselViewPager.getChildAt(0) as RecyclerView
recyclerView.post {
val offset = recyclerView.width / 6
recyclerView.scrollBy(offset, 0)
}
This approach is safe and officially supported.
Common Pitfalls to Avoid
❌ Calling scrollTo() before layout
❌ Trying to use fractional values in setCurrentItem()
❌ Forgetting to disable clipToPadding for carousels
❌ Applying offset before adapter is attached
Best Practices Summary
| Requirement | Recommendation |
|---|---|
| Fractional start | Use scrollBy() |
| Infinite carousel | Start from large index |
| Multiple visible pages | Override getPageWidth() |
| Smooth UX | Disable animation on initial set |
| Compatibility | Use post {} |
Conclusion
Although Android’s ViewPager does not support fractional start positions natively, a clean and maintainable solution exists. By combining:
- Integer-based initialization
- Manual pixel offset scrolling
- Optional page width control
you can achieve a 0.5 start position (or any fractional offset) that works seamlessly with carousels, infinite pagers, and complex UI animations.
This approach is widely used in production apps and remains compatible with custom transformers, ViewModels, and synchronized pagers.


