Вероятно, многие из вас (как я) имеют проблемы с созданием ViewPager с нижними точками, например:

Как вы создаете такой Android ViewPager?
Вероятно, многие из вас (как я) имеют проблемы с созданием ViewPager с нижними точками, например:

Как вы создаете такой Android ViewPager?
Все, что нам нужно: ViewPager, TabLayout и 2 drawables для выбранных точек и точек по умолчанию.
 Во-первых, мы должны добавить TabLayout к нашему макету экрана и связать его с ViewPager. Мы можем сделать это двумя способами:
TabLayout во ViewPager<android.support.v4.view.ViewPager
    android:id="@+id/photos_viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.TabLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>
 В этом случае
TabLayoutбудет автоматически соединен сViewPager, ноTabLayoutбудет рядом сViewPager, а не над ним.
TabLayout<android.support.v4.view.ViewPager
    android:id="@+id/photos_viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
<android.support.design.widget.TabLayout
    android:id="@+id/tab_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
 В этом случае мы можем поместить
TabLayoutгде угодно, но мы должны соединитьTabLayoutсViewPagerпрограммно
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);
  Как только мы создали наш макет, мы должны подготовить наши точки. Итак, мы создаем три файла: selected_dot.xml, default_dot.xml и tab_selector.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>
 <?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>
 <?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>
  Теперь нам нужно добавить только 3 строки кода в TabLayout в нашем XML-макете.
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
		Сначала создайте макет, в котором укажите один LinerLayout для точек, которые отображаются поверх вашего 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>
 После этого создайте 2 рисунка
1. Не выбранный 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. Выбранный 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>
 После этого установите адаптер
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) {
        }
    });
}
 Создайте метод 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();
    }
		Вы можете проверить мою библиотеку для обработки вашего запроса: https://github.com/tommybuonomo/dotsindicator
В вашем макете XML
  <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"
      />
 В вашем коде Java
dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator);
viewPager = (ViewPager) findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
dotsIndicator.setViewPager(viewPager);
		Ваш 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"
                    />
 создать Drawable. щелкните правой кнопкой мыши на drawable → new → Drawable.
tab_selector.xml
<item android:drawable="@drawable/selected_tab"
    android:state_selected="true"/>
<item android:drawable="@drawable/unselected_tab"/>
  Теперь есть еще два XML файла. создайте еще два XML файла с уважаемым именем. это индикатор селектора и невыбранный индикатор
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>
		Поместите ViewFlipper и viewFlipper_linear_dot_lay (Linearlayout) на одну и ту же базовую линию и следуйте приведенному ниже
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();
                    }
                }
 И OnRight & OnLeft получает размещенный ниже код
for (int i = 0; i < images_linear.length; i++) {
 images_linear[i].setImageResource(R.drawable.unselected);
 }
images_linear[viewFlipper.getDisplayedChild()].setImageResource(R.drawable.selected);
		<android.support.v4.view.ViewPager
      android:id="@+id/vpImage"
      android:layout_width="match_parent"
      android:layout_height="@dimen/_120sdp" />
<android.support.design.widget.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" />
 ImageAdapter imageAdapter = new ImageAdapter(context, arrayList);
vpImage.setOffscreenPageLimit(1);
vpImage.setAdapter(imageAdapter);
tlImage.setupWithViewPager(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
<android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <android.support.v7.widget.AppCompatImageView
        android:id="@+id/ivProductImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/no_image" />
</android.support.v7.widget.LinearLayoutCompat>