Bagaimana Anda membuat Pager Tampilan Android dengan indikator titik?

155

Mungkin banyak dari Anda (seperti saya), memiliki masalah dengan membuat ViewPagerdengan titik-titik terbawah, seperti ini: masukkan deskripsi gambar di sini

Bagaimana Anda membuat ViewPager Android seperti itu?

RediOne1
sumber

Jawaban:

318

Yang kami butuhkan adalah: ViewPager , TabLayout , dan 2 drawable untuk titik-titik yang dipilih dan default.

Pertama, kita harus menambahkan TabLayouttata letak layar kita, dan menghubungkannya dengan ViewPager. Kita dapat melakukan ini dengan dua cara:


Bersarang TabLayoutdiViewPager

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

Dalam hal ini TabLayoutakan secara otomatis terhubung dengan ViewPager, tetapi TabLayoutakan di sebelah ViewPager, bukan di atasnya.


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

Dalam hal ini, kita dapat meletakkan di TabLayoutmana saja, tetapi kita harus terhubung TabLayoutdengan secara ViewPagerterprogram

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

Setelah kami membuat tata letak kami, kami harus menyiapkan titik-titik kami. Jadi kita membuat tiga file: selected_dot.xml, default_dot.xmldan 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>

Sekarang kita perlu menambahkan hanya 3 baris kode ke TabLayoutdalam tata letak XML kita.

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

Untuk ViewPager2membaca artikel ini:

ViewPager (2) dengan indikator titik di medium.com

Up-vote dipersilahkan ;-)

RediOne1
sumber
18
Anda sebaiknya meletakkan ini di bagian dokumentasi. itu membantu.
Erfan GLMPR
3
@AmitSingh Anda dapat menggunakan app:tabMaxWidthdi TabLayout
RediOne1
3
Saya tidak tahu apakah saya tidak mengikuti petunjuk dengan benar, tetapi saya juga harus menambahkan yang berikut untuk menunjukkan hanya titik-titik dengan ruang yang layak di antara mereka: app:tabMaxWidth="30dp" app:tabTextColor="@color/transparent2" app:tabSelectedTextColor="@color/transparent2" app:tabIndicatorHeight="0dp" android:layout_gravity="bottom|center"
Tujuh
3
Untuk menghapus spasi antar titik aplikasi: tabPaddingStart = "@ dimen / margin_7.5" app: tabPaddingEnd = "@ dimen / margin_7.5"
dev_mg99
30

Pertama, buat tata letak, dengan memberi satu LinerLayout untuk Dots yang ditampilkan di atas Pager Tampilan Anda

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

Setelah itu buat 2 drawable

1. Drawable Tidak Dipilih

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

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

Setelah itu atur 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) {

        }
    });
}

Buat metode 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
sumber
Dan apa itu HomeViewPagerAdapter?
CoolMind
Ubah onPageSeleksi sedikit agar berfungsi sempurna seperti di bawah ini mengesampingkan kesenangan onPageSelected (posisi: Int) {for (i in 0 hingga ivArrayDotsPager !!. Size) {if (i! = Position) ivArrayDotsPager !! [i] .setImageDrawable (ContextCompat.getDrawable ( applicationContext, R.drawable.unselected_dot)) lain ivArrayDotsPager !! [i] .setImageDrawable (ContextCompat.getDrawable (applicationContext, R.drawable.selected_dot))} linearLayout !!. bawaToFront ()}
amity
19

Anda dapat memeriksa perpustakaan saya untuk menangani permintaan Anda: https://github.com/tommybuonomo/dotsindicator

Dalam tata letak XML Anda

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

Dalam kode Java Anda

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
sumber
Sangat mudah digunakan dan terlihat hebat terutama dengan animasinya ... terima kasih! Aku, bagaimanapun, harus menambahkan tools:replace="android:label"ke applicationtag di saya AndroidManifest.xmluntuk menyingkirkan kesalahan tentang tag yang didefinisikan dua kali dan menyebabkan membangun Gradle gagal.
Fat Monk
Namun, saya mendapatkan gradlekesalahan 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'- bagaimana saya bisa memperbaikinya?
Fat Monk
cara menggulir secara otomatis DotsIndicator
Shivam Kumar
hei .. saya menerapkan ini .. saya menggunakan <com.tbuonomo.viewpagerdotsindicator.WormDotsIndicator> tetapi titik-titik semakin banyak ditampilkan di kiri ekstrim .. bagaimana cara menyelaraskan titik-titik di tengah?
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
sumber
1

Xml Anda

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

buat drawable. klik kanan pada drawable -> new -> Drawable file resource name file itu

tab_selector.xml

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

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

Sekarang ada dua file xml lagi. buat dua file xml lagi dengan nama yang dihormati. ini adalah indikator pemilih dan indikator tidak dipilih

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>
Pengecualian Null Pointer
sumber
Mungkin SmartViewPagertampilan khusus Anda.
CoolMind
1

Ketika Anda menginginkan sesuatu yang mirip dengan ini dengan ViewPager2 dan Kotlin terbaru

Semuanya menjelaskan sendiri, tidak perlu dijelaskan!

masukkan deskripsi gambar di sini

1. Aktivitas atau Fragmen Anda

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. Tata Letak

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

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

Tempatkan ViewFlipper dan viewFlipper_linear_dot_lay (Linearlayout) di samebaseline dan ikuti yang di bawah ini

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

Dan OnRight & OnLeft memastikan tempatkan kode di bawah ini

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

Tambahkan dependensi> Sinkronkan Gradle

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

Dalam kode java Anda

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


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

Dalam tata letak Anda

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