如何使用点指示器创建Android View寻呼机?

Red*_*ne1 142 android indicator android-viewpager android-tablayout

可能你们很多人(像我一样)都有ViewPager使用底点创建的问题,像这样: 在此输入图像描述

你如何创建这样的Android ViewPager?

Red*_*ne1 286

我们所需要的只是:ViewPager,TabLayout和2个选定和默认点的drawable.

首先,我们必须添加TabLayout到我们的屏幕布局,并将其连接ViewPager.我们可以通过两种方式做到这一点:


嵌套TabLayoutViewPager

<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>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,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"/>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们可以把TabLayout任何地方,但我们必须连接TabLayoutViewPager编程

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);
Run Code Online (Sandbox Code Playgroud)

一旦我们创建了布局,我们就必须准备好我们的点.因此,我们创建三个文件:selected_dot.xml,default_dot.xmltab_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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

现在我们需要TabLayout在XML布局中只添加3行代码.

app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
Run Code Online (Sandbox Code Playgroud)

  • 你最好把它放在文档部分.虽然它有所帮助. (16认同)
  • @ErfanGholampour http://stackoverflow.com/documentation/android/692/viewpager/22945/viewpager-with-a-dots-indicator#t=201609141951318798598 (2认同)
  • @AmitSingh您可以在TabLayout中使用`app:tabMaxWidth` (2认同)
  • 我不知道我是否没有正确地按照说明操作,但我还必须添加以下内容,以便仅显示它们之间有足够空间的点:`app:tabMaxWidth ="30dp"app:tabTextColor ="@ color/transparent2"app:tabSelectedTextColor ="@ color/transparent2"app:tabIndicatorHeight ="0dp"android:layout_gravity ="bottom | center"` (2认同)
  • 要删除点之间的间距app:tabPaddingStart ="@ dimen/margin_7.5"app:tabPaddingEnd ="@ dimen/margin_7.5" (2认同)

小智 28

首先创建一个布局,为您的View Pager显示一个LinerLayout

<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>
Run Code Online (Sandbox Code Playgroud)

之后创建2个drawables

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

之后设置适配器

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

        }
    });
}
Run Code Online (Sandbox Code Playgroud)

创建方法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();
    }
Run Code Online (Sandbox Code Playgroud)


小智 15

您可以查看我的库以处理您的请求: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"
      />
Run Code Online (Sandbox Code Playgroud)

在您的Java代码中

dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator);
viewPager = (ViewPager) findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
dotsIndicator.setViewPager(viewPager);
Run Code Online (Sandbox Code Playgroud)


Fat*_*tie 10

2021年,如何实际去做。仅限 ViewPager2。

请参阅这篇优秀的短文,其中有几个问题:

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

从 2021 年起的普通 Android Studio 默认项目开始,具有合理的新最小值(当前为 24 个)...

一般概念:

制作一个标准的 TabLayout,但将每个“选项卡单元”替换为“一个小点”而不是通常的文本。

在 TabLayout 中,您确实可以使用“tabBackground”替换每个“选项卡单元”:

        app:tabBackground="@drawable/tab_selector"
Run Code Online (Sandbox Code Playgroud)

因此,将以下内容添加到具有 ViewPager2 的屏幕的 XML 中:

    <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"/>
Run Code Online (Sandbox Code Playgroud)

请仔细注意,我们正在用我们自己的“tab_selector”替换 TabLayout 中的每一个“选项卡单元

需要完全明确的是,“tabBackground”是指单个的小“选项卡单元”,而不是整个选项卡栏系统。

(另外,请注意 tabIndicatorGravity 和 tabIndicatorHeight 这两个技巧确实会消除通常的“选项卡单位”的“框”。)

接下来以显而易见的方式创建三个可绘制对象:tab_selector和两个不同的点。请参阅上述文章或本页上的数百个示例。

神奇的代码:

在你onCreate有预期的代码...

viewPager = findViewById(R.id.simple_slide_pager);
tab_layout = findViewById(R.id.tab_layout);
viewPager.setAdapter(new ScreenSlidePagerAdapter(this));
Run Code Online (Sandbox Code Playgroud)

最后是让它工作的神奇代码片段。遵循上述方法:

2021 年最新情况:

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

完成。

(在里面onConfigureTab你可以做任何声音效果或任何可能需要的东西。有关更短的语法,请参阅上面 @F1iX 的关键评论。)


Kis*_*nki 7

当你想用最新的ViewPager2Kotlin做类似的事情时

一切都是自明的,无需解释!

在此处输入图片说明

1.您的活动或片段

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()
}
Run Code Online (Sandbox Code Playgroud)

2. 布局

<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" />
Run Code Online (Sandbox Code Playgroud)

3.可绘制: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" />
Run Code Online (Sandbox Code Playgroud)

4.可绘制: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" />
Run Code Online (Sandbox Code Playgroud)

5. 可绘制: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" />
Run Code Online (Sandbox Code Playgroud)

6. 适配器

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

}

7.布局: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" />
Run Code Online (Sandbox Code Playgroud)