Comment créer un pager Android View avec un indicateur de points?

155

Probablement beaucoup d'entre vous (comme moi) ont des problèmes avec la création ViewPageravec les points du bas, comme ceci: entrez la description de l'image ici

Comment créer un tel ViewPager Android?

RediOne1
la source

Réponses:

318

Tout ce dont nous avons besoin sont: ViewPager , TabLayout et 2 drawables pour les points sélectionnés et par défaut.

Tout d'abord, nous devons ajouter TabLayoutà notre disposition d'écran et la connecter avec ViewPager. Nous pouvons le faire de deux manières:


Imbriqué TabLayoutdansViewPager

<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>

Dans ce cas TabLayoutsera automatiquement connecté avec ViewPager, mais TabLayoutsera à côté ViewPager, pas dessus.


Séparé 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"/>

Dans ce cas, nous pouvons mettre TabLayoutn'importe où, mais nous devons nous connecter TabLayoutavec par ViewPagerprogramme

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);

Une fois que nous avons créé notre mise en page, nous devons préparer nos points. Nous créons donc trois fichiers: selected_dot.xml, default_dot.xmlet 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>

Maintenant, nous devons ajouter seulement 3 lignes de code TabLayoutdans notre mise en page XML.

app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"

Pour ViewPager2lire cet article:

ViewPager (2) avec indicateur de points sur medium.com

Les votes positifs sont les bienvenus ;-)

RediOne1
la source
18
vous feriez mieux de mettre cela dans la section documentation. cela a aidé cependant.
Erfan GLMPR le
3
@AmitSingh Vous pouvez utiliser app:tabMaxWidthdans TabLayout
RediOne1
3
Je ne sais pas si je n'ai pas suivi correctement les instructions mais j'ai également dû ajouter ce qui suit afin de ne montrer que les points avec un espace décent entre eux: app:tabMaxWidth="30dp" app:tabTextColor="@color/transparent2" app:tabSelectedTextColor="@color/transparent2" app:tabIndicatorHeight="0dp" android:layout_gravity="bottom|center"
Sept
3
Pour supprimer l'espacement entre les points app: tabPaddingStart = "@ dimen / margin_7.5" app: tabPaddingEnd = "@ dimen / margin_7.5"
dev_mg99
30

Créez d'abord une mise en page, en donnant un LinerLayout pour les points qui s'affichent sur votre page de visualisation

<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>

Après cela, créez 2 drawables

1. Dessinable non sélectionné

<?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. Dessinable sélectionné

<?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>

Après cet adaptateur défini

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) {

        }
    });
}

Créez une méthode 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();
    }
Ishant Garg
la source
Et qu'est-ce que c'est HomeViewPagerAdapter?
CoolMind
Modifiez onPageSelect peu pour fonctionner parfaitement comme ci-dessous remplacez fun onPageSelected (position: Int) {for (i in 0 jusqu'à 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
19

Vous pouvez consulter ma bibliothèque pour gérer votre demande: https://github.com/tommybuonomo/dotsindicator

Dans votre mise en page 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"
      />

Dans votre code Java

dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator);
viewPager = (ViewPager) findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
dotsIndicator.setViewPager(viewPager);
Tommy Buonomo
la source
Si simple à utiliser et a fière allure surtout avec les animations ... merci! Cependant, j'ai dû ajouter tools:replace="android:label"à la applicationbalise dans my AndroidManifest.xmlpour me débarrasser d'une erreur au sujet de cette balise définie deux fois et provoquant un échec de construction de gradle.
Fat Monk du
gradleCependant, j'obtiens une erreur 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'- comment puis-je résoudre ce problème?
Fat Monk
comment faire défiler automatiquement DotsIndicator
Shivam Kumar
hé .. J'ai implémenté ceci..J'ai utilisé <com.tbuonomo.viewpagerdotsindicator.WormDotsIndicator> mais les points sont affichés à l'extrême gauche .. comment aligner les points au centre?
3
<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>
Ketan Ramani
la source
1

Votre 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"
                    />

créer un dessin. clic droit sur 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"/>

Il y a maintenant deux autres fichiers xml. créez deux autres fichiers xml avec un nom respecté. ce sont l'indicateur de sélection et l'indicateur non sélectionné

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>
Exception de pointeur nul
la source
SmartViewPagerEst probablement votre vue personnalisée.
CoolMind
1

Lorsque vous voulez quelque chose de similaire avec les derniers ViewPager2 et Kotlin

Tout s'explique d'elle-même, pas besoin d'expliquer!

entrez la description de l'image ici

1. Votre activité ou 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. Disposition

<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. Dessiné: 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. Dessinable: 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. Dessiné: 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. Adaptateur

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. Disposition: 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
la source
0

Placez ViewFlipper et viewFlipper_linear_dot_lay (Linearlayout) sur la même ligne de base et suivez celle ci-dessous

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();
                    }
                }

Et OnRight & OnLeft obtientures placer le code ci-dessous

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
la source
0

Ajouter des dépendances> Synchroniser le Gradle

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

Dans votre code java

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


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

Dans votre mise en page

<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"
/>
Mue
la source