A view pager indicator view to deal with a large amount of pages.

Overview

Attention

I'm not going to support this anymore. Just use a better solution, e.g. this one Indefinite-Pager-Indicator

BubblePagerIndicator

A view pager indicator view to deal with a large amount of pages. Nice scale and transition animations are supported.

Sample

Usage

  1. Add mavenCentral() to repositories block in your gradle file.
  2. Add implementation 'com.github.shuhart:bubblepagerindicator:1.2.0' to your dependencies.
  3. Add BubblePageIndicator into your layouts or view hierarchy:
<com.shuhart.bubblepagerindicator.BubblePageIndicator
    android:id="@+id/indicator"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/pager"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="32dp"
    android:layout_marginTop="32dp"
    app:bpi_fillColor="@color/colorAccent"
    app:bpi_pageColor="@color/colorPrimary"
    app:bpi_radius="8dp"
    app:bpi_marginBetweenCircles="6dp"
    app:bpi_onSurfaceCount="@integer/default_bubble_indicator_on_surface_count"
    app:bpi_risingCount="@integer/default_bubble_indicator_rising_count"/>
  1. Attach indicator to the ViewPager instance:
pager = findViewById(R.id.pager);
indicator = findViewById(R.id.indicator);
adapter = new ViewPagerAdapter();
pager.setAdapter(adapter);
indicator.setViewPager(pager);

An adapter should be attached to the ViewPager before calling indicator.setViewPager(pager).

  1. You can customize the behavior in runtime:
indicator.setOnSurfaceCount(3);
indicator.setRisingCount(2);
// resolved color
indicator.setFillColor(ContextCompat.getColor(this, R.color.colorAccent));
// resolved color
indicator.setPageColor(ContextCompat.getColor(this, R.color.colorPrimary));
// in px
indicator.setRadius(getResources().getDimensionPixelSize(R.dimen.default_bubble_indicator_radius));
// in px
indicator.setMarginBetweenCircles(getResources().getDimensionPixelSize(
            R.dimen.default_bubble_indicator_circles_margin));

Customization

Attribute Description Default Value
bpi_pageColor Current page circle color. #FFFFFF
bpi_fillColor Circles color #000000
bpi_radius Normal circle radius. 3dp
bpi_marginBetweenCircles Margin between centers of circles. 3dp
bpi_onSurfaceCount A number of circles with full radius (bpi_radius) 5
bpi_risingCount A number of scaled circles. 2

Maximum number of circles visible to the user is bpi_onSurfaceCount + bpi_risingCount * 2 (Default is 9).
At the beginning only bpi_onSurfaceCount + bpi_risingCount (Default is 7) circles are visible.
Radius for a rising circle is scaled by power of 2 with some correction applied.
In every aspect the library is mimicking the Instagram indicator behavior.

Special thanks

@tree1891 for his help in fixing many annoying issues.

License

Copyright 2017 Bogdan Kornev.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Custom OnSurfaceCount issue

    Custom OnSurfaceCount issue

    Navigating away from the screen with ViewPager and dots and then navigating back, custom OnSurfaceCount not restored and layout broken. ex: setOnSurfaceCount(1);

    bug 
    opened by tree1891 15
  • Layout cropped

    Layout cropped

    At the beginning, pager adapter is initialized, not later. It does work if set OnSurfaceCount by 3.

            BubblePageIndicator pageIndicator = findViewById(R.id.page_indicator);
            pageIndicator.setViewPager(viewPager);
            pageIndicator.setEnabled(false);
    

    image

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
            <com.shuhart.bubblepagerindicator.BubblePageIndicator
                android:id="@+id/page_indicator"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="8dp"
                android:layout_marginBottom="8dp"
                app:fillColor="@color/azure"
                app:pageColor="#d8d8d8"
                app:radius="4dp" />
    
            <android.support.v4.view.ViewPager
                android:id="@+id/viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
    
        </LinearLayout>
    
    opened by tree1891 12
  • NPE onMeasure

    NPE onMeasure

    Already updated to v1.1.0 from 1.0.13 and still have the same issue:

    java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.view.PagerAdapter android.support.v4.view.ViewPager.getAdapter()' on a null object reference
            at com.shuhart.bubblepagerindicator.BubblePageIndicator.getCount(BubblePageIndicator.java:185)
            at com.shuhart.bubblepagerindicator.BubblePageIndicator.getInitialStartX(BubblePageIndicator.java:480)
            at com.shuhart.bubblepagerindicator.BubblePageIndicator.measureStartX(BubblePageIndicator.java:473)
            at com.shuhart.bubblepagerindicator.BubblePageIndicator.onMeasure(BubblePageIndicator.java:468)
            at android.view.View.measure(View.java:22002)
            at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
            at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
            at android.support.design.widget.CollapsingToolbarLayout.onMeasure(CollapsingToolbarLayout.java:411)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
            at android.support.design.widget.AppBarLayout.onMeasure(AppBarLayout.java:234)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
            at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:739)
            at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:811)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
            at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6580)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
            at com.android.internal.policy.DecorView.onMeasure(DecorView.java:721)
            at android.view.View.measure(View.java:22002)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2410)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1498)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1751)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1386)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6733)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
            at android.view.Choreographer.doCallbacks(Choreographer.java:723)
            at android.view.Choreographer.doFrame(Choreographer.java:658)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
            at android.os.Handler.handleCallback(Handler.java:789)
            at android.os.Handler.dispatchMessage(Handler.java:98)
            at android.os.Looper.loop(Looper.java:164)
            at android.app.ActivityThread.main(ActivityThread.java:6541)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
    

    I defined it in XML like this:

    <com.shuhart.bubblepagerindicator.BubblePageIndicator
        android:id="@+id/bubble_indicator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="10dp"
        android:fitsSystemWindows="true"
        android:visibility="visible"
        app:bpi_fillColor="@color/red"
        app:bpi_pageColor="@color/green"
        app:bpi_radius="8dp"
        app:bpi_marginBetweenCircles="6dp"
        app:bpi_onSurfaceCount="3"
        app:bpi_risingCount="1"/>
    

    Looks like onMeasure is being called as soon as the activity is created but BubblePageIndicator doesn't have any viewPager reference yet because I set it later in the lifecycle, and there's no null checks in the BubblePageIndicator class:

    @Override
    protected int getCount() {
        return viewPager.getAdapter().getCount();
    }
    
    opened by andreshj87 4
  • v1.1.0 not available

    v1.1.0 not available

    Gradle fails to resolve version 1.1.0 from jcenter, and apparently the last available version is 1.0.13 https://bintray.com/shuhart/BubblePagerIndicator/bubblepagerindicator

    Am I doing something wrong?

    opened by andreshj87 1
  • App Crashes

    App Crashes

    Observer com.shuhart.bubblepagerindicator.BubblePageIndicator$1@a0ab1a6 was not registered This is the error i get on a recyclerview with viewpager as item , and every viewpager has an indicator.

    opened by valob 1
  • Does I set all the thing in OnCreate?

    Does I set all the thing in OnCreate?

    I am trying setAdapter, setViewPager after API call. But it always crash by NullPointerException. I found out it seems like to set all the thing in OnCreate.

    Should I set the empty adapter at the beginning?

    opened by simonlau0715 1
  • In adapter lost the location

    In adapter lost the location

    if i have a viewpager in a recyclerview, when scroll it the list besides change the position the sime item the item above if is changed the indicator keep in the same position

    opened by alexglobant 1
Releases(v1.2.0)
Owner
Bogdan Kornev
Bogdan Kornev
Onboarding sample project with view pager & shared preferences

Onboarding Sample Project When the application is first downloaded, we go to onboarding from the splash screen. We keep the information that onboardin

Feyza Ürkut 2 Jun 29, 2022
A pager for Android with parallax effect

ParallaxPagerTransformer A pager transformer for Android with parallax effect Installation in your build.gradle file dependencies { // ... com

Javier Gonzalez 654 Dec 29, 2022
This library provides easy ways to add onboarding or pager screens with different animation and indicators.

WalkThroughAndroid Make amazing OnBoarding Screens easily for your app with different colorful animations, fonts, styles, and many more. Customize you

MindInventory 33 Sep 9, 2022
🦚 An expandable layout that shows a two-level layout with an indicator.

ExpandableLayout ?? An expandable layout that shows a two-level layout with an indicator. Including in your project Gradle Add below codes to your roo

Jaewoong Eum 716 Dec 25, 2022
A lightweight indicator like in nexus 5 launcher

CircleIndicator A lightweight indicator like in nexus 5 launcher Gradle AndroidX dependencies { implementation 'me.relex:circleindicator:2.1.6' }

relex 4.1k Dec 30, 2022
💳 Bank Card View is a simple and elegant card view with Flip animation.

Visualização de cartão bancário ?? Bank Card View é uma visualização de cartão simples e elegante com animação Flip. Versões Selecione a língua : Engl

Geovani Amaral 10 Dec 12, 2022
💳 Bank Card View is a simple and elegant card view with Flip animation.

Visualização de cartão bancário ?? Bank Card View é uma visualização de cartão simples e elegante com animação Flip. Versões Selecione a língua : Engl

Geovani Amaral 9 Aug 26, 2022
Cute view animation collection.

Android View Animations One day, I saw an iOS library, which is a view shaker, it's very beautiful. I think Android also need one, and should be bette

代码家 12.2k Jan 1, 2023
Android view with both path from constructed path or from svg.

android-pathview You want to animate svg or normal Paths?<br> Change the color, pathWidth or add svg.<br> Animate the "procentage" property to make th

Georgi Eftimov 2.9k Dec 30, 2022
ViewAnimator view with a lollipop style reveal effect

ViewRevealAnimator Widget ViewAnimator view with a lollipop style reveal effect. Regular animation can be set (just like the default ViewAnimator) for

Alessandro Crugnola 339 Jun 3, 2022
Android view inspired by http://qrohlf.com/trianglify/

Trianglify Android view inspired by http://qrohlf.com/trianglify/ Usage Add the dependency dependencies { compile 'com.manolovn:trianglify:1.1.0'

Manuel Vera 457 Dec 15, 2022
🌠 Transform into a different view or activity using morphing animations.

TransformationLayout ?? Transform into a different view or activity using morphing animations. Using Transformation motions of new material version. D

Jaewoong Eum 2k Jan 3, 2023
An easy, flexible way to add a shimmering effect to any view in an Android app.

Shimmer for Android Shimmer is an Android library that provides an easy way to add a shimmer effect to any view in your Android app. It is useful as a

Facebook 5.1k Dec 26, 2022
💳 A quick and easy flip view through which you can create views with two sides like credit cards, poker cards etc.

The article on how this library was created is now published. You can read it on this link here. →. ?? EasyFlipView Built with ❤︎ by Wajahat Karim and

Wajahat Karim 1.3k Dec 14, 2022
A simple animated step view for Android

StepView A simple animated step view for Android. Backward and forward animations is supported. Usage Add jcenter() to repositories block in your grad

Bogdan Kornev 833 Dec 30, 2022
Automatically manipulates the duration of animations dependent on view count. Quicksand .. the more you struggle.

QuickSand When showing a really enchanting explanatory animation to your users, but you know that after a while it'll get tedious and would stop users

Paul Blundell 385 Sep 9, 2022
Customizable bounce animation for any view like in Clash Royale app

Bounceview-Android Customizable bounce animation for any view updation Getting Started In your build.gradle dependencies { implementation 'hari.bo

Hariprasanth S 149 Nov 18, 2022
Deprecated in favour of https://developer.android.com/reference/android/support/v4/view/animation/PathInterpolatorCompat.html

Deprecated: use https://developer.android.com/reference/android/support/v4/view/animation/PathInterpolatorCompat.html instead. android-cubic-bezier-in

Codesoup 161 Jan 1, 2023
A customised EditText view serving the purpose of taking numeric One Time Password from a user. With stunning animation, and high customizability.

PassCodeText A customised EditText view serving the purpose of taking numeric One Time Password from a user. With stunning animation, and high customi

Swapnil Tiwari 107 Nov 16, 2022