Created
September 3, 2015 14:51
-
-
Save sveinungkb/87624bd65b47b2bc105a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2012 The Android Open Source Project | |
* | |
* 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. | |
*/ | |
/** | |
* Since v23 of the support library contain a layout bug we include the v22 of these files. | |
* https://code.google.com/p/android/issues/detail?id=184715& | |
*/ | |
package android.support.v4.view; | |
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.graphics.Paint; | |
import android.graphics.Rect; | |
import android.graphics.drawable.Drawable; | |
import android.support.annotation.ColorRes; | |
import android.support.annotation.DrawableRes; | |
import android.util.AttributeSet; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.view.ViewConfiguration; | |
/** | |
* PagerTabStrip is an interactive indicator of the current, next, | |
* and previous pages of a {@link android.support.v4.view.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 android.support.v4.view.PagerAdapter#getPageTitle(int)} in the adapter supplied to | |
* the ViewPager. | |
* | |
* <p>For a non-interactive indicator, see {@link PagerTitleStripV22}.</p> | |
*/ | |
public class PagerTabStripV22 extends PagerTitleStripV22 { | |
private static final String TAG = "PagerTabStrip"; | |
private static final int INDICATOR_HEIGHT = 3; // dp | |
private static final int MIN_PADDING_BOTTOM = INDICATOR_HEIGHT + 3; // dp | |
private static final int TAB_PADDING = 16; // dp | |
private static final int TAB_SPACING = 32; // dp | |
private static final int MIN_TEXT_SPACING = TAB_SPACING + TAB_PADDING * 2; // dp | |
private static final int FULL_UNDERLINE_HEIGHT = 1; // 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 final Rect mTempRect = new Rect(); | |
private int mTabAlpha = 0xFF; | |
private boolean mDrawFullUnderline = false; | |
private boolean mDrawFullUnderlineSet = false; | |
private int mFullUnderlineHeight; | |
private boolean mIgnoreTap; | |
private float mInitialMotionX; | |
private float mInitialMotionY; | |
private int mTouchSlop; | |
public PagerTabStripV22(Context context) { | |
this(context, null); | |
} | |
public PagerTabStripV22(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
mIndicatorColor = mTextColor; | |
mTabPaint.setColor(mIndicatorColor); | |
// Note: this follows the rules for Resources#getDimensionPixelOffset/Size: | |
// sizes round up, offsets round down. | |
final float density = context.getResources().getDisplayMetrics().density; | |
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); | |
mFullUnderlineHeight = (int) (FULL_UNDERLINE_HEIGHT * 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); | |
mPrevText.setFocusable(true); | |
mPrevText.setOnClickListener(new OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
mPager.setCurrentItem(mPager.getCurrentItem() - 1); | |
} | |
}); | |
mNextText.setFocusable(true); | |
mNextText.setOnClickListener(new OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
mPager.setCurrentItem(mPager.getCurrentItem() + 1); | |
} | |
}); | |
if (getBackground() == null) { | |
mDrawFullUnderline = true; | |
} | |
} | |
/** | |
* Set the color of the tab indicator bar. | |
* | |
* @param color Color to set as an 0xRRGGBB value. The high byte (alpha) is ignored. | |
*/ | |
public void setTabIndicatorColor(int color) { | |
mIndicatorColor = color; | |
mTabPaint.setColor(mIndicatorColor); | |
invalidate(); | |
} | |
/** | |
* Set the color of the tab indicator bar from a color resource. | |
* | |
* @param resId Resource ID of a color resource to load | |
*/ | |
public void setTabIndicatorColorResource(@ColorRes int resId) { | |
setTabIndicatorColor(getContext().getResources().getColor(resId)); | |
} | |
/** | |
* @return The current tab indicator color as an 0xRRGGBB value. | |
*/ | |
public int getTabIndicatorColor() { | |
return mIndicatorColor; | |
} | |
@Override | |
public void setPadding(int left, int top, int right, int bottom) { | |
if (bottom < mMinPaddingBottom) { | |
bottom = mMinPaddingBottom; | |
} | |
super.setPadding(left, top, right, bottom); | |
} | |
@Override | |
public void setTextSpacing(int textSpacing) { | |
if (textSpacing < mMinTextSpacing) { | |
textSpacing = mMinTextSpacing; | |
} | |
super.setTextSpacing(textSpacing); | |
} | |
@Override | |
public void setBackgroundDrawable(Drawable d) { | |
super.setBackgroundDrawable(d); | |
if (!mDrawFullUnderlineSet) { | |
mDrawFullUnderline = d == null; | |
} | |
} | |
@Override | |
public void setBackgroundColor(int color) { | |
super.setBackgroundColor(color); | |
if (!mDrawFullUnderlineSet) { | |
mDrawFullUnderline = (color & 0xFF000000) == 0; | |
} | |
} | |
@Override | |
public void setBackgroundResource(@DrawableRes int resId) { | |
super.setBackgroundResource(resId); | |
if (!mDrawFullUnderlineSet) { | |
mDrawFullUnderline = resId == 0; | |
} | |
} | |
/** | |
* Set whether this tab strip should draw a full-width underline in the | |
* current tab indicator color. | |
* | |
* @param drawFull true to draw a full-width underline, false otherwise | |
*/ | |
public void setDrawFullUnderline(boolean drawFull) { | |
mDrawFullUnderline = drawFull; | |
mDrawFullUnderlineSet = true; | |
invalidate(); | |
} | |
/** | |
* Return whether or not this tab strip will draw a full-width underline. | |
* This defaults to true if no background is set. | |
* | |
* @return true if this tab strip will draw a full-width underline in the | |
* current tab indicator color. | |
*/ | |
public boolean getDrawFullUnderline() { | |
return mDrawFullUnderline; | |
} | |
@Override | |
int getMinHeight() { | |
return Math.max(super.getMinHeight(), mMinStripHeight); | |
} | |
@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 < mCurrText.getLeft() - mTabPadding) { | |
mPager.setCurrentItem(mPager.getCurrentItem() - 1); | |
} else if (x > mCurrText.getRight() + mTabPadding) { | |
mPager.setCurrentItem(mPager.getCurrentItem() + 1); | |
} | |
break; | |
} | |
return true; | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
super.onDraw(canvas); | |
final int height = getHeight(); | |
final int bottom = height; | |
final int left = mCurrText.getLeft() - mTabPadding; | |
final int right = mCurrText.getRight() + mTabPadding; | |
final int top = bottom - mIndicatorHeight; | |
mTabPaint.setColor(mTabAlpha << 24 | (mIndicatorColor & 0xFFFFFF)); | |
canvas.drawRect(left, top, right, bottom, mTabPaint); | |
if (mDrawFullUnderline) { | |
mTabPaint.setColor(0xFF << 24 | (mIndicatorColor & 0xFFFFFF)); | |
canvas.drawRect(getPaddingLeft(), height - mFullUnderlineHeight, | |
getWidth() - getPaddingRight(), height, mTabPaint); | |
} | |
} | |
@Override | |
void updateTextPositions(int position, float positionOffset, boolean force) { | |
final Rect r = mTempRect; | |
int bottom = getHeight(); | |
int left = mCurrText.getLeft() - mTabPadding; | |
int right = mCurrText.getRight() + mTabPadding; | |
int top = bottom - mIndicatorHeight; | |
r.set(left, top, right, bottom); | |
super.updateTextPositions(position, positionOffset, force); | |
mTabAlpha = (int) (Math.abs(positionOffset - 0.5f) * 2 * 0xFF); | |
left = mCurrText.getLeft() - mTabPadding; | |
right = mCurrText.getRight() + mTabPadding; | |
r.union(left, top, right, bottom); | |
invalidate(r); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment