Skip to content

Instantly share code, notes, and snippets.

@Pulimet
Created September 11, 2017 06:18
Show Gist options
  • Save Pulimet/ab49e634169b58c5715f821917f37abb to your computer and use it in GitHub Desktop.
Save Pulimet/ab49e634169b58c5715f821917f37abb to your computer and use it in GitHub Desktop.
Custom tab strip for ViewPager (titles + current indicator)
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.gaiamobile.ynet.pplus.ui.customviews.CustomTabStrip
android:id="@+id/customTabStrip"
android:layout_width="match_parent"
android:layout_height="40dp"/>
</android.support.v4.view.ViewPager>
/**
* PagerTitleStrip is a non-interactive indicator of the current, next,
* and previous pages of a {@link ViewPager}. It is intended to be used as a
* child view of a ViewPager widget in your XML layout.
* Add it as a child of a ViewPager in your layout file and set its
* android:layout_gravity to TOP or BOTTOM to pin it to the top or bottom
* of the ViewPager. The title from each page is supplied by the method
* {@link PagerAdapter#getPageTitle(int)} in the adapter supplied to
* the ViewPager.
*/
@ViewPager.DecorView
public class CustomTabStrip extends ViewGroup {
private ViewPager mPager;
private final TextView[] mTextViews = new TextView[5];
private static final int PREV_PREV = 0;
private static final int PREV = 1;
private static final int CURR = 2;
private static final int NEXT = 3;
private static final int NEXT_NEXT = 4;
private int mLastKnownCurrentPage = -1;
private float mLastKnownPositionOffset = -1;
private int mScaledTextSpacing;
private int mGravity;
private boolean mUpdatingText;
private boolean mUpdatingPositions;
private final PageListener mPageListener = new PageListener();
private WeakReference<PagerAdapter> mWatchingAdapter;
private static final int[] ATTRS = new int[]{
android.R.attr.textAppearance,
android.R.attr.textSize,
android.R.attr.textColor,
android.R.attr.gravity
};
private static final float SIDE_ALPHA = 0.6f;
// Space between titles
private static final int TEXT_SPACING = 16; // dp
private int mNonPrimaryAlpha;
private int mTextColor;
// -----------------------------------
private static final int INDICATOR_HEIGHT = 6; // dp
private static final int MIN_PADDING_BOTTOM = INDICATOR_HEIGHT + 3; // dp
private static final int TAB_PADDING = 2; // dp
private static final int TAB_SPACING = 2; // dp
private static final int MIN_TEXT_SPACING = TAB_SPACING + TAB_PADDING * 2; // dp
private static final int MIN_STRIP_HEIGHT = 32; // dp
private int mIndicatorColor;
private int mIndicatorHeight;
private int mMinPaddingBottom;
private int mMinTextSpacing;
private int mMinStripHeight;
private int mTabPadding;
private final Paint mTabPaint = new Paint();
private int mTabAlpha = 0xFF;
private boolean mIgnoreTap;
private float mInitialMotionX;
private float mInitialMotionY;
private int mTouchSlop;
private final Path mPath = new Path();
private boolean mIndicatorVisible = true;
public CustomTabStrip(Context context) {
this(context, null);
}
public CustomTabStrip(Context context, AttributeSet attrs) {
super(context, attrs);
final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
final int textAppearance = a.getResourceId(0, 0);
final int textSize = a.getDimensionPixelSize(1, 0);
final int textColor = a.getColor(2, 0);
mGravity = a.getInteger(3, Gravity.BOTTOM);
a.recycle();
// TextViews creation + set tags
createTitles(context, textAppearance, textSize, textColor);
// Text and indicator color
mTextColor = mTextViews[CURR].getTextColors().getDefaultColor();
mIndicatorColor = mTextColor;
// ???
setNonPrimaryAlpha(SIDE_ALPHA);
final float density = context.getResources().getDisplayMetrics().density;
// Set space between titles
mScaledTextSpacing = (int) (TEXT_SPACING * density);
// ----------------INDICATORS-------------------
if (mIndicatorVisible) {
setIndicatorParams(context, density);
}
}
private void createTitles(Context context, int textAppearance, int textSize, int textColor) {
for (int i = 0; i < mTextViews.length; i++) {
addView(mTextViews[i] = new TextView(context));
mTextViews[i].setTag(i);
}
for (TextView textView : mTextViews) {
// Set textAppearance
if (textAppearance != 0) {
TextViewCompat.setTextAppearance(textView, textAppearance);
}
// Set textSize
if (textSize != 0) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
// Set textColor
if (textColor != 0) {
textView.setTextColor(textColor);
}
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setSingleLine();
// Set focusable true and click listener
textView.setFocusable(true);
ClickListener clickListener = new ClickListener();
textView.setOnClickListener(clickListener);
}
}
private void setIndicatorParams(Context context, float density) {
mTabPaint.setColor(mIndicatorColor);
// Note: this follows the rules for Resources#getDimensionPixelOffset/Size: sizes round up, offsets round down.
mIndicatorHeight = (int) (INDICATOR_HEIGHT * density + 0.5f);
mMinPaddingBottom = (int) (MIN_PADDING_BOTTOM * density + 0.5f);
mMinTextSpacing = (int) (MIN_TEXT_SPACING * density);
mTabPadding = (int) (TAB_PADDING * density + 0.5f);
mMinStripHeight = (int) (MIN_STRIP_HEIGHT * density + 0.5f);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
// Enforce restrictions
setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom());
setTextSpacing(getTextSpacing());
setWillNotDraw(false);
}
//--------- INDICATOR START ------
/**
* Set the color of the tab indicator bar.
*
* @param color Color to set as an 0xRRGGBB value. The high byte (alpha) is ignored.
*/
@SuppressWarnings("unused")
public void setTabIndicatorColor(@ColorInt int color) {
mIndicatorColor = color;
mTabPaint.setColor(mIndicatorColor);
invalidate();
}
@Override
public void setPadding(int left, int top, int right, int bottom) {
if (bottom < mMinPaddingBottom) {
bottom = mMinPaddingBottom;
}
super.setPadding(left, top, right, bottom);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
if (action != MotionEvent.ACTION_DOWN && mIgnoreTap) {
return false;
}
// Any tap within touch slop to either side of the current item
// will scroll to prev/next.
final float x = ev.getX();
final float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mInitialMotionX = x;
mInitialMotionY = y;
mIgnoreTap = false;
break;
case MotionEvent.ACTION_MOVE:
if (Math.abs(x - mInitialMotionX) > mTouchSlop
|| Math.abs(y - mInitialMotionY) > mTouchSlop) {
mIgnoreTap = true;
}
break;
case MotionEvent.ACTION_UP:
if (x < mTextViews[CURR].getLeft() - mTabPadding) {
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
} else if (x > mTextViews[CURR].getRight() + mTabPadding) {
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
}
break;
}
return true;
}
public void setIndicatorVisible(boolean indicatorVisible) {
mIndicatorVisible = indicatorVisible;
mIndicatorHeight = 0;
mMinPaddingBottom = 0;
mIndicatorHeight = 0;
invalidate();
}
@SuppressWarnings({"UnnecessaryLocalVariable", "NumericOverflow"})
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!mIndicatorVisible) {
return;
}
final int height = getHeight();
final int width = getHeight() / 3;
final int bottom = height;
final int top = bottom - mIndicatorHeight;
final int left = mTextViews[CURR].getLeft() - mTabPadding;
final int right = mTextViews[CURR].getRight() + mTabPadding;
final int middle = left + ((right - left) / 2);
final int tLeft = middle - width / 2;
final int tRight = middle + width / 2;
mTabPaint.setColor(mTabAlpha << 24 | (mIndicatorColor & 0xEEEEEE));
//canvas.drawRect(left, top, right, bottom, mTabPaint);
mPath.reset();
mPath.moveTo(tLeft, bottom);
mPath.lineTo(middle, top);
mPath.lineTo(tRight, bottom);
mPath.close();
canvas.drawPath(mPath, mTabPaint);
}
//----------------
/**
* Set the required spacing between title segments.
*
* @param spacingPixels Spacing between each title displayed in pixels
*/
private void setTextSpacing(int spacingPixels) {
if (spacingPixels < mMinTextSpacing) {
spacingPixels = mMinTextSpacing;
}
mScaledTextSpacing = spacingPixels;
requestLayout();
}
/**
* @return The required spacing between title segments in pixels
*/
private int getTextSpacing() {
return mScaledTextSpacing;
}
/**
* Set the alpha value used for non-primary page titles.
*
* @param alpha Opacity value in the range 0-1f
*/
private void setNonPrimaryAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha) {
mNonPrimaryAlpha = (int) (alpha * 255) & 0xFF;
final int transparentColor = (mNonPrimaryAlpha << 24) | (mTextColor & 0xFFFFFF);
for (TextView textView : mTextViews) {
if (isTextViewCurrent(textView)) {
continue;
}
textView.setTextColor(transparentColor);
}
}
private boolean isTextViewCurrent(TextView textView) {
return (int) textView.getTag() == CURR;
}
/**
* Set the color value used as the base color for all displayed page titles.
* Alpha will be ignored for non-primary page titles. See {@link #setNonPrimaryAlpha(float)}.
*
* @param color Color hex code in 0xAARRGGBB format
*/
public void setTextColor(@ColorInt int color) {
mTextColor = color;
final int transparentColor = (mNonPrimaryAlpha << 24) | (mTextColor & 0xFFFFFF);
for (TextView textView : mTextViews) {
if (isTextViewCurrent(textView)) {
textView.setTextColor(color);
} else {
textView.setTextColor(transparentColor);
}
}
}
public void setTextColors(@ColorInt int selectedColor, @ColorInt int otherColor) {
mTextColor = otherColor;
for (TextView textView : mTextViews) {
if (isTextViewCurrent(textView)) {
textView.setTextColor(selectedColor);
} else {
textView.setTextColor(otherColor);
}
}
}
/**
* Set the default text size to a given unit and value.
* See {@link TypedValue} for the possible dimension units.
* <p>
* <p>Example: to set the text size to 14px, use
* setTextSize(TypedValue.COMPLEX_UNIT_PX, 14);</p>
*
* @param unit The desired dimension unit
* @param size The desired size in the given units
*/
public void setTextSize(int unit, float size) {
for (TextView textView : mTextViews) {
textView.setTextSize(unit, size);
}
}
public void setSelectedTitleBold(boolean isBold) {
mTextViews[CURR].setTypeface(null, isBold ? Typeface.BOLD : Typeface.NORMAL);
}
public void setAllTitleBold(boolean isBold) {
for (TextView textView : mTextViews) {
textView.setTypeface(null, isBold ? Typeface.BOLD : Typeface.NORMAL);
}
}
/**
* Set the {@link Gravity} used to position text within the title strip.
* Only the vertical gravity component is used.
*
* @param gravity {@link Gravity} constant for positioning title text
*/
public void setGravity(int gravity) {
mGravity = gravity;
requestLayout();
}
@SuppressWarnings("deprecation")
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
final ViewParent parent = getParent();
if (!(parent instanceof ViewPager)) {
throw new IllegalStateException(
"PagerTitleStrip must be a direct child of a ViewPager.");
}
final ViewPager pager = (ViewPager) parent;
final PagerAdapter adapter = pager.getAdapter();
pager.setOnPageChangeListener(mPageListener);
pager.addOnAdapterChangeListener(mPageListener);
mPager = pager;
updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter);
}
@SuppressWarnings("deprecation")
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mPager != null) {
updateAdapter(mPager.getAdapter(), null);
mPager.setOnPageChangeListener(null);
mPager.removeOnAdapterChangeListener(mPageListener);
mPager = null;
}
}
private void updateText(int currentItem, PagerAdapter adapter) {
final int itemCount = adapter != null ? adapter.getCount() : 0;
mUpdatingText = true;
CharSequence text = null;
if (currentItem >= 2 && adapter != null) {
text = adapter.getPageTitle(currentItem - 2);
}
mTextViews[0].setText(text);
if (currentItem >= 1 && adapter != null) {
text = adapter.getPageTitle(currentItem - 1);
}
mTextViews[1].setText(text);
mTextViews[2].setText(adapter != null && currentItem < itemCount
? adapter.getPageTitle(currentItem) : null);
text = null;
if (currentItem + 1 < itemCount && adapter != null) {
text = adapter.getPageTitle(currentItem + 1);
}
mTextViews[3].setText(text);
if (currentItem + 2 < itemCount && adapter != null) {
text = adapter.getPageTitle(currentItem + 2);
}
mTextViews[4].setText(text);
// Measure everything
final int width = getWidth() - getPaddingLeft() - getPaddingRight();
final int maxWidth = Math.max(0, (int) (width * 0.8f));
final int childWidthSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST);
final int childHeight = getHeight() - getPaddingTop() - getPaddingBottom();
final int maxHeight = Math.max(0, childHeight);
final int childHeightSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
for (TextView textView : mTextViews) {
textView.measure(childWidthSpec, childHeightSpec);
}
mLastKnownCurrentPage = currentItem;
if (!mUpdatingPositions) {
updateTextPositions(currentItem, mLastKnownPositionOffset, false);
}
mUpdatingText = false;
}
@Override
public void requestLayout() {
if (!mUpdatingText) {
super.requestLayout();
}
}
private void updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter) {
if (oldAdapter != null) {
oldAdapter.unregisterDataSetObserver(mPageListener);
mWatchingAdapter = null;
}
if (newAdapter != null) {
newAdapter.registerDataSetObserver(mPageListener);
mWatchingAdapter = new WeakReference<>(newAdapter);
}
if (mPager != null) {
mLastKnownCurrentPage = -1;
mLastKnownPositionOffset = -1;
updateText(mPager.getCurrentItem(), newAdapter);
requestLayout();
}
}
private void updateTextPositions(int position, float positionOffset, boolean force) {
if (position != mLastKnownCurrentPage) {
updateText(position, mPager.getAdapter());
} else if (!force && positionOffset == mLastKnownPositionOffset) {
return;
}
//MyLog.d("Position: " + position + " positionOffset: " + positionOffset);
mUpdatingPositions = true;
final int prevPrevWidth = mTextViews[PREV_PREV].getMeasuredWidth();
final int prevWidth = mTextViews[PREV].getMeasuredWidth();
final int currWidth = mTextViews[CURR].getMeasuredWidth();
final int nextWidth = mTextViews[NEXT].getMeasuredWidth();
final int nextNextWidth = mTextViews[NEXT_NEXT].getMeasuredWidth();
final int halfCurrWidth = currWidth / 2;
final int stripWidth = getWidth();
final int stripHeight = getHeight();
final int paddingLeft = getPaddingLeft();
final int paddingRight = getPaddingRight();
final int paddingTop = getPaddingTop();
final int paddingBottom = getPaddingBottom();
final int textPaddedLeft = paddingLeft + halfCurrWidth;
final int textPaddedRight = paddingRight + halfCurrWidth;
final int contentWidth = stripWidth - textPaddedLeft - textPaddedRight;
float currOffset = positionOffset + 0.5f;
if (currOffset > 1.f) {
currOffset -= 1.f;
}
final int currCenter = stripWidth - textPaddedRight - (int) (contentWidth * currOffset);
final int currLeft = Math.min(
Math.max(currCenter - currWidth / 2, prevWidth + mScaledTextSpacing), stripWidth - nextWidth - currWidth - mScaledTextSpacing);
final int currRight = currLeft + currWidth;
final int prevPrevBaseline = mTextViews[PREV_PREV].getBaseline();
final int prevBaseline = mTextViews[PREV].getBaseline();
final int currBaseline = mTextViews[CURR].getBaseline();
final int nextBaseline = mTextViews[NEXT].getBaseline();
final int nextNextBaseline = mTextViews[NEXT_NEXT].getBaseline();
//final int maxBaseline = Math.max(Math.max(prevBaseline, currBaseline), nextBaseline);
final int maxBaseline = Math.max(currBaseline,
Math.max(Math.max(prevPrevBaseline, prevBaseline), Math.max(nextBaseline, nextNextBaseline)));
final int prevPrevTopOffset = maxBaseline - prevPrevBaseline;
final int prevTopOffset = maxBaseline - prevBaseline;
final int currTopOffset = maxBaseline - currBaseline;
final int nextTopOffset = maxBaseline - nextBaseline;
final int nextNextTopOffset = maxBaseline - nextNextBaseline;
final int alignedPrevPrevHeight = prevPrevTopOffset + mTextViews[PREV_PREV].getMeasuredHeight();
final int alignedPrevHeight = prevTopOffset + mTextViews[PREV].getMeasuredHeight();
final int alignedCurrHeight = currTopOffset + mTextViews[CURR].getMeasuredHeight();
final int alignedNextHeight = nextTopOffset + mTextViews[NEXT].getMeasuredHeight();
final int alignedNextNextHeight = nextNextTopOffset + mTextViews[NEXT_NEXT].getMeasuredHeight();
//final int maxTextHeight = Math.max(Math.max(alignedPrevHeight, alignedCurrHeight), alignedNextHeight);
final int maxTextHeight = Math.max(alignedCurrHeight,
Math.max(Math.max(alignedPrevPrevHeight, alignedPrevHeight), Math.max(alignedNextHeight, alignedNextNextHeight)));
final int vGrav = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
int prevPrevTop;
int prevTop;
int currTop;
int nextTop;
int nextNextTop;
switch (vGrav) {
default:
case Gravity.TOP:
prevPrevTop = paddingTop + prevPrevTopOffset;
prevTop = paddingTop + prevTopOffset;
currTop = paddingTop + currTopOffset;
nextTop = paddingTop + nextTopOffset;
nextNextTop = paddingTop + nextNextTopOffset;
break;
case Gravity.CENTER_VERTICAL:
final int paddedHeight = stripHeight - paddingTop - paddingBottom;
final int centeredTop = (paddedHeight - maxTextHeight) / 2;
prevPrevTop = centeredTop + prevPrevTopOffset;
prevTop = centeredTop + prevTopOffset;
currTop = centeredTop + currTopOffset;
nextTop = centeredTop + nextTopOffset;
nextNextTop = centeredTop + nextNextTopOffset;
break;
case Gravity.BOTTOM:
final int bottomGravTop = stripHeight - paddingBottom - maxTextHeight;
prevPrevTop = bottomGravTop + prevPrevTopOffset;
prevTop = bottomGravTop + prevTopOffset;
currTop = bottomGravTop + currTopOffset;
nextTop = bottomGravTop + nextTopOffset;
nextNextTop = bottomGravTop + nextNextTopOffset;
break;
}
mTextViews[CURR].layout(currLeft, currTop, currRight, currTop + mTextViews[CURR].getMeasuredHeight());
//final int prevLeft = Math.min(paddingLeft, currLeft - mScaledTextSpacing - prevWidth);
final int prevLeft = Math.min(paddingLeft + prevPrevWidth + mScaledTextSpacing, currLeft - mScaledTextSpacing - prevWidth);
mTextViews[PREV].layout(prevLeft, prevTop, prevLeft + prevWidth, prevTop + mTextViews[PREV].getMeasuredHeight());
final int prevPrevLeft = Math.min(paddingLeft, prevLeft - mScaledTextSpacing - prevPrevWidth);
mTextViews[PREV_PREV].layout(prevPrevLeft, prevPrevTop, prevPrevLeft + prevPrevWidth,
prevPrevTop + mTextViews[PREV_PREV].getMeasuredHeight());
//final int nextLeft = Math.max(stripWidth - paddingRight - nextWidth, currRight + mScaledTextSpacing);
final int nextLeft = Math.max(stripWidth - paddingRight - nextNextWidth - mScaledTextSpacing - nextWidth, currRight + mScaledTextSpacing);
mTextViews[NEXT].layout(nextLeft, nextTop, nextLeft + nextWidth, nextTop + mTextViews[NEXT].getMeasuredHeight());
final int nextNextLeft = Math.max(stripWidth - paddingRight - nextNextWidth, nextLeft + nextWidth + mScaledTextSpacing);
mTextViews[NEXT_NEXT].layout(nextNextLeft, nextNextTop, nextNextLeft + nextNextWidth,
nextNextTop + mTextViews[NEXT_NEXT].getMeasuredHeight());
mLastKnownPositionOffset = positionOffset;
mUpdatingPositions = false;
//---- Indicator
mTabAlpha = (int) (Math.abs(positionOffset - 0.5f) * 2 * 0xFF);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("Must measure with an exact width");
}
final int heightPadding = getPaddingTop() + getPaddingBottom();
final int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, heightPadding, LayoutParams.WRAP_CONTENT);
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int widthPadding = (int) (widthSize * 0.2f);
final int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, widthPadding, LayoutParams.WRAP_CONTENT);
for (TextView textView : mTextViews) {
textView.measure(childWidthSpec, childHeightSpec);
}
final int height;
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
height = MeasureSpec.getSize(heightMeasureSpec);
} else {
final int textHeight = mTextViews[CURR].getMeasuredHeight();
final int minHeight = getMinHeight();
height = Math.max(minHeight, textHeight + heightPadding);
}
final int childState = mTextViews[CURR].getMeasuredState();
final int measuredHeight = View.resolveSizeAndState(height, heightMeasureSpec,
childState << View.MEASURED_HEIGHT_STATE_SHIFT);
setMeasuredDimension(widthSize, measuredHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mPager != null) {
final float offset = mLastKnownPositionOffset >= 0 ? mLastKnownPositionOffset : 0;
updateTextPositions(mLastKnownCurrentPage, offset, true);
}
}
private int getMinHeight() {
int minHeight = 0;
final Drawable bg = getBackground();
if (bg != null) {
minHeight = bg.getIntrinsicHeight();
}
return Math.max(minHeight, mMinStripHeight);
}
private class ClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
switch ((int) view.getTag()) {
case PREV_PREV:
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
break;
case PREV:
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
break;
case NEXT:
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
break;
case NEXT_NEXT:
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
break;
}
}
}
private class PageListener extends DataSetObserver implements ViewPager.OnPageChangeListener,
ViewPager.OnAdapterChangeListener {
private int mScrollState;
PageListener() {
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (positionOffset > 0.5f) {
// Consider ourselves to be on the next page when we're 50% of the way there.
position++;
}
updateTextPositions(position, positionOffset, false);
}
@Override
public void onPageSelected(int position) {
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
// Only update the text here if we're not dragging or settling.
updateText(mPager.getCurrentItem(), mPager.getAdapter());
final float offset = mLastKnownPositionOffset >= 0 ? mLastKnownPositionOffset : 0;
updateTextPositions(mPager.getCurrentItem(), offset, true);
}
}
@Override
public void onPageScrollStateChanged(int state) {
mScrollState = state;
}
@Override
public void onAdapterChanged(@NonNull ViewPager viewPager, PagerAdapter oldAdapter,
PagerAdapter newAdapter) {
updateAdapter(oldAdapter, newAdapter);
}
@Override
public void onChanged() {
updateText(mPager.getCurrentItem(), mPager.getAdapter());
final float offset = mLastKnownPositionOffset >= 0 ? mLastKnownPositionOffset : 0;
updateTextPositions(mPager.getCurrentItem(), offset, true);
}
}
}
CustomTabStrip customTabStrip = findViewById(R.id.customTabStrip);
customTabStrip.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
customTabStrip.setBackgroundColor(getResources().getColor(R.color.pagerTabStripColor));
customTabStrip.setTabIndicatorColor(Color.WHITE);
customTabStrip.setTextColor(Color.WHITE);
customTabStrip.setSelectedTitleBold(true);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment