184

Probably many of you (as me), have problem with creating ViewPager with bottom dots, like this: enter image description here

How do you create such an Android ViewPager?

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
RediOne1
  • 10,389
  • 6
  • 25
  • 46
  • **2021** If you are pure ViewPager2 and 24+, the critical code for TabLayoutMediator has changed. I put in the latest in an answer below. What a PITA ! – Fattie Mar 03 '21 at 18:42

10 Answers10

399

All we need are: ViewPager, TabLayout and 2 drawables for selected and default dots.

Firstly, we have to add TabLayout to our screen layout, and connect it with ViewPager. We can do this in two ways:


Nested TabLayout in ViewPager

<androidx.viewpager.widget.ViewPager
    android:id="@+id/photos_viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.tabs.TabLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</androidx.viewpager.widget.ViewPager>

In this case TabLayout will be automatically connected with ViewPager, but TabLayout will be next to ViewPager, not over it.


Separate TabLayout

<androidx.viewpager.widget.ViewPager
    android:id="@+id/photos_viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tab_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

In this case, we can put TabLayout anywhere, but we have to connect TabLayout with ViewPager programmatically

ViewPager pager = (ViewPager) view.findViewById(R.id.photos_viewpager);
PagerAdapter adapter = new PhotosAdapter(getChildFragmentManager(), photosUrl);
pager.setAdapter(adapter);

TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager, true);

Once we created our layout, we have to prepare our dots. So we create three files: selected_dot.xml, default_dot.xml and tab_selector.xml.


selected_dot.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="0dp"
            android:shape="ring"
            android:thickness="8dp"
            android:useLevel="false">
            <solid android:color="@color/colorAccent"/>
        </shape>    
    </item>
</layer-list>

default_dot.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="0dp"
            android:shape="ring"
            android:thickness="8dp"
            android:useLevel="false">
            <solid android:color="@android:color/darker_gray"/>
        </shape>    
    </item>
</layer-list>

tab_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/selected_dot"
          android:state_selected="true"/>

    <item android:drawable="@drawable/default_dot"/>
</selector>

Now we need to add only 3 lines of code to TabLayout in our XML layout.

app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
Boken
  • 4,825
  • 10
  • 32
  • 42
RediOne1
  • 10,389
  • 6
  • 25
  • 46
  • 25
    you better put this in the documentation section. it helped though. – Erfan GLMPR Sep 14 '16 at 13:49
  • 3
    @ErfanGholampour http://stackoverflow.com/documentation/android/692/viewpager/22945/viewpager-with-a-dots-indicator#t=201609141951318798598 – RediOne1 Sep 14 '16 at 19:52
  • Hey, can you help me in reducing the gaps between the dots? – Amit Singh Jun 05 '17 at 06:56
  • 5
    @AmitSingh You can use `app:tabMaxWidth` in TabLayout – RediOne1 Jun 05 '17 at 09:13
  • can't put those indicator in the bottom of layout overlapping `ViewPager`. When using `LinearLayout` it goes below the `ViewPager` and using `RelativeLayout` also same. – dawanse Jun 06 '17 at 15:29
  • @dawn `TabLayout` should be placed as separated widget (like in example **Separate `TabLayout`**. If you put `TabLayout` as a child of `ViewPager` it'll be autmoaticaly placed below `ViewPager` and not overlap it. – RediOne1 Jun 07 '17 at 11:16
  • 5
    I do not know if I did not follow the instructions correctly but I also had to add the following in order to show only the dots with a decent space between them: `app:tabMaxWidth="30dp" app:tabTextColor="@color/transparent2" app:tabSelectedTextColor="@color/transparent2" app:tabIndicatorHeight="0dp" android:layout_gravity="bottom|center"` – Seven Oct 19 '17 at 21:20
  • I'm getting an error very like the one described in https://stackoverflow.com/questions/31712563/error-inflating-class-android-support-design-widget-tablayout when trying to use this. The solutions suggested for the linked question don;t resolve the problem either. The app compiles and runs OK ad there are no errors in the editor, but when the activity tries to inflate the app crashes. – Fat Monk Oct 31 '17 at 15:54
  • 3
    For remove spacing between dots app:tabPaddingStart="@dimen/margin_7.5" app:tabPaddingEnd="@dimen/margin_7.5" – tech.mohit.garg Nov 21 '17 at 07:46
  • I have only Viewpager, please suggest what to do. – eC Droid Nov 23 '17 at 06:54
  • I followed your answer and everything works really smoothly, thank you. I have one question though, in my app the `TabLayout` is always in the far top tried many things to put it in the bottom with no luck. I placed it nested in the `ViewPager` and also separately. still the same problem. Any ideas? – Sam May 24 '18 at 19:32
  • Thank you I followed this [link](https://stackoverflow.com/questions/33380668/how-to-set-android-tablayout-in-the-bottom-of-the-screen) to fix the `TabLayout` position on the screen – Sam May 24 '18 at 19:48
  • After adding `app:tabBackground="@drawable/tab_selector"` and others to TabLayout an application stopped compiling wih error. – CoolMind Jul 16 '18 at 14:54
  • @RediOne1, 3 lines of exception like `AGPBI: {"kind":"error","text":"error: attribute \u0027com.example:tabBackground\u0027 not found.","sources":[{"file":"C:\\Users\\user\\AndroidStudioProjects\\sample\\app\\src\\main\\res\\layout\\activity_start.xml","position":{"startLine":53}}],"original":"","tool":"AAPT"}`. After removing `app` attributes it crushes with exception `Caused by: android.view.InflateException: Binary XML file line #54: Error inflating class android.support.design.widget.TabLayout`. I write in Kotlin. – CoolMind Jul 17 '18 at 08:51
  • @CoolMind Do you have `xmlns:app="http://schemas.android.com/apk/res-auto"` on top of your layout file? If you can, please paste whole layout file to https://pastebin.com/ and paste link here. – RediOne1 Jul 18 '18 at 09:49
  • @RediOne1, yes, i have this attribute. I removed `TabLayout`, because it is not needed. But if you wish, I can create a sample layout for you. – CoolMind Jul 18 '18 at 09:52
  • @CoolMind Ok, do it, please. – RediOne1 Jul 19 '18 at 06:23
  • 1
    @RediOne1 The xml could just be a , instead of a in an in a , right? – Touré Holder Oct 18 '18 at 15:28
  • @Touré Holder Yes – RediOne1 Oct 18 '18 at 16:02
  • Thanks! Just need place TabLayout outside ViewPager to place below ViewPager – Black_Zerg Feb 28 '19 at 10:17
  • unable to find tabIndicatorHeight – Maveňツ Apr 24 '19 at 13:30
  • 1
    I had to add `implementation 'com.android.support:support-v4:x.x.x'` into the dependencies, otherwise I got errors like `Android resource linking failed` `attribute tabBackground (aka com.company.appname:tabBackground) not found.` – Jordan H Apr 24 '19 at 16:34
  • How to do this with `ViewPager2` and `TabLayoutMediator`? – IgorGanapolsky Mar 10 '20 at 21:00
  • @IgorGanapolsky I prepared simple demo for ViewPager and ViewPager2: https://github.com/AdrianKuta/ViewPagerDotsIndicator I will also update Answer, thank you for this question ;-) – RediOne1 Mar 11 '20 at 13:59
  • should a separate tablayout be created if I want to display dots below viewpager? – Hari Kiran Jun 17 '20 at 00:30
  • And finally, to disable tab touch events use this `tab_layout.touchables?.forEach { it.isEnabled = false }` – Sai Jul 06 '20 at 14:31
  • 1
    To play with the space/gap between tabs and to remove indication use this `app:tabPaddingStart="8dp" app:tabPaddingEnd="8dp" app:tabIndicatorHeight="0dp"` – Sai Jul 06 '20 at 14:45
  • 1
    For ViewPager2 with Java, you need ```viewPager = findViewById(R.id.pager);pagerAdapter = new ScreenSlidePagerAdapter(this); viewPager.setAdapter(pagerAdapter); tabLayout = findViewById(R.id.tabs); new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {}).attach();``` – F1iX Dec 26 '20 at 19:10
  • bravo @F1iX exactly – Fattie Mar 03 '21 at 18:46
  • final touch add backgroud:@android:color/transparent to the tab layout – kamal douma Nov 02 '22 at 10:03
32

First Create a layout, in that give one LinerLayout for Dots which show over your View Pager

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>


    <LinearLayout
        android:id="@+id/pager_dots"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="10dp"
        android:background="@android:color/transparent"
        android:gravity="center_horizontal"
        android:orientation="horizontal">
    </LinearLayout>

</RelativeLayout>

After that create 2 drawables

1. Unselected Drawable

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@android:color/transparent"/>
    <size android:width="12dp" android:height="12dp"/>

    <stroke android:width="1dp" android:color="#ffffff"/>
</shape>

2. Selected Drawable

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@android:color/transparent"/>
    <size android:width="12dp" android:height="12dp"/>

    <stroke android:width="1dp" android:color="#000000"/>
</shape>

After that set adapter

private LinearLayout llPagerDots;
private ViewPager viewPager;
private ArrayList<String> eventImagesUrl;
private HomeViewPagerAdapter homeViewPagerAdapter;
private ImageView[] ivArrayDotsPager;

public void setUpViewPager() {
    viewPager = (ViewPager) findViewById(R.id.view_pager);
    llPagerDots = (LinearLayout) findViewById(R.id.pager_dots);

    homeViewPagerAdapter = new HomeViewPagerAdapter(mContext, eventImagesUrl);

    viewPager.setAdapter(homeViewPagerAdapter);

    setupPagerIndidcatorDots();

    ivArrayDotsPager[0].setImageResource(R.drawable.page_indicator_selected);

    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            for (int i = 0; i < ivArrayDotsPager.length; i++) {
                ivArrayDotsPager[i].setImageResource(R.drawable.page_indicator_unselected);
            }
            ivArrayDotsPager[position].setImageResource(R.drawable.page_indicator_selected);
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
}

Create a method setupPagerIndidcatorDots() :

private void setupPagerIndidcatorDots() {
    ivArrayDotsPager = new ImageView[eventImagesUrl.size()];
    for (int i = 0; i < ivArrayDotsPager.length; i++) {
        ivArrayDotsPager[i] = new ImageView(getActivity());
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.setMargins(5, 0, 5, 0);
        ivArrayDotsPager[i].setLayoutParams(params);
        ivArrayDotsPager[i].setImageResource(R.drawable.page_indicator_unselected);
        //ivArrayDotsPager[i].setAlpha(0.4f);
        ivArrayDotsPager[i].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                view.setAlpha(1);
            }
        });
        llPagerDots.addView(ivArrayDotsPager[i]);
        llPagerDots.bringToFront();
    }
RediOne1
  • 10,389
  • 6
  • 25
  • 46
Ishant Garg
  • 829
  • 9
  • 6
  • And what is `HomeViewPagerAdapter`? – CoolMind Jul 17 '18 at 10:28
  • Modify onPageSelect little to work perfectly as below override fun onPageSelected(position: Int) { for (i in 0 until ivArrayDotsPager!!.size) { if (i != position) ivArrayDotsPager!![i].setImageDrawable(ContextCompat.getDrawable(applicationContext, R.drawable.unselected_dot)) else ivArrayDotsPager!![i].setImageDrawable(ContextCompat.getDrawable(applicationContext, R.drawable.selected_dot)) } linearLayout!!.bringToFront()} – amity Aug 29 '18 at 12:40
20

You can check out my library to handle your request : https://github.com/tommybuonomo/dotsindicator

In your XML layout

  <com.tbuonomo.viewpagerdotsindicator.DotsIndicator
      android:id="@+id/dots_indicator"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerHorizontal="true"
      app:dotsColor="@color/colorPrimary"
      app:dotsSize="16dp"
      app:dotsWidthFactor="3"
      />

In your Java code

dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator);
viewPager = (ViewPager) findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
dotsIndicator.setViewPager(viewPager);
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Tommy Buonomo
  • 201
  • 2
  • 3
  • So simple to use and looks great especially with the animations... thanks! I did, however, have to add `tools:replace="android:label"` to the `application` tag in my `AndroidManifest.xml` to get rid of an error about that tag being defined twice and causing a gradle build fail. – Fat Monk Oct 31 '17 at 21:03
  • 1
    I am getting a `gradle` error, though `Error:(39, 20) All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions 27.0.0, 25.3.1. Examples include 'com.android.support:support-compat:27.0.0' and 'com.android.support:animated-vector-drawable:25.3.1'` - how can i fix this? – Fat Monk Oct 31 '17 at 21:16
  • how to scroll automatically DotsIndicator – Shivam Kumar Dec 26 '18 at 09:10
  • hey ..I implemented this..I used but dots are getting displayed at extreme left ..how to align dots at centre? –  Dec 12 '19 at 14:18
13

When you want something similar to this with the latest ViewPager2 and Kotlin

Everything is self-explaining, no need to explain!

enter image description here

1. Your Activity or Fragment

val imageList = listOf(
        ImageModel(R.drawable.offer1),
        ImageModel(R.drawable.splash),
        ImageModel(R.drawable.offer1),
        ImageModel(R.drawable.splash2)
    )

    val adapter = HomeOffersAdapter()
    adapter.setItem(imageList)
    photos_viewpager.adapter = adapter

    TabLayoutMediator(tab_layout, photos_viewpager) { tab, position ->
    }.attach()
}

2. 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="@dimen/dp_200">

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/photos_viewpager"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_200" />

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tab_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_gravity="bottom|center"
    app:tabBackground="@drawable/tab_selector"
    app:tabGravity="center"
    app:tabIndicatorHeight="0dp"
    app:tabSelectedTextColor="@android:color/transparent"
    app:tabTextColor="@android:color/transparent" />

3. Drawable: tab_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/dot_selected" android:state_selected="true" />
<item android:drawable="@drawable/dot_default" />

4. Drawable: dot_selected.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thickness="@dimen/dp_8"
android:useLevel="false">

<solid android:color="@color/colorPrimary" />

<stroke
    android:width="@dimen/dp_1"
    android:color="@android:color/white" />

5. Drawable: dot_default.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thickness="@dimen/dp_8"
android:useLevel="false">

<solid android:color="@android:color/transparent" />

<stroke
    android:width="@dimen/dp_1"
    android:color="@android:color/white" />

6. Adapter

class HomeOffersAdapter : RecyclerView.Adapter<HomeOffersAdapter.HomeOffersViewHolder>() {

private var list: List<ImageModel> = listOf()


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeOffersViewHolder {
    return HomeOffersViewHolder(parent)
}


override fun onBindViewHolder(holder: HomeOffersViewHolder, position: Int) {
    holder.bind(list[position])
}

fun setItem(list: List<ImageModel>) {
    this.list = list
    notifyDataSetChanged()
}

override fun getItemCount(): Int = list.size

class HomeOffersViewHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {

    constructor(parent: ViewGroup) : this(
        LayoutInflater.from(parent.context).inflate(
            R.layout.pager_item,
            parent, false
        )
    )

    fun bind(imageModel: ImageModel) {
        itemView.offerImage.setImageResource(imageModel.image)
    }
}

}

7. Layout: pager_item.xml

<LinearLayout 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:fitsSystemWindows="true"
android:orientation="vertical">

<androidx.appcompat.widget.AppCompatImageView
    android:id="@+id/offerImage"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_200"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    tools:src="@drawable/offer1" />

Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
9

2021, how to actually do it. ViewPager2 only.

Refer to this excellent short article, which has a couple of problems:

https://medium.com/@adrian.kuta93/android-viewpager-with-dots-indicator-a34c91e59e3a

Starting with a normal Android Studio default project as of 2021, with a reasonably new minimum (24 currently)...

General concept:

Make a standard TabLayout, but replace each "tab unit" with "a little dot" rather than the usual text.

In TabLayout, you can indeed replace each "tab unit" using "tabBackground":

        app:tabBackground="@drawable/tab_selector"

So add the following to the XML of your screen, which has a ViewPager2:

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:background="#00FFFFFF"
        app:tabBackground="@drawable/tab_selector"
        app:tabIndicatorGravity="center"
        app:tabIndicatorHeight="0dp"/>

Notice carefully we are replacing each and every one of the "tab units" in the TabLayout, with our own "tab_selector".

To be completely clear, "tabBackground" means the individual little "tab units", not the whole tab bar system.

(Aside, note that the two tricks tabIndicatorGravity and tabIndicatorHeight will indeed get rid of the "boxes" that are the usual "tab units".)

Next create three drawables in the obvious way, tab_selector and the two different dots. See the above article or 100s of examples on this page.

The magic code:

In your onCreate have the expected code ...

viewPager = findViewById(R.id.simple_slide_pager);
tab_layout = findViewById(R.id.tab_layout);
viewPager.setAdapter(new ScreenSlidePagerAdapter(this));

and then here at last is the magic code fragment to make it work. Follow the above by:

Up to date for 2021:

TabLayoutMediator tabLayoutMediator =
  new TabLayoutMediator(tab_layout, viewPager, true,
    new TabLayoutMediator.TabConfigurationStrategy() {
      @Override public void onConfigureTab(
        @NonNull TabLayout.Tab tab, int position) { }
    }
);
tabLayoutMediator.attach();

It's done.

(Inside onConfigureTab you can do any sound effects or whatever the heck might be needed. For shorter syntax see the key comment by @F1iX above.)

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • This was a great help, thanks. When I set in the two DOT.XML files, I'd expect the dot bar to adjust size accordingly - but it does not. I need them bigger for our audience, so was hoping you could direct me where to make that change so they're larger on screen? – Bungles Oct 03 '21 at 23:17
  • hell that's a tough one, I'm rusty. i think you have to actually make the thing that holds it (the tab_selector ?) BIGGER. that determines the size? I am sorry ... it s a good question, ask a new question about it ! – Fattie Oct 04 '21 at 00:35
2
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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="match_parent"
    android:orientation="vertical">

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vpImage"
        android:layout_width="match_parent"
        android:layout_height="@dimen/_150sdp" />

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tlImage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabBackground="@drawable/selector_product_image"
        app:tabGravity="center"
        app:tabIndicatorHeight="0dp"
        app:tabMaxWidth="12dp"
        app:tabRippleColor="@null" />

</androidx.appcompat.widget.LinearLayoutCompat>

ImageAdapter imageAdapter = new ImageAdapter(getActivity(), arrayListSlider);
binding.vpImage.setOffscreenPageLimit(1);
binding.vpImage.setAdapter(imageAdapter);
binding.tlImage.setupWithViewPager(binding.vpImage);

selector_product_image.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/image_selected" android:state_selected="true" />
    <item android:drawable="@drawable/image_unselected" />

</selector>

image_selected.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="0dp"
            android:shape="ring"
            android:thickness="4dp"
            android:useLevel="false">
            <solid android:color="@color/colorAccent" />
        </shape>
    </item>
</layer-list>

image_unselected.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="0dp"
            android:shape="ring"
            android:thickness="4dp"
            android:useLevel="false">
            <solid android:color="@color/colorPrimary" />
        </shape>
    </item>
</layer-list>

ImageAdapter.java

class ImageAdapter extends PagerAdapter {

  private Context context;
  private ArrayList<ImageModel> arrayList;
  private LayoutInflater layoutInflater;

  public ImageAdapter(Context context, ArrayList<ImageModel> arrayList) {
      this.context = context;
      this.arrayList = arrayList;
      this.layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  }

  @Override
  public int getCount() {
      return arrayList.size();
  }

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

  @Override
  public Object instantiateItem(ViewGroup container, int position) {
      View view = layoutInflater.inflate(R.layout.row_slider_image, container, false);

      AppCompatImageView ivProductImage = view.findViewById(R.id.ivProductImage);

      if (!TextUtils.isEmpty(arrayList.get(position).getImage())) {
          Glide.with(context)
                  .load(arrayList.get(position).getImage())
                  .apply(new RequestOptions().placeholder(R.drawable.no_image).error(R.drawable.no_image))
                  .into(ivProductImage);
      }

      container.addView(view);
      return view;
  }

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

row_slider_image.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/ivProductImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:scaleType="fitXY"
        android:src="@drawable/no_image" />

</androidx.appcompat.widget.LinearLayoutCompat>
Ketan Ramani
  • 4,874
  • 37
  • 42
1

For Viewpager2, follow the same steps which suggested by @RediOne1 and in the activity or fragment use below code to attach tablayout with viwpager2

 val tabLayoutMediator  = TabLayoutMediator(binding.tabLayout,binding.offersVp) { _, _ -> }
 tabLayoutMediator.attach()
Abhijith Brumal
  • 1,652
  • 10
  • 14
0

Your xml

  <RelativeLayout
                android:id="@+id/rl_speed"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_above="@+id/ll_dashboard_buttons"
                android:layout_below="@+id/ib_menu">

                <com.smart.gps.speedometer.app.utils.SmartViewPager
                    android:id="@+id/view_pager"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" 
                   app:layout_behavior="@string/appbar_scrolling_view_behavior">
                   </com.smart.gps.speedometer.app.utils.SmartViewPager>

                   <android.support.design.widget.TabLayout
                    android:id="@+id/sliding_tabs"
                    android:layout_alignParentBottom="true"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:tabBackground="@drawable/tab_selector"
                    app:tabIndicatorHeight="0dp"
                    app:tabGravity="center"
                    />

create a drawable. right click on drawable -> new -> Drawable file resource name that file

tab_selector.xml

<item android:drawable="@drawable/selected_tab"
    android:state_selected="true"/>

<item android:drawable="@drawable/unselected_tab"/>

Now there is two more xml files. create two more xml files with respected name. these are the selecter indicator and unselected indicator

selected_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="0dp"
            android:shape="ring"
            android:thickness="4dp"
            android:useLevel="false">
            <solid android:color="@color/highspeed"/>
        </shape>
    </item>
</layer-list>

unselected_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape
            android:innerRadius="0dp"
            android:shape="ring"
            android:thickness="2dp"
            android:useLevel="false">
            <solid android:color="@android:color/darker_gray"/>
        </shape>
    </item>
</layer-list>
0

Place ViewFlipper and viewFlipper_linear_dot_lay(Linearlayout) on samebaseline and follow the below one

viewFlipper_linear_dot_lay= (LinearLayout) findViewById(R.id.dots_lay);
setupDotsOnViewPager(images_viewFlipper);
    for (int i = 0; i < images_viewFlipper.size(); i++) {
    //Add Images to ViewFlipper 
    }



private void setupDotsOnViewPager(ArrayList images_viewFlipper) {
                    images_linear = new ImageView[images_viewFlipper.size()];
                    for (int i = 0; i < images_linear.length; i++) {
                        images_linear[i] = new ImageView(this);
                        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                        params.setMargins(5, 0, 5, 0);
                        params.gravity = Gravity.BOTTOM | Gravity.CENTER;
                        images_linear[i].setLayoutParams(params);
                        images_linear[i].setImageResource(R.drawable.unselected);
                        viewFlipper_linear_dot_lay.addView(images_linear[i]);
                        viewFlipper_linear_dot_lay.bringToFront();
                    }
                }

And OnRight & OnLeft getsures place the below code

for (int i = 0; i < images_linear.length; i++) {
 images_linear[i].setImageResource(R.drawable.unselected);
 }
images_linear[viewFlipper.getDisplayedChild()].setImageResource(R.drawable.selected);
VV W
  • 169
  • 7
0

Add dependencies > Sync the Gradle

implementation 'com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2'

In your java code

 dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator3);


myViewPagerAdapter = new MyViewPagerAdapter();
        viewPager.setAdapter(myViewPagerAdapter);
        viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
        dotsIndicator.setViewPager(viewPager);

In your layout

<com.tbuonomo.viewpagerdotsindicator.SpringDotsIndicator
android:id="@+id/spring_dots_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:dampingRatio="0.5"
app:dotsColor="@color/material_white"
app:dotsStrokeColor="@color/material_yellow"
app:dotsCornerRadius="2dp"
app:dotsSize="16dp"
app:dotsSpacing="6dp"
app:dotsStrokeWidth="2dp"
app:stiffness="300"
/>
  • nice ,but this uses AndroidX. I am in situation that i cannot migrate my project into AndroidX now. – meekash55 Nov 11 '20 at 14:04
  • @meekash55 I prefer you migrate to android X at the beginning build App, cause there many cases that make you should move to Android X, this case is one of the samples. – Tri Mueri Sandes May 18 '21 at 22:34
  • I think to migrate not took too long, but this is your decision. adjust to your situation and conditions – Tri Mueri Sandes May 18 '21 at 22:43