PagerTitleStrippublic class PagerTitleStrip extends android.view.ViewGroup implements ViewPager.DecorPagerTitleStrip 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.
For an interactive indicator, see {@link PagerTabStrip}. |
Fields Summary |
---|
private static final String | TAG | ViewPager | mPager | android.widget.TextView | mPrevText | android.widget.TextView | mCurrText | android.widget.TextView | mNextText | private int | mLastKnownCurrentPage | private float | mLastKnownPositionOffset | private int | mScaledTextSpacing | private int | mGravity | private boolean | mUpdatingText | private boolean | mUpdatingPositions | private final PageListener | mPageListener | private WeakReference | mWatchingAdapter | private static final int[] | ATTRS | private static final int[] | TEXT_ATTRS | private static final float | SIDE_ALPHA | private static final int | TEXT_SPACING | private int | mNonPrimaryAlpha | int | mTextColor | private static final PagerTitleStripImpl | IMPL |
Constructors Summary |
---|
public PagerTitleStrip(android.content.Context context)
this(context, null);
| public PagerTitleStrip(android.content.Context context, android.util.AttributeSet attrs)
super(context, attrs);
addView(mPrevText = new TextView(context));
addView(mCurrText = new TextView(context));
addView(mNextText = new TextView(context));
final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
final int textAppearance = a.getResourceId(0, 0);
if (textAppearance != 0) {
mPrevText.setTextAppearance(context, textAppearance);
mCurrText.setTextAppearance(context, textAppearance);
mNextText.setTextAppearance(context, textAppearance);
}
final int textSize = a.getDimensionPixelSize(1, 0);
if (textSize != 0) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
if (a.hasValue(2)) {
final int textColor = a.getColor(2, 0);
mPrevText.setTextColor(textColor);
mCurrText.setTextColor(textColor);
mNextText.setTextColor(textColor);
}
mGravity = a.getInteger(3, Gravity.BOTTOM);
a.recycle();
mTextColor = mCurrText.getTextColors().getDefaultColor();
setNonPrimaryAlpha(SIDE_ALPHA);
mPrevText.setEllipsize(TruncateAt.END);
mCurrText.setEllipsize(TruncateAt.END);
mNextText.setEllipsize(TruncateAt.END);
boolean allCaps = false;
if (textAppearance != 0) {
final TypedArray ta = context.obtainStyledAttributes(textAppearance, TEXT_ATTRS);
allCaps = ta.getBoolean(0, false);
ta.recycle();
}
if (allCaps) {
setSingleLineAllCaps(mPrevText);
setSingleLineAllCaps(mCurrText);
setSingleLineAllCaps(mNextText);
} else {
mPrevText.setSingleLine();
mCurrText.setSingleLine();
mNextText.setSingleLine();
}
final float density = context.getResources().getDisplayMetrics().density;
mScaledTextSpacing = (int) (TEXT_SPACING * density);
|
Methods Summary |
---|
int | getMinHeight()
int minHeight = 0;
final Drawable bg = getBackground();
if (bg != null) {
minHeight = bg.getIntrinsicHeight();
}
return minHeight;
| public int | getTextSpacing()
return mScaledTextSpacing;
| 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.setInternalPageChangeListener(mPageListener);
pager.setOnAdapterChangeListener(mPageListener);
mPager = pager;
updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter);
| protected void | onDetachedFromWindow()
super.onDetachedFromWindow();
if (mPager != null) {
updateAdapter(mPager.getAdapter(), null);
mPager.setInternalPageChangeListener(null);
mPager.setOnAdapterChangeListener(null);
mPager = null;
}
| 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);
}
| protected void | onMeasure(int widthMeasureSpec, int heightMeasureSpec)
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("Must measure with an exact width");
}
int childHeight = heightSize;
int minHeight = getMinHeight();
int padding = 0;
padding = getPaddingTop() + getPaddingBottom();
childHeight -= padding;
final int childWidthSpec = MeasureSpec.makeMeasureSpec((int) (widthSize * 0.8f),
MeasureSpec.AT_MOST);
final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST);
mPrevText.measure(childWidthSpec, childHeightSpec);
mCurrText.measure(childWidthSpec, childHeightSpec);
mNextText.measure(childWidthSpec, childHeightSpec);
if (heightMode == MeasureSpec.EXACTLY) {
setMeasuredDimension(widthSize, heightSize);
} else {
int textHeight = mCurrText.getMeasuredHeight();
setMeasuredDimension(widthSize, Math.max(minHeight, textHeight + padding));
}
| public void | requestLayout()
if (!mUpdatingText) {
super.requestLayout();
}
| public void | setGravity(int gravity)Set the {@link Gravity} used to position text within the title strip.
Only the vertical gravity component is used.
mGravity = gravity;
requestLayout();
| public void | setNonPrimaryAlpha(float alpha)Set the alpha value used for non-primary page titles.
mNonPrimaryAlpha = (int) (alpha * 255) & 0xFF;
final int transparentColor = (mNonPrimaryAlpha << 24) | (mTextColor & 0xFFFFFF);
mPrevText.setTextColor(transparentColor);
mNextText.setTextColor(transparentColor);
| private static void | setSingleLineAllCaps(android.widget.TextView text)
if (android.os.Build.VERSION.SDK_INT >= 14) {
IMPL = new PagerTitleStripImplIcs();
} else {
IMPL = new PagerTitleStripImplBase();
}
IMPL.setSingleLineAllCaps(text);
| public void | setTextColor(int color)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)}.
mTextColor = color;
mCurrText.setTextColor(color);
final int transparentColor = (mNonPrimaryAlpha << 24) | (mTextColor & 0xFFFFFF);
mPrevText.setTextColor(transparentColor);
mNextText.setTextColor(transparentColor);
| public void | setTextSize(int unit, float size)Set the default text size to a given unit and value.
See {@link TypedValue} for the possible dimension units.
Example: to set the text size to 14px, use
setTextSize(TypedValue.COMPLEX_UNIT_PX, 14);
mPrevText.setTextSize(unit, size);
mCurrText.setTextSize(unit, size);
mNextText.setTextSize(unit, size);
| public void | setTextSpacing(int spacingPixels)Set the required spacing between title segments.
mScaledTextSpacing = spacingPixels;
requestLayout();
| void | updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter)
if (oldAdapter != null) {
oldAdapter.unregisterDataSetObserver(mPageListener);
mWatchingAdapter = null;
}
if (newAdapter != null) {
newAdapter.registerDataSetObserver(mPageListener);
mWatchingAdapter = new WeakReference<PagerAdapter>(newAdapter);
}
if (mPager != null) {
mLastKnownCurrentPage = -1;
mLastKnownPositionOffset = -1;
updateText(mPager.getCurrentItem(), newAdapter);
requestLayout();
}
| void | updateText(int currentItem, PagerAdapter adapter)
final int itemCount = adapter != null ? adapter.getCount() : 0;
mUpdatingText = true;
CharSequence text = null;
if (currentItem >= 1 && adapter != null) {
text = adapter.getPageTitle(currentItem - 1);
}
mPrevText.setText(text);
mCurrText.setText(adapter != null && currentItem < itemCount ?
adapter.getPageTitle(currentItem) : null);
text = null;
if (currentItem + 1 < itemCount && adapter != null) {
text = adapter.getPageTitle(currentItem + 1);
}
mNextText.setText(text);
// Measure everything
final int width = getWidth() - getPaddingLeft() - getPaddingRight();
final int childHeight = getHeight() - getPaddingTop() - getPaddingBottom();
final int childWidthSpec = MeasureSpec.makeMeasureSpec((int) (width * 0.8f),
MeasureSpec.AT_MOST);
final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST);
mPrevText.measure(childWidthSpec, childHeightSpec);
mCurrText.measure(childWidthSpec, childHeightSpec);
mNextText.measure(childWidthSpec, childHeightSpec);
mLastKnownCurrentPage = currentItem;
if (!mUpdatingPositions) {
updateTextPositions(currentItem, mLastKnownPositionOffset, false);
}
mUpdatingText = false;
| void | updateTextPositions(int position, float positionOffset, boolean force)
if (position != mLastKnownCurrentPage) {
updateText(position, mPager.getAdapter());
} else if (!force && positionOffset == mLastKnownPositionOffset) {
return;
}
mUpdatingPositions = true;
final int prevWidth = mPrevText.getMeasuredWidth();
final int currWidth = mCurrText.getMeasuredWidth();
final int nextWidth = mNextText.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 = currCenter - currWidth / 2;
final int currRight = currLeft + currWidth;
final int prevBaseline = mPrevText.getBaseline();
final int currBaseline = mCurrText.getBaseline();
final int nextBaseline = mNextText.getBaseline();
final int maxBaseline = Math.max(Math.max(prevBaseline, currBaseline), nextBaseline);
final int prevTopOffset = maxBaseline - prevBaseline;
final int currTopOffset = maxBaseline - currBaseline;
final int nextTopOffset = maxBaseline - nextBaseline;
final int alignedPrevHeight = prevTopOffset + mPrevText.getMeasuredHeight();
final int alignedCurrHeight = currTopOffset + mCurrText.getMeasuredHeight();
final int alignedNextHeight = nextTopOffset + mNextText.getMeasuredHeight();
final int maxTextHeight = Math.max(Math.max(alignedPrevHeight, alignedCurrHeight),
alignedNextHeight);
final int vgrav = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
int prevTop;
int currTop;
int nextTop;
switch (vgrav) {
default:
case Gravity.TOP:
prevTop = paddingTop + prevTopOffset;
currTop = paddingTop + currTopOffset;
nextTop = paddingTop + nextTopOffset;
break;
case Gravity.CENTER_VERTICAL:
final int paddedHeight = stripHeight - paddingTop - paddingBottom;
final int centeredTop = (paddedHeight - maxTextHeight) / 2;
prevTop = centeredTop + prevTopOffset;
currTop = centeredTop + currTopOffset;
nextTop = centeredTop + nextTopOffset;
break;
case Gravity.BOTTOM:
final int bottomGravTop = stripHeight - paddingBottom - maxTextHeight;
prevTop = bottomGravTop + prevTopOffset;
currTop = bottomGravTop + currTopOffset;
nextTop = bottomGravTop + nextTopOffset;
break;
}
mCurrText.layout(currLeft, currTop, currRight,
currTop + mCurrText.getMeasuredHeight());
final int prevLeft = Math.min(paddingLeft, currLeft - mScaledTextSpacing - prevWidth);
mPrevText.layout(prevLeft, prevTop, prevLeft + prevWidth,
prevTop + mPrevText.getMeasuredHeight());
final int nextLeft = Math.max(stripWidth - paddingRight - nextWidth,
currRight + mScaledTextSpacing);
mNextText.layout(nextLeft, nextTop, nextLeft + nextWidth,
nextTop + mNextText.getMeasuredHeight());
mLastKnownPositionOffset = positionOffset;
mUpdatingPositions = false;
|
|