Android ViewPager with bottom dots
Solution 1
No need for that much code.
You can do all this stuff without coding so much by using only viewpager
with tablayout
.
Your main Layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
<android.support.design.widget.TabLayout
android:id="@+id/tabDots"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"/>
</RelativeLayout>
Hook up your UI elements inactivity or fragment as follows:
Java Code:
mImageViewPager = (ViewPager) findViewById(R.id.pager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabDots);
tabLayout.setupWithViewPager(mImageViewPager, true);
That's it, you are good to go.
You will need to create the following xml resource file in the drawable folder.
tab_indicator_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorAccent"/>
</shape>
tab_indicator_default.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="oval"
android:thickness="2dp"
android:useLevel="false">
<solid android:color="@android:color/darker_gray"/>
</shape>
tab_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/tab_indicator_selected"
android:state_selected="true"/>
<item android:drawable="@drawable/tab_indicator_default"/>
</selector>
Feeling as lazy as I am? Well, all the above code is converted into a library!
Usage
Add the following in your gradle:
implementation 'com.chabbal:slidingdotsplash:1.0.2'
Add the following to your Activity or Fragment layout.
<com.chabbal.slidingdotsplash.SlidingSplashView
android:id="@+id/splash"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:imageResources="@array/img_id_arr"/>
Create an integer array in strings.xml
e.g.
<integer-array name="img_id_arr">
<item>@drawable/img1</item>
<item>@drawable/img2</item>
<item>@drawable/img3</item>
<item>@drawable/img4</item>
</integer-array>
Done!
Extra in order to listen page changes use addOnPageChangeListener(listener);
Github link.
Solution 2
My handmade solution:
In the layout:
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/dots"
/>
And in the Activity
private final static int NUM_PAGES = 5;
private ViewPager mViewPager;
private List<ImageView> dots;
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
addDots();
}
public void addDots() {
dots = new ArrayList<>();
LinearLayout dotsLayout = (LinearLayout)findViewById(R.id.dots);
for(int i = 0; i < NUM_PAGES; i++) {
ImageView dot = new ImageView(this);
dot.setImageDrawable(getResources().getDrawable(R.drawable.pager_dot_not_selected));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
dotsLayout.addView(dot, params);
dots.add(dot);
}
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
selectDot(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
public void selectDot(int idx) {
Resources res = getResources();
for(int i = 0; i < NUM_PAGES; i++) {
int drawableId = (i==idx)?(R.drawable.pager_dot_selected):(R.drawable.pager_dot_not_selected);
Drawable drawable = res.getDrawable(drawableId);
dots.get(i).setImageDrawable(drawable);
}
}
Solution 3
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
switch (position) {
case 0:
img_page1.setImageResource(R.drawable.dot_selected);
img_page2.setImageResource(R.drawable.dot);
img_page3.setImageResource(R.drawable.dot);
img_page4.setImageResource(R.drawable.dot);
break;
case 1:
img_page1.setImageResource(R.drawable.dot);
img_page2.setImageResource(R.drawable.dot_selected);
img_page3.setImageResource(R.drawable.dot);
img_page4.setImageResource(R.drawable.dot);
break;
case 2:
img_page1.setImageResource(R.drawable.dot);
img_page2.setImageResource(R.drawable.dot);
img_page3.setImageResource(R.drawable.dot_selected);
img_page4.setImageResource(R.drawable.dot);
break;
case 3:
img_page1.setImageResource(R.drawable.dot);
img_page2.setImageResource(R.drawable.dot);
img_page3.setImageResource(R.drawable.dot);
img_page4.setImageResource(R.drawable.dot_selected);
break;
default:
break;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
Solution 4
I created a library to address the need for a page indicator in a ViewPager. My library contains a View called DotIndicator. To use my library, add compile 'com.matthew-tamlin:sliding-intro-screen:3.2.0'
to your gradle build file.
The View can be added to your layout by adding the following:
<com.matthewtamlin.sliding_intro_screen_library.indicators.DotIndicator
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:numberOfDots=YOUR_INT_HERE
app:selectedDotIndex=YOUR_INT_HERE/>
The above code perfectly replicates the functionality of the dots on the Google Launcher homescreen, however if you want to further customise it then the following attributes can be added:
-
app:unselectedDotDiameter
andapp:selectedDotDiameter
to set the diameters of the dots -
app:unselectedDotColor
andapp:selectedDotColor
to set the colors of the dots -
app:spacingBetweenDots
to change the distance between the dots -
app:dotTransitionDuration
to set the time for animating the change from small to big (and back)
Additionally, the view can be created programatically using:
DotIndicator indicator = new DotIndicator(context);
Methods exist to modify the properties, similar to the attributes. To update the indicator to show a different page as selected, just call method indicator.setSelectedItem(int, true)
from inside ViewPager.OnPageChangeListener.onPageSelected(int)
.
Here's an example of it in use:
If you're interested, the library was actually designed to make intro screens like the one shown in the above gif.
Github source available here: https://github.com/MatthewTamlin/SlidingIntroScreen
Solution 5
ViewPagerIndicator
has not been updated since 2012 and got several bugs that were never fixed.
I finally found an alternative with this light library that displays nice dots for the viewpager
, here is the link:
https://github.com/ongakuer/CircleIndicator
Easy to implement!
Related videos on Youtube
![Kfir Guy](https://i.stack.imgur.com/BhcSp.jpg?s=256&g=1)
Kfir Guy
Updated on July 16, 2022Comments
-
Kfir Guy almost 2 years
I want to add 3 bottom dots to my ViewPager, like this.
I use FragmentActivity and support library ViewPager.
-
Kfir Guy over 10 yearsI need to add dots, not tabs (like Nexus 5 launcher).
-
RediOne1 over 7 yearsCheck out my solution: stackoverflow.com/a/38459310/4631935
-
-
Apurva almost 9 years
setOnPageChangedListener()
deprecated!! UseaddOnPageChangedListener()
now. -
Apurva almost 9 yearsWhy use heavy component
Layout
just to put a dot? UseView
instead. -
ShawnV almost 9 yearsI think the linear layout is so that it will center and group the dots.
-
Dixit Panchal about 8 yearsGot error at indicator.setSelectedItem(position, true); IndexOutOfBoundsException
-
Helios about 8 yearsWhich version? I thought I fixed that in 3.0.1, also what were your values for indicator.size() and position?
-
vsp almost 8 yearsGreat library! However, is there a more elegant way to update selectedItem and numberOfItems at the same time? Depending on which one is bigger, the order changes, otherwise you throw an IndexOutOfBounds exception. See this gist.
-
Helios almost 8 years@vsp DotIndicator implements the SelectionIndicator interface, which means if has two useful methods which can solve your problem:
int getNumberOfItems()
andvoid setNumberOfItems()
. Rather than catching the exception, you could do something like this gist.github.com/MatthewTamlin/761c7338d271af29526edc7859480aef. -
Helios almost 8 yearsFor anyone not following the gist conversation, there was actually a bug which has now been fixed. 3.0.2 is the latest version as of right now.
-
0xMatthewGroves almost 8 yearsThis is not really a great solution, as you have to know exactly how many pages you'll be using. As soon as you add or remove a page, you're in trouble.
-
kashlo almost 8 yearsHow to use DotIndicator class in the Activity? it says cannot resolve symbol DotIndicator
-
Helios almost 8 years@zakusha sounds like it's probably an IDE error, have you tried cleaning and rebuilding he project? I've had problems with Android Studio just not finding classes that are definitely in the dependencies before. As a worst case solution, try invalidating your cache and redownloading all dependencies. Still, I'll check there's nothing wrong with the library and get back to you.
-
androidguy over 7 yearsDoes this spread the dots across the whole parent width? You'd want the dots to be 10-20 dp apart for a page indicator.
-
Junaid over 7 yearsit places the dots in the center of the parent width....and yes appropriate spacing is also there between the dots...up vote if it helped you..
-
androidguy over 7 yearsThis solution, and most of the others, adds a ViewGroup and an extra View for each page, which is unnecessary waste to draw a few circles. I went with Jake Wharton's library, but added his code directly so I could fix some small issues.
-
Eric Engel over 7 yearsMaybe I missed something, but the array going into the strings file can't find @Drawable/img 1-4. These are not mentioned here. What am I missing???
-
Junaid over 7 yearshi you have to create your own array in strings.xml. and add those images mentioned in array to drawable folder...by the way 'd' of your @Drawable/img is Capital make it small...
-
Mohamed Hamdaoui over 7 yearsThank you for the solution, it is working fine! but how do we detect which position we're at ? I need to know which position of tha pager we're at so I can update other views. I tried the setOnShowImageListener and tried to work with that call back, but it doesn't get called. Can you please advise ?
-
Junaid over 7 yearsi have updated the answer change version of library in gradle and use onPageChangeListener...
-
Mohamed Hamdaoui over 7 yearsI had already upvoted before I ask the question, because it already helped me a lot, but now I wish I can apvote +2 or +100 :) because adding the onPageChangeListener worked perfectly for me! And just to make it clear for anyone that may use this, you need to do your updates on the onPageSelected callback only, adding the update in the onPageScrolled callback makes it messy, it starts the update as soon as you start scrolling, which is not visually good!
-
winklerrr about 7 yearsWhy do we need a TabLayout?
-
cascal about 7 yearsYou can just use
shape
as the root element for the indicator drawables. There's no need to wrap them as individual items in alayer-list
. -
makkhay gurung almost 7 yearsCan someone help me? I used the library and the sliding dot is visible but whenever I slide the image it doesn't move the sliding dot. In other words, if I slide the image from the corner then it will slide the image but not the sliding dot, and If I slide from the middle, it will slide the dots but not the image. I have images in my fragment and viewpager in activity_main.xml. Any help and guidance would be greatly appreciated. Thanks :). @Juni
-
Junaid almost 7 yearskindly post your question with your code on github repository so that i can look into it.
-
Eli almost 7 yearsNice solution that works great. However this doesn't work if you override
GetPageTitleFormatted
as you will end up with tabs with titles and dots. -
Gak2 almost 7 yearsany way to reduce the space between the dots?
-
Erum almost 7 years@Juni how will i show left side page, mid page , next page using same example with dots indicating to page 1
-
Mehdi Dehghani over 6 yearsWorks perfectly
Xamarin.Android
. great answer. -
Aditya Vyas-Lakhan over 6 yearsi used this but on viewpager scroll dots are not changing
-
Angad over 6 yearsIs it possible to change the colour of dots? like white fill dots when selected and not-fill when unselected?
-
Angad over 6 yearsIs there any documentation on how to use this library?
-
Junaid over 6 yearsyes change the respective indicator drawable.xml to your needs, it should work then
-
kike about 6 yearsDon't fight the framework. Android has tools for doing this as TabLayout, there is no reason for reinventing the wheel.
-
Duna about 6 yearsSimplify to this: private void setDotSelection(int index) { dot1.setImageResource(index == 0 ? R.drawable.circle_selected : R.drawable.circle); dot2.setImageResource(index == 1 ? R.drawable.circle_selected : R.drawable.circle); dot3.setImageResource(index == 2 ? R.drawable.circle_selected : R.drawable.circle); dot4.setImageResource(index == 3 ? R.drawable.circle_selected : R.drawable.circle); dot5.setImageResource(index == 4 ? R.drawable.circle_selected : R.drawable.circle); }
-
blackHawk about 6 yearsFor recycler view? page indicator?
-
Sandeep Londhe over 5 yearsthis is the best answer.
-
abh22ishek over 5 yearsin mine dots, transition is not happening
-
schlenger over 5 yearsYou want to use
com.google.android.material.tabs.TabLayout
in newer Versions -
dreinoso almost 5 yearsUpdate: that works but you should use new components: androidx.viewpager.widget.ViewPager and com.google.android.material.tabs.TabLayout
-
landrykapela over 4 yearsthe dots don't seem to slide along with the page. I use the slidingsplashview
-
katie about 4 yearsThe above drawable XML looks weird until I changed shape to
ring
. Seems like ring is also used in the slidingdotsplash library instead of oval. -
Junaid almost 4 years@katie It was originally "ring" but someone revised it to "oval". (And perhaps I approved the edit without reading it). Thanks for pointing out
-
Michał Jabłoński almost 4 yearsWhat bugs do you know? Can you provide some sources?
-
Vikas Pandey over 3 yearsBoth of these are ring shape xml drawable. yet i see rectangular boxes as seperator. app:ci_drawable=. "@drawable/selected_dot" app:ci_drawable_unselected=. "@drawable/default_dot"
-
Vikas Pandey over 3 yearseasy to impliment, but it shows rectengular box in selected case even though i have set circuler xmls only.
-
M. Afrashteh over 3 yearsHow is it possible to animate dots when pages are scrolling?
-
Junaid over 3 years@M.Afrashteh You can add your own code in
onPageScrolled
to move the dots...or if you don't wanna do it yourself then use a library that does this -
Aaron over 2 yearsThis solution can be somewhat simplified. No need of the extra
tab_selector.xml
. See my answer