18fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell/* 28fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Copyright (C) 2011 The Android Open Source Project 38fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * 48fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 58fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * you may not use this file except in compliance with the License. 68fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * You may obtain a copy of the License at 78fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * 88fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * http://www.apache.org/licenses/LICENSE-2.0 98fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * 108fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Unless required by applicable law or agreed to in writing, software 118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * distributed under the License is distributed on an "AS IS" BASIS, 128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * See the License for the specific language governing permissions and 148fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * limitations under the License. 158fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 168fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 178fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellpackage android.support.v4.view; 188fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 198fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.content.Context; 208fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.content.res.TypedArray; 218fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.database.DataSetObserver; 228fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.graphics.drawable.Drawable; 238fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.text.TextUtils.TruncateAt; 248fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.util.AttributeSet; 258fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.util.TypedValue; 2623b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powellimport android.view.Gravity; 278fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.view.ViewGroup; 288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.view.ViewParent; 298fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powellimport android.widget.TextView; 308fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 315d6251c65f890a57aa9929eb6aacae2d8b917ec9Adam Powellimport java.lang.ref.WeakReference; 325d6251c65f890a57aa9929eb6aacae2d8b917ec9Adam Powell 338fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell/** 348fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * PagerTitleStrip is a non-interactive indicator of the current, next, 350574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * and previous pages of a {@link ViewPager}. It is intended to be used as a 368fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * child view of a ViewPager widget in your XML layout. 378fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * Add it as a child of a ViewPager in your layout file and set its 388fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * android:layout_gravity to TOP or BOTTOM to pin it to the top or bottom 398fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * of the ViewPager. The title from each page is supplied by the method 408fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * {@link PagerAdapter#getPageTitle(int)} in the adapter supplied to 418fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell * the ViewPager. 4224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * 4324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * <p>For an interactive indicator, see {@link PagerTabStrip}.</p> 448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell */ 451ccb8bcb79557d861de7f271c13e2fd8e54e012aAdam Powellpublic class PagerTitleStrip extends ViewGroup implements ViewPager.Decor { 468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private static final String TAG = "PagerTitleStrip"; 478fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell ViewPager mPager; 4924cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell TextView mPrevText; 5024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell TextView mCurrText; 5124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell TextView mNextText; 528fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 538fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private int mLastKnownCurrentPage = -1; 548fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private float mLastKnownPositionOffset = -1; 558fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private int mScaledTextSpacing; 5623b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell private int mGravity; 578fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 588fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private boolean mUpdatingText; 598fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private boolean mUpdatingPositions; 608fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 618fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private final PageListener mPageListener = new PageListener(); 628fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 635d6251c65f890a57aa9929eb6aacae2d8b917ec9Adam Powell private WeakReference<PagerAdapter> mWatchingAdapter; 645d6251c65f890a57aa9929eb6aacae2d8b917ec9Adam Powell 658fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private static final int[] ATTRS = new int[] { 668fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell android.R.attr.textAppearance, 67552468d2a1e3cbf74f3a6dcbb68fe079aed56cf9Adam Powell android.R.attr.textSize, 688fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell android.R.attr.textColor, 6923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell android.R.attr.gravity 708fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell }; 718fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 721e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell private static final int[] TEXT_ATTRS = new int[] { 731e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 0x0101038c // android.R.attr.textAllCaps 741e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell }; 751e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 76552468d2a1e3cbf74f3a6dcbb68fe079aed56cf9Adam Powell private static final float SIDE_ALPHA = 0.6f; 778fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private static final int TEXT_SPACING = 16; // dip 788fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 79552468d2a1e3cbf74f3a6dcbb68fe079aed56cf9Adam Powell private int mNonPrimaryAlpha; 8024cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell int mTextColor; 81a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 821e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell interface PagerTitleStripImpl { 831e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell void setSingleLineAllCaps(TextView text); 841e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 851e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 861e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell static class PagerTitleStripImplBase implements PagerTitleStripImpl { 871e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell public void setSingleLineAllCaps(TextView text) { 881e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell text.setSingleLine(); 891e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 901e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 911e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 921e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell static class PagerTitleStripImplIcs implements PagerTitleStripImpl { 931e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell public void setSingleLineAllCaps(TextView text) { 941e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell PagerTitleStripIcs.setSingleLineAllCaps(text); 951e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 961e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 971e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 981e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell private static final PagerTitleStripImpl IMPL; 991e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell static { 1001e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell if (android.os.Build.VERSION.SDK_INT >= 14) { 1011e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell IMPL = new PagerTitleStripImplIcs(); 1021e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } else { 1031e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell IMPL = new PagerTitleStripImplBase(); 1041e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 1051e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 1061e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 1071e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell private static void setSingleLineAllCaps(TextView text) { 1081e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell IMPL.setSingleLineAllCaps(text); 1091e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 1101e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 1118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public PagerTitleStrip(Context context) { 1128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell this(context, null); 1138fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 1148fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 1158fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public PagerTitleStrip(Context context, AttributeSet attrs) { 1168fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell super(context, attrs); 1178fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 1188fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell addView(mPrevText = new TextView(context)); 1198fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell addView(mCurrText = new TextView(context)); 1208fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell addView(mNextText = new TextView(context)); 1218fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 1228fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS); 1238fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int textAppearance = a.getResourceId(0, 0); 1248fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (textAppearance != 0) { 1258fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mPrevText.setTextAppearance(context, textAppearance); 1268fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mCurrText.setTextAppearance(context, textAppearance); 1278fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mNextText.setTextAppearance(context, textAppearance); 1288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 12923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int textSize = a.getDimensionPixelSize(1, 0); 13023b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell if (textSize != 0) { 13123b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); 13223b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell } 13323b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell if (a.hasValue(2)) { 134552468d2a1e3cbf74f3a6dcbb68fe079aed56cf9Adam Powell final int textColor = a.getColor(2, 0); 1358fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mPrevText.setTextColor(textColor); 1368fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mCurrText.setTextColor(textColor); 1378fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mNextText.setTextColor(textColor); 1388fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 13923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell mGravity = a.getInteger(3, Gravity.BOTTOM); 1408fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell a.recycle(); 1418fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 142a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mTextColor = mCurrText.getTextColors().getDefaultColor(); 143a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell setNonPrimaryAlpha(SIDE_ALPHA); 1448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 1458fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mPrevText.setEllipsize(TruncateAt.END); 1468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mCurrText.setEllipsize(TruncateAt.END); 1478fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mNextText.setEllipsize(TruncateAt.END); 1481e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 1491e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell boolean allCaps = false; 1501e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell if (textAppearance != 0) { 1511e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell final TypedArray ta = context.obtainStyledAttributes(textAppearance, TEXT_ATTRS); 1521e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell allCaps = ta.getBoolean(0, false); 1531e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell ta.recycle(); 1541e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 1551e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 1561e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell if (allCaps) { 1571e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell setSingleLineAllCaps(mPrevText); 1581e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell setSingleLineAllCaps(mCurrText); 1591e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell setSingleLineAllCaps(mNextText); 1601e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } else { 1611e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell mPrevText.setSingleLine(); 1621e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell mCurrText.setSingleLine(); 1631e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell mNextText.setSingleLine(); 1641e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 1658fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 1668fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final float density = context.getResources().getDisplayMetrics().density; 1678fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mScaledTextSpacing = (int) (TEXT_SPACING * density); 1688fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 1698fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 170a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell /** 171a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * Set the required spacing between title segments. 172a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * 173a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * @param spacingPixels Spacing between each title displayed in pixels 174a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell */ 175a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell public void setTextSpacing(int spacingPixels) { 176a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mScaledTextSpacing = spacingPixels; 177a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell requestLayout(); 178a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 179a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 180a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell /** 18124cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell * @return The required spacing between title segments in pixels 18224cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell */ 18324cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell public int getTextSpacing() { 18424cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell return mScaledTextSpacing; 18524cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell } 18624cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell 18724cc55cb5775a71ff144a3588003fa8e52951c7dAdam Powell /** 188a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * Set the alpha value used for non-primary page titles. 189a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * 190a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * @param alpha Opacity value in the range 0-1f 191a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell */ 192a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell public void setNonPrimaryAlpha(float alpha) { 193a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mNonPrimaryAlpha = (int) (alpha * 255) & 0xFF; 194a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int transparentColor = (mNonPrimaryAlpha << 24) | (mTextColor & 0xFFFFFF); 195a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mPrevText.setTextColor(transparentColor); 196a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mNextText.setTextColor(transparentColor); 197a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 198a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 199a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell /** 200a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * Set the color value used as the base color for all displayed page titles. 201a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * Alpha will be ignored for non-primary page titles. See {@link #setNonPrimaryAlpha(float)}. 202a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * 203a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * @param color Color hex code in 0xAARRGGBB format 204a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell */ 205a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell public void setTextColor(int color) { 206a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mTextColor = color; 207a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mCurrText.setTextColor(color); 208a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell final int transparentColor = (mNonPrimaryAlpha << 24) | (mTextColor & 0xFFFFFF); 209a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mPrevText.setTextColor(transparentColor); 210a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mNextText.setTextColor(transparentColor); 211a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 212a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 213a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell /** 214a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * Set the default text size to a given unit and value. 215a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * See {@link TypedValue} for the possible dimension units. 216a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * 217a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * <p>Example: to set the text size to 14px, use 218a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * setTextSize(TypedValue.COMPLEX_UNIT_PX, 14);</p> 219a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * 220a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * @param unit The desired dimension unit 221a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell * @param size The desired size in the given units 222a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell */ 223a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell public void setTextSize(int unit, float size) { 224a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mPrevText.setTextSize(unit, size); 225a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mCurrText.setTextSize(unit, size); 226a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell mNextText.setTextSize(unit, size); 227a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell } 228a4a06a94df00575480d789b60ea25ce59184df1fAdam Powell 22923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell /** 23023b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell * Set the {@link Gravity} used to position text within the title strip. 23123b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell * Only the vertical gravity component is used. 23223b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell * 23323b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell * @param gravity {@link Gravity} constant for positioning title text 23423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell */ 23523b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell public void setGravity(int gravity) { 23623b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell mGravity = gravity; 23723b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell requestLayout(); 23823b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell } 23923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell 2408fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 2418fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell protected void onAttachedToWindow() { 2428fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell super.onAttachedToWindow(); 2438fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final ViewParent parent = getParent(); 2458fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (!(parent instanceof ViewPager)) { 2468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell throw new IllegalStateException( 2478fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell "PagerTitleStrip must be a direct child of a ViewPager."); 2488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 2498fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2508fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final ViewPager pager = (ViewPager) parent; 2518fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final PagerAdapter adapter = pager.getAdapter(); 2528fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2538fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell pager.setInternalPageChangeListener(mPageListener); 2548fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell pager.setOnAdapterChangeListener(mPageListener); 2558fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mPager = pager; 2565d6251c65f890a57aa9929eb6aacae2d8b917ec9Adam Powell updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter); 2578fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 2588fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2598fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 2608fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell protected void onDetachedFromWindow() { 26182971b1050c50d3be5b2cbc285c74076e6763892Adam Powell super.onDetachedFromWindow(); 26282971b1050c50d3be5b2cbc285c74076e6763892Adam Powell if (mPager != null) { 26382971b1050c50d3be5b2cbc285c74076e6763892Adam Powell updateAdapter(mPager.getAdapter(), null); 26482971b1050c50d3be5b2cbc285c74076e6763892Adam Powell mPager.setInternalPageChangeListener(null); 26582971b1050c50d3be5b2cbc285c74076e6763892Adam Powell mPager.setOnAdapterChangeListener(null); 26682971b1050c50d3be5b2cbc285c74076e6763892Adam Powell mPager = null; 26782971b1050c50d3be5b2cbc285c74076e6763892Adam Powell } 2688fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 2698fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2708fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell void updateText(int currentItem, PagerAdapter adapter) { 2718fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int itemCount = adapter != null ? adapter.getCount() : 0; 2728fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mUpdatingText = true; 2738fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2748fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell CharSequence text = null; 2758fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (currentItem >= 1 && adapter != null) { 2768fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell text = adapter.getPageTitle(currentItem - 1); 2778fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 2788fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mPrevText.setText(text); 2798fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2808d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell mCurrText.setText(adapter != null && currentItem < itemCount ? 2818d3dd8427b57f463f0d4959c0ad8796008472caaAdam Powell adapter.getPageTitle(currentItem) : null); 2828fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2838fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell text = null; 2848fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (currentItem + 1 < itemCount && adapter != null) { 2858fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell text = adapter.getPageTitle(currentItem + 1); 2868fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 2878fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mNextText.setText(text); 2888fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2898fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell // Measure everything 2908fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int width = getWidth() - getPaddingLeft() - getPaddingRight(); 2918fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int childHeight = getHeight() - getPaddingTop() - getPaddingBottom(); 2928fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int childWidthSpec = MeasureSpec.makeMeasureSpec((int) (width * 0.8f), 2938fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell MeasureSpec.AT_MOST); 29423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST); 2958fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mPrevText.measure(childWidthSpec, childHeightSpec); 2968fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mCurrText.measure(childWidthSpec, childHeightSpec); 2978fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mNextText.measure(childWidthSpec, childHeightSpec); 2988fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 2998fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mLastKnownCurrentPage = currentItem; 3008fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3018fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (!mUpdatingPositions) { 3025f6568e7e269783e2668527461878cadfbe65215Adam Powell updateTextPositions(currentItem, mLastKnownPositionOffset, false); 3038fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3048fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3058fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mUpdatingText = false; 3068fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3078fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3088fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 3098fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void requestLayout() { 3108fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (!mUpdatingText) { 3118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell super.requestLayout(); 3128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3138fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3148fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3158fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell void updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter) { 3168fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (oldAdapter != null) { 3178fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell oldAdapter.unregisterDataSetObserver(mPageListener); 3185d6251c65f890a57aa9929eb6aacae2d8b917ec9Adam Powell mWatchingAdapter = null; 3198fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3208fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (newAdapter != null) { 3218fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell newAdapter.registerDataSetObserver(mPageListener); 3225d6251c65f890a57aa9929eb6aacae2d8b917ec9Adam Powell mWatchingAdapter = new WeakReference<PagerAdapter>(newAdapter); 3238fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3248fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (mPager != null) { 3258fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mLastKnownCurrentPage = -1; 3268fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mLastKnownPositionOffset = -1; 3278fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell updateText(mPager.getCurrentItem(), newAdapter); 328a7aea206661d601755bfac4165092d9130cba2bcAdam Powell requestLayout(); 3298fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3308fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3318fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3325f6568e7e269783e2668527461878cadfbe65215Adam Powell void updateTextPositions(int position, float positionOffset, boolean force) { 3338fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (position != mLastKnownCurrentPage) { 3348fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell updateText(position, mPager.getAdapter()); 3355f6568e7e269783e2668527461878cadfbe65215Adam Powell } else if (!force && positionOffset == mLastKnownPositionOffset) { 3368fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell return; 3378fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3388fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3398fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mUpdatingPositions = true; 3408fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3418fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int prevWidth = mPrevText.getMeasuredWidth(); 3428fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int currWidth = mCurrText.getMeasuredWidth(); 3438fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int nextWidth = mNextText.getMeasuredWidth(); 3448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int halfCurrWidth = currWidth / 2; 3458fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int stripWidth = getWidth(); 34723b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int stripHeight = getHeight(); 3488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int paddingLeft = getPaddingLeft(); 3498fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int paddingRight = getPaddingRight(); 3508fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int paddingTop = getPaddingTop(); 35123b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int paddingBottom = getPaddingBottom(); 3528fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int textPaddedLeft = paddingLeft + halfCurrWidth; 3538fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int textPaddedRight = paddingRight + halfCurrWidth; 3548fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int contentWidth = stripWidth - textPaddedLeft - textPaddedRight; 3558fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 3568fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell float currOffset = positionOffset + 0.5f; 3578fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (currOffset > 1.f) { 3588fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell currOffset -= 1.f; 3598fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 3608fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int currCenter = stripWidth - textPaddedRight - (int) (contentWidth * currOffset); 3618fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int currLeft = currCenter - currWidth / 2; 3628fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int currRight = currLeft + currWidth; 3638fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 36423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int prevBaseline = mPrevText.getBaseline(); 36523b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int currBaseline = mCurrText.getBaseline(); 36623b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int nextBaseline = mNextText.getBaseline(); 36723b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int maxBaseline = Math.max(Math.max(prevBaseline, currBaseline), nextBaseline); 36823b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int prevTopOffset = maxBaseline - prevBaseline; 36923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int currTopOffset = maxBaseline - currBaseline; 37023b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int nextTopOffset = maxBaseline - nextBaseline; 37123b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int alignedPrevHeight = prevTopOffset + mPrevText.getMeasuredHeight(); 37223b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int alignedCurrHeight = currTopOffset + mCurrText.getMeasuredHeight(); 37323b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int alignedNextHeight = nextTopOffset + mNextText.getMeasuredHeight(); 37423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int maxTextHeight = Math.max(Math.max(alignedPrevHeight, alignedCurrHeight), 37523b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell alignedNextHeight); 37623b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell 37723b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int vgrav = mGravity & Gravity.VERTICAL_GRAVITY_MASK; 37823b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell 37923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell int prevTop; 38023b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell int currTop; 38123b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell int nextTop; 38223b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell switch (vgrav) { 38323b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell default: 38423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell case Gravity.TOP: 38523b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell prevTop = paddingTop + prevTopOffset; 38623b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell currTop = paddingTop + currTopOffset; 38723b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell nextTop = paddingTop + nextTopOffset; 38823b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell break; 38923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell case Gravity.CENTER_VERTICAL: 39023b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int paddedHeight = stripHeight - paddingTop - paddingBottom; 39123b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int centeredTop = (paddedHeight - maxTextHeight) / 2; 39223b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell prevTop = centeredTop + prevTopOffset; 39323b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell currTop = centeredTop + currTopOffset; 39423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell nextTop = centeredTop + nextTopOffset; 39523b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell break; 39623b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell case Gravity.BOTTOM: 39723b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int bottomGravTop = stripHeight - paddingBottom - maxTextHeight; 39823b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell prevTop = bottomGravTop + prevTopOffset; 39923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell currTop = bottomGravTop + currTopOffset; 40023b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell nextTop = bottomGravTop + nextTopOffset; 40123b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell break; 40223b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell } 40323b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell 40423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell mCurrText.layout(currLeft, currTop, currRight, 40523b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell currTop + mCurrText.getMeasuredHeight()); 4068fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4078fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int prevLeft = Math.min(paddingLeft, currLeft - mScaledTextSpacing - prevWidth); 40823b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell mPrevText.layout(prevLeft, prevTop, prevLeft + prevWidth, 40923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell prevTop + mPrevText.getMeasuredHeight()); 4108fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int nextLeft = Math.max(stripWidth - paddingRight - nextWidth, 4128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell currRight + mScaledTextSpacing); 41323b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell mNextText.layout(nextLeft, nextTop, nextLeft + nextWidth, 41423b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell nextTop + mNextText.getMeasuredHeight()); 4158fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4168fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mLastKnownPositionOffset = positionOffset; 4178fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mUpdatingPositions = false; 4188fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4198fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4208fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 4218fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 4228fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 4238fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 4248fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 4258fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int heightSize = MeasureSpec.getSize(heightMeasureSpec); 4268fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4278fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (widthMode != MeasureSpec.EXACTLY) { 4288fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell throw new IllegalStateException("Must measure with an exact width"); 4298fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4308fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4318fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int childHeight = heightSize; 4321e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell int minHeight = getMinHeight(); 4338fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int padding = 0; 4348fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell padding = getPaddingTop() + getPaddingBottom(); 4358fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell childHeight -= padding; 4368fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4378fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell final int childWidthSpec = MeasureSpec.makeMeasureSpec((int) (widthSize * 0.8f), 4388fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell MeasureSpec.AT_MOST); 43923b42ec742c2047d6bb9b364c9609e6e0af13b9dAdam Powell final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST); 4408fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4418fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mPrevText.measure(childWidthSpec, childHeightSpec); 4428fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mCurrText.measure(childWidthSpec, childHeightSpec); 4438fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mNextText.measure(childWidthSpec, childHeightSpec); 4448fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4458fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (heightMode == MeasureSpec.EXACTLY) { 4468fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell setMeasuredDimension(widthSize, heightSize); 4478fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } else { 4488fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell int textHeight = mCurrText.getMeasuredHeight(); 4498fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell setMeasuredDimension(widthSize, Math.max(minHeight, textHeight + padding)); 4508fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4518fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4528fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4538fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 4548fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell protected void onLayout(boolean changed, int l, int t, int r, int b) { 4558fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (mPager != null) { 4561e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell final float offset = mLastKnownPositionOffset >= 0 ? mLastKnownPositionOffset : 0; 45740f36156156b6aedaf47e65f403212136c7cd7b9Adam Powell updateTextPositions(mLastKnownCurrentPage, offset, true); 4581e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 4591e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell } 4601e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell 4611e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell int getMinHeight() { 4621e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell int minHeight = 0; 4631e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell final Drawable bg = getBackground(); 4641e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell if (bg != null) { 4651e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell minHeight = bg.getIntrinsicHeight(); 4668fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4671e37da8d4fbd23a4440f32eba784520dc7a03265Adam Powell return minHeight; 4688fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4698fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4708fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private class PageListener extends DataSetObserver implements ViewPager.OnPageChangeListener, 4718fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell ViewPager.OnAdapterChangeListener { 4728fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell private int mScrollState; 4738fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4748fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 4758fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 4768fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (positionOffset > 0.5f) { 4778fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell // Consider ourselves to be on the next page when we're 50% of the way there. 4788fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell position++; 4798fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4805f6568e7e269783e2668527461878cadfbe65215Adam Powell updateTextPositions(position, positionOffset, false); 4818fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4828fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4838fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 4848fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void onPageSelected(int position) { 4858fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { 4868fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell // Only update the text here if we're not dragging or settling. 4878fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell updateText(mPager.getCurrentItem(), mPager.getAdapter()); 488cc1cad0588e86d568b9467aa2669c2160af46503Adam Powell 489cc1cad0588e86d568b9467aa2669c2160af46503Adam Powell final float offset = mLastKnownPositionOffset >= 0 ? mLastKnownPositionOffset : 0; 490cc1cad0588e86d568b9467aa2669c2160af46503Adam Powell updateTextPositions(mPager.getCurrentItem(), offset, true); 4918fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4928fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4938fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4948fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 4958fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void onPageScrollStateChanged(int state) { 4968fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell mScrollState = state; 4978fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 4988fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 4998fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 5008fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void onAdapterChanged(PagerAdapter oldAdapter, PagerAdapter newAdapter) { 5018fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell updateAdapter(oldAdapter, newAdapter); 5028fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 5038fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell 5048fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell @Override 5058fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell public void onChanged() { 5068fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell updateText(mPager.getCurrentItem(), mPager.getAdapter()); 507cc1cad0588e86d568b9467aa2669c2160af46503Adam Powell 508cc1cad0588e86d568b9467aa2669c2160af46503Adam Powell final float offset = mLastKnownPositionOffset >= 0 ? mLastKnownPositionOffset : 0; 509cc1cad0588e86d568b9467aa2669c2160af46503Adam Powell updateTextPositions(mPager.getCurrentItem(), offset, true); 5108fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 5118fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell } 5128fffe01871be1806a1bdefa1f7213b660fcf5ac0Adam Powell} 513