Android ViewPager with bottom dots
S

10

211

I want to add 3 bottom dots to my ViewPager, like this.

3 bottom dots 3 bottom dots 3 bottom dots

I use FragmentActivity and support library ViewPager.

Siclari answered 14/12, 2013 at 18:14 Comment(2)
I need to add dots, not tabs (like Nexus 5 launcher).Siclari
Check out my solution: https://mcmap.net/q/128758/-how-do-you-create-an-android-view-pager-with-a-dots-indicatorRegurgitate
U
408

Pager bottom dots/indicators in Compose

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PageIndicator(
    count: Int,
    pagerState: PagerState,
    modifier: Modifier = Modifier
) {
    Row(
        modifier = modifier
    ) {
        repeat(count) { index ->

            // play with size and corner shape to get the desired result
            // following displays a dot
            Box(
                modifier = Modifier
                    .size(16.dp)
                    .clip(RoundedCornerShape(50))
                    .background(
                        if (pagerState.currentPage == index) selectedColour else normalColour
                    )
            )

            // to add space between indicators
            if (index != count) {
                Spacer(modifier = Modifier.padding(horizontal = 4.dp))
            }
        }
    }
}

That's it :) Compose is love :D

Previous answer for ViewPager

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 in activity 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.

Unconformable answered 14/10, 2016 at 16:15 Comment(27)
Does this spread the dots across the whole parent width? You'd want the dots to be 10-20 dp apart for a page indicator.Bowsprit
it 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..Unconformable
This 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.Bowsprit
Maybe 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???Distinctive
hi 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...Unconformable
Thank 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 ?Electron
i have updated the answer change version of library in gradle and use onPageChangeListener...Unconformable
I 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!Electron
Why do we need a TabLayout?Clarisclarisa
You can just use shape as the root element for the indicator drawables. There's no need to wrap them as individual items in a layer-list.Embry
Can 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 :). @JuniOutgrow
kindly post your question with your code on github repository so that i can look into it.Unconformable
Nice solution that works great. However this doesn't work if you override GetPageTitleFormatted as you will end up with tabs with titles and dots.Grisham
any way to reduce the space between the dots?Epi
@Juni how will i show left side page, mid page , next page using same example with dots indicating to page 1Barleycorn
Works perfectly Xamarin.Android. great answer.Fulkerson
Is it possible to change the colour of dots? like white fill dots when selected and not-fill when unselected?Behring
yes change the respective indicator drawable.xml to your needs, it should work thenUnconformable
For recycler view? page indicator?Faulk
You want to use com.google.android.material.tabs.TabLayout in newer VersionsBerey
Update: that works but you should use new components: androidx.viewpager.widget.ViewPager and com.google.android.material.tabs.TabLayoutMichelle
the dots don't seem to slide along with the page. I use the slidingsplashviewMccartney
The above drawable XML looks weird until I changed shape to ring. Seems like ring is also used in the slidingdotsplash library instead of oval.Xenophobe
@Xenophobe It was originally "ring" but someone revised it to "oval". (And perhaps I approved the edit without reading it). Thanks for pointing outUnconformable
How is it possible to animate dots when pages are scrolling?Pola
@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 thisUnconformable
This solution can be somewhat simplified. No need of the extra tab_selector.xml. See my answerValeta
C
43

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);
    }
}
Catastrophe answered 1/5, 2015 at 21:12 Comment(2)
Why use heavy component Layout just to put a dot? Use View instead.Namely
I think the linear layout is so that it will center and group the dots.Jubilant
P
37
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) {

            }
        });
Polenta answered 13/1, 2015 at 9:20 Comment(4)
setOnPageChangedListener() deprecated!! Use addOnPageChangedListener() now.Namely
This 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.Itis
Don't fight the framework. Android has tools for doing this as TabLayout, there is no reason for reinventing the wheel.Ronna
Simplify 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); }Poco
S
33

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 and app:selectedDotDiameter to set the diameters of the dots
  • app:unselectedDotColor and app: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:

enter image description here

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

Sanctified answered 29/2, 2016 at 9:21 Comment(9)
Got error at indicator.setSelectedItem(position, true); IndexOutOfBoundsExceptionNumen
Which version? I thought I fixed that in 3.0.1, also what were your values for indicator.size() and position?Sanctified
Great 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.Cantrell
@Cantrell DotIndicator implements the SelectionIndicator interface, which means if has two useful methods which can solve your problem: int getNumberOfItems() and void setNumberOfItems(). Rather than catching the exception, you could do something like this gist.github.com/MatthewTamlin/761c7338d271af29526edc7859480aef.Sanctified
For 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.Sanctified
How to use DotIndicator class in the Activity? it says cannot resolve symbol DotIndicatorSubconscious
@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.Sanctified
Is there any documentation on how to use this library?Behring
in mine dots, transition is not happeningHistrionic
C
24

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!

Costotomy answered 25/8, 2016 at 12:1 Comment(3)
What bugs do you know? Can you provide some sources?Apocynthion
Both 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"Cystoid
easy to impliment, but it shows rectengular box in selected case even though i have set circuler xmls only.Cystoid
M
20

I thought of posting a simpler solution for the above problem and indicator numbers can be dynamically changed with only changing one variable value dotCounts=x what I did goes like this.

  1. Create an xml file in drawable folder for page selected indicator named "item_selected".
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval" android:useLevel="true"
        android:dither="true">
        <size android:height="8dp" android:width="8dp"/>
        <solid android:color="@color/image_item_selected_for_dots"/>
    </shape>
  1. Create one more xml file for unselected indicator named "item_unselected"
    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval" android:useLevel="true"
        android:dither="true">
        <size android:height="8dp" android:width="8dp"/>
        <solid android:color="@color/image_item_unselected_for_dots"/>
    </shape>
  1. Now add this part of the code at the place where you want to display the indicators for example below viewPager in your Layout XML file.
    <RelativeLayout
        android:id="@+id/viewPagerIndicator"
        android:layout_width="match_parent"
        android:layout_below="@+id/banner_pager"
        android:layout_height="wrap_content"
        android:gravity="center">
    
        <LinearLayout
            android:id="@+id/viewPagerCountDots"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:orientation="horizontal" />

    </RelativeLayout>
  1. Add this function on top of your activity file where your layout is inflated or the above xml file is related to
    private int dotsCount = 5;    //No of tabs or images
    private ImageView[] dots;
    LinearLayout linearLayout;
    
    private void drawPageSelectionIndicators(int mPosition){
        if(linearLayout!=null) {
            linearLayout.removeAllViews();
        }
        linearLayout=(LinearLayout)findViewById(R.id.viewPagerCountDots);
        dots = new ImageView[dotsCount];
        for (int i = 0; i < dotsCount; i++) {
            dots[i] = new ImageView(context);
            if(i==mPosition)
                dots[i].setImageDrawable(getResources().getDrawable(R.drawable.item_selected));
            else
                dots[i].setImageDrawable(getResources().getDrawable(R.drawable.item_unselected));
    
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
            );
    
            params.setMargins(4, 0, 4, 0);
            linearLayout.addView(dots[i], params);
        }
    }
  1. Finally in your onCreate method add the following code to reference your layout and handle pageselected positions
    drawPageSelectionIndicators(0);
    mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }
    
        @Override
        public void onPageSelected(int position) {
            drawPageSelectionIndicators(position);
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
        }
    });
Malcah answered 21/3, 2016 at 6:43 Comment(0)
I
9

Following is my proposed solution.

  • Since we need to show only some images in the view pagers so have avoided the cumbersome use of fragments.
    • Implemented the view page indicators (the bottom dots without any extra library or plugin)
    • On the touch of the view page indicators(the dots) also the page navigation is happening.
    • Please don"t forget to add your own images in the resources.
    • Feel free to comment and improve upon it.

A) Following is my activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="schneider.carouseladventure.MainActivity">

    <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/viewpager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <RelativeLayout
        android:id="@+id/viewPagerIndicator"
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:layout_alignParentBottom="true"
        android:layout_marginTop="5dp"
        android:gravity="center">

        <LinearLayout
            android:id="@+id/viewPagerCountDots"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:orientation="horizontal" />

    </RelativeLayout>


</RelativeLayout>

B) pager_item.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/imageView" />
</LinearLayout>

C) MainActivity.java

import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener, View.OnClickListener {

    int[] mResources = {R.drawable.nature1, R.drawable.nature2, R.drawable.nature3, R.drawable.nature4,
            R.drawable.nature5, R.drawable.nature6
    };

    ViewPager mViewPager;
    private CustomPagerAdapter mAdapter;
    private LinearLayout pager_indicator;
    private int dotsCount;
    private ImageView[] dots;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        pager_indicator = (LinearLayout) findViewById(R.id.viewPagerCountDots);
        mAdapter = new CustomPagerAdapter(this, mResources);
        mViewPager.setAdapter(mAdapter);
        mViewPager.setCurrentItem(0);
        mViewPager.setOnPageChangeListener(this);

        setPageViewIndicator();

    }

    private void setPageViewIndicator() {

        Log.d("###setPageViewIndicator", " : called");
        dotsCount = mAdapter.getCount();
        dots = new ImageView[dotsCount];

        for (int i = 0; i < dotsCount; i++) {
            dots[i] = new ImageView(this);
            dots[i].setImageDrawable(getResources().getDrawable(R.drawable.nonselecteditem_dot));

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
            );

            params.setMargins(4, 0, 4, 0);

            final int presentPosition = i;
            dots[presentPosition].setOnTouchListener(new View.OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    mViewPager.setCurrentItem(presentPosition);
                    return true;
                }

            });


            pager_indicator.addView(dots[i], params);
        }

        dots[0].setImageDrawable(getResources().getDrawable(R.drawable.selecteditem_dot));
    }

    @Override
    public void onClick(View v) {

    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {

        Log.d("###onPageSelected, pos ", String.valueOf(position));
        for (int i = 0; i < dotsCount; i++) {
            dots[i].setImageDrawable(getResources().getDrawable(R.drawable.nonselecteditem_dot));
        }

        dots[position].setImageDrawable(getResources().getDrawable(R.drawable.selecteditem_dot));

        if (position + 1 == dotsCount) {

        } else {

        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

D) CustomPagerAdapter.java

 import android.content.Context;
    import android.support.v4.view.PagerAdapter;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.LinearLayout;

    public class CustomPagerAdapter extends PagerAdapter {
        private Context mContext;
        LayoutInflater mLayoutInflater;
        private int[] mResources;

        public CustomPagerAdapter(Context context, int[] resources) {
            mContext = context;
            mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            mResources = resources;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {

            View itemView = mLayoutInflater.inflate(R.layout.pager_item,container,false);
            ImageView imageView = (ImageView) itemView.findViewById(R.id.imageView);
            imageView.setImageResource(mResources[position]);
           /* LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(950, 950);
            imageView.setLayoutParams(layoutParams);*/
            container.addView(itemView);
            return itemView;
        }

        @Override
        public void destroyItem(ViewGroup collection, int position, Object view) {
            collection.removeView((View) view);
        }

        @Override
        public int getCount() {
            return mResources.length;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }
    }

E) selecteditem_dot.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval" android:useLevel="true"
    android:dither="true">

    <size android:height="12dip" android:width="12dip"/>

    <solid android:color="#7e7e7e"/>
</shape>

F) nonselecteditem_dot.xml

 <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval" android:useLevel="true"
        android:dither="true">        
        <size android:height="12dip" android:width="12dip"/>        
        <solid android:color="#d3d3d3"/>
    </shape>

first image

enter image description here

Intellectualize answered 4/8, 2016 at 4:29 Comment(2)
i used this but on viewpager scroll dots are not changingGalba
this is the best answer.Deianira
V
3

The solution provided by @Junaid can be simplified. Instead of creating a selector (tab_selector.xml) you can simply set the drawables on the TabLayout directly.

<com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        app:tabBackground="@drawable/tab_indicator_default"
        app:tabIndicator="@drawable/tab_indicator_selected"
        app:tabIndicatorColor="<youColor>"
        app:tabIndicatorGravity="center"
        app:tabIndicatorHeight="8dp" />

app:tabIndicatorHeight is set to the same value as in tab_indicator_selected.xml. Following this approach you keep the default animation of the TabLayout. Programmatically, you have to set the tab as selected:

object : ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
        val tab = binding.tabLayout.getTabAt(position)
        binding.tabLayout.selectTab(tab, true)
    }
}

Please note that I used ViewPager2. There should be equivalent method using ViewPager.

Valeta answered 30/9, 2021 at 12:10 Comment(0)
L
1

If anyone wants to build a viewPager with thumbnails as indicators, using this library could be an option: ThumbIndicator for viewPager that works also with image links as resources.

Luciana answered 4/3, 2019 at 8:49 Comment(0)
M
0

Here is how I did this, somewhat similar to the solutions above. Just make sure you call the loadDots() method after all images are downloaded.

    private int dotsCount;
    private TextView dotsTextView[];

    private void setupAdapter() {
        adapter = new SomeAdapter(getContext(), images);
        viewPager.setAdapter(adapter);
        viewPager.setCurrentItem(0);
        viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
    }

    private final ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

        @Override
        public void onPageSelected(int position) {
            for (int i = 0; i < dotsCount; i++)
                dotsTextView[i].setTextColor(Color.GRAY);

            dotsTextView[position].setTextColor(Color.WHITE);
        }

        @Override
        public void onPageScrollStateChanged(int state) {}
    };

    protected void loadDots() {
        dotsCount = adapter.getCount();
        dotsTextView = new TextView[dotsCount];
        for (int i = 0; i < dotsCount; i++) {
            dotsTextView[i] = new TextView(getContext());
            dotsTextView[i].setText(R.string.dot);
            dotsTextView[i].setTextSize(45);
            dotsTextView[i].setTypeface(null, Typeface.BOLD);
            dotsTextView[i].setTextColor(android.graphics.Color.GRAY);
            mDotsLayout.addView(dotsTextView[i]);
        }
        dotsTextView[0].setTextColor(Color.WHITE);
    }

XML

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:background="#00000000"/>


    <ImageView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/introImageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <LinearLayout
        android:id="@+id/image_count"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00000000"
        android:gravity="center|bottom"
        android:orientation="horizontal"/>
</FrameLayout>
Mathildamathilde answered 24/3, 2018 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.