Skip to content

Instantly share code, notes, and snippets.

@vic797
Last active October 21, 2020 19:34
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save vic797/b44305f587a7d9bf8ef094a5b60735a0 to your computer and use it in GitHub Desktop.
Simple line indicator for ViewPager
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
public class LinePagerIndicator extends View implements ViewPager.OnPageChangeListener, ViewPager.OnAdapterChangeListener {
private int barWidth;
private ViewPager pager;
private Paint paint;
private IndicatorObserver observer;
private int left;
public LinePagerIndicator(Context context) {
super(context);
init();
}
public LinePagerIndicator(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public LinePagerIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setViewPager(ViewPager pager) {
if (this.pager != null && this.pager.getAdapter() != null) {
this.pager.getAdapter().unregisterDataSetObserver(observer);
this.pager.removeOnAdapterChangeListener(this);
this.pager.removeOnPageChangeListener(this);
}
this.pager = pager;
updatePagerInfo(true);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
Rect rect = new Rect();
rect.left = left;
rect.top = 0;
rect.bottom = getMeasuredHeight();
rect.right = left + barWidth;
canvas.drawRect(rect, paint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = getSuggestedMinimumWidth() + getPaddingLeft() + getPaddingRight();
int desiredHeight = getSuggestedMinimumHeight() + getPaddingTop() + getPaddingBottom();
setMeasuredDimension(measureDimension(desiredWidth, widthMeasureSpec), measureDimension(desiredHeight, heightMeasureSpec));
updatePagerInfo(false);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
left = Math.round(barWidth * positionOffset) + (barWidth * position);
invalidate();
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onAdapterChanged(@NonNull ViewPager viewPager, @Nullable PagerAdapter oldAdapter, @Nullable PagerAdapter newAdapter) {
updatePagerInfo(false);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
updatePagerInfo(false);
}
private void init() {
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
this.observer = new IndicatorObserver();
left = 0;
}
private void updatePagerInfo(boolean addListeners) {
if (pager != null && pager.getAdapter() != null) {
if (addListeners) {
pager.getAdapter().registerDataSetObserver(observer);
pager.addOnAdapterChangeListener(this);
pager.addOnPageChangeListener(this);
}
int itemCount = pager.getAdapter().getCount() == 0 ? 1 : pager.getAdapter().getCount();
barWidth = getMeasuredWidth() / itemCount;
} else {
barWidth = getMeasuredWidth();
}
invalidate();
}
private int measureDimension(int desiredSize, int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = desiredSize;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
private class IndicatorObserver extends DataSetObserver {
@Override
public void onChanged() {
updatePagerInfo(false);
}
@Override
public void onInvalidated() {
updatePagerInfo(false);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment