-
-
Save aldoborrero/70fbeb062fab0ccc7d87 to your computer and use it in GitHub Desktop.
A quick and dirty (very dirty indeed) FixedIconTabPagerIndicator which includes an Icon and a little text!
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
/** | |
* This widget implements an indicator that mimics those found | |
* in iOS. | |
*/ | |
public class FixedIconTabPageIndicator extends LinearLayout implements PageIndicator { | |
public static final String TAG = FixedIconTabPageIndicator.class.getSimpleName(); | |
private static final CharSequence DEFAULT_EMPTY_TITLE = ""; | |
private static final int DEFAULT_ANIM_TIME = 250; | |
private int mMaxTabWidth; | |
private int mSelectedTabIndex; | |
private ViewPager mViewPager; | |
private ViewPager.OnPageChangeListener mListener; | |
private Runnable mTabSelector; | |
//PageIndicator Footer required Views | |
private View[] barViews; | |
private View pageIndicatorEmptySpace; | |
private boolean gapOpen; | |
private final OnClickListener mTabClickListener = new OnClickListener() { | |
public void onClick(View view) { | |
//TabView tabView = (TabView) view; | |
TabLinearView tabView = (TabLinearView) view; | |
final int oldSelected = mViewPager.getCurrentItem(); | |
final int newSelected = tabView.getIndex(); | |
//Use array of views | |
for (int i = 0; i < barViews.length; i++) { | |
if (i == newSelected) | |
barViews[i].setBackgroundColor(Color.RED); | |
else | |
barViews[i].setBackgroundColor(Color.TRANSPARENT); | |
} | |
mViewPager.setCurrentItem(newSelected); | |
if (oldSelected == newSelected && mTabReselectedListener != null) { | |
mTabReselectedListener.onTabReselected(newSelected); | |
} | |
} | |
}; | |
private OnTabReselectedListener mTabReselectedListener; | |
/** | |
* Interface for a callback when the selected tab has been reselected. | |
*/ | |
public interface OnTabReselectedListener { | |
/** | |
* Callback when the selected tab has been reselected. | |
* | |
* @param position Position of the current center item. | |
*/ | |
void onTabReselected(int position); | |
} | |
public FixedIconTabPageIndicator(Context context) { | |
this(context, null); | |
} | |
public FixedIconTabPageIndicator(Context context, AttributeSet attrs) { | |
this(context, attrs, 0); | |
} | |
public FixedIconTabPageIndicator(Context context, AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
setHorizontalGravity(LinearLayout.HORIZONTAL); | |
} | |
@Override | |
public void onAttachedToWindow() { | |
super.onAttachedToWindow(); | |
if (mTabSelector != null) { | |
post(mTabSelector); | |
} | |
} | |
@Override | |
public void onDetachedFromWindow() { | |
super.onDetachedFromWindow(); | |
if (mTabSelector != null) { | |
removeCallbacks(mTabSelector); | |
} | |
} | |
@Override | |
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
} | |
@Override | |
public void setViewPager(ViewPager view) { | |
if (mViewPager == view) { | |
return; | |
} | |
if (mViewPager != null) { | |
mViewPager.setOnPageChangeListener(null); | |
} | |
final PagerAdapter adapter = view.getAdapter(); | |
if (adapter == null) { | |
throw new IllegalStateException("ViewPager does not have adapter instance."); | |
} | |
mViewPager = view; | |
view.setOnPageChangeListener(this); | |
notifyDataSetChanged(); | |
} | |
@Override | |
public void setViewPager(ViewPager view, int initialPosition) { | |
setViewPager(view); | |
setCurrentItem(initialPosition); | |
} | |
@Override | |
public void setCurrentItem(int item) { | |
if (mViewPager == null) { | |
throw new IllegalStateException("ViewPager has not been bound."); | |
} | |
mSelectedTabIndex = item; | |
mViewPager.setCurrentItem(item); | |
final int tabCount = getChildCount(); | |
for (int i = 0; i < tabCount; i++) { | |
final View child = getChildAt(i); | |
final boolean isSelected = (i == item); | |
child.setSelected(isSelected); | |
if (isSelected) { | |
animateToTab(item); | |
} | |
} | |
} | |
@Override | |
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { | |
mListener = listener; | |
} | |
@Override | |
public void notifyDataSetChanged() { | |
removeAllViews(); | |
PagerAdapter adapter = mViewPager.getAdapter(); | |
IconPagerAdapter iconAdapter = null; | |
if (adapter instanceof IconPagerAdapter) { | |
iconAdapter = (IconPagerAdapter) adapter; | |
} | |
int count = adapter.getCount(); | |
barViews = new View[count]; | |
boolean emptyTabAdded = false; | |
for (int i = 0; i < count; i++) { | |
if (!emptyTabAdded && i == count / 2) { //Center of the indicator | |
emptyTabAdded = true; | |
addEmptyTab(); | |
i--; //Ignore this step on the bucle | |
} else { | |
CharSequence title = adapter.getPageTitle(i); | |
if (title == null) { | |
title = DEFAULT_EMPTY_TITLE; | |
} | |
int iconResId = 0; | |
if (iconAdapter != null) { | |
iconResId = iconAdapter.getIconResId(i); | |
} | |
addTab(i, title, iconResId); | |
} | |
} | |
count++; | |
if (mSelectedTabIndex > count) { | |
mSelectedTabIndex = count - 1; | |
} | |
setCurrentItem(mSelectedTabIndex); | |
requestLayout(); | |
} | |
@Override | |
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { | |
if (mListener != null) { | |
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); | |
} | |
} | |
@Override | |
public void onPageSelected(int position) { | |
setCurrentItem(position); | |
if (mListener != null) { | |
mListener.onPageSelected(position); | |
} | |
} | |
@Override | |
public void onPageScrollStateChanged(int state) { | |
if (mListener != null) { | |
mListener.onPageScrollStateChanged(state); | |
} | |
} | |
public void setOnTabReselectedListener(OnTabReselectedListener listener) { | |
mTabReselectedListener = listener; | |
} | |
private void addEmptyTab() { | |
final TabLinearView tabView = new TabLinearView(getContext()); | |
pageIndicatorEmptySpace = tabView; //Store the middle view in attribute | |
addView(tabView, new LinearLayout.LayoutParams(0, MATCH_PARENT)); | |
} | |
private void addTab(int index, CharSequence text, int iconResId) { | |
final TabLinearView tabView = new TabLinearView(getContext()); | |
tabView.setIndex(index); | |
tabView.setFocusable(true); | |
tabView.setOnClickListener(mTabClickListener); | |
ImageView imgIconIndicator = new ImageView(getContext()); | |
imgIconIndicator.setImageDrawable(getResources().getDrawable(iconResId)); | |
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(35), dpToPx(35)); | |
params.gravity = Gravity.CENTER; | |
imgIconIndicator.setLayoutParams(params); | |
imgIconIndicator.setPadding(dpToPx(4), dpToPx(4), dpToPx(4), 0); | |
tabView.addView(imgIconIndicator); | |
TextView txtIconIndicator = new TextView(getContext()); | |
txtIconIndicator.setText(text); | |
txtIconIndicator.setTextSize(12); | |
txtIconIndicator.setTextColor(Color.BLACK); | |
txtIconIndicator.setGravity(Gravity.CENTER); | |
txtIconIndicator.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)); | |
tabView.addView(txtIconIndicator); | |
View viewIconSelection = new View(getContext()); | |
LinearLayout.LayoutParams viewParams = new LinearLayout.LayoutParams(MATCH_PARENT, 6); | |
viewParams.setMargins(dpToPx(5), 0, dpToPx(5), 0); | |
viewIconSelection.setLayoutParams(viewParams); | |
if (index == 0) { | |
viewIconSelection.setBackgroundColor(Color.RED); | |
} else { | |
viewIconSelection.setBackgroundColor(Color.TRANSPARENT); | |
} | |
barViews[index] = viewIconSelection; //Store views in array of views | |
tabView.addView(viewIconSelection); | |
addView(tabView, new LinearLayout.LayoutParams(0, MATCH_PARENT, 1)); | |
} | |
private static Drawable scaleDrawable(Drawable drawable, int width, int height) { | |
int wi = drawable.getIntrinsicWidth(); | |
int hi = drawable.getIntrinsicHeight(); | |
int dimDiff = Math.abs(wi - width) - Math.abs(hi - height); | |
float scale = (dimDiff > 0) ? width / (float) wi : height / | |
(float) hi; | |
Rect bounds = new Rect(0, 0, (int) (scale * wi), (int) (scale * hi)); | |
drawable.setBounds(bounds); | |
return drawable; | |
} | |
private void animateToTab(final int position) { | |
final View tabView = getChildAt(position); | |
if (mTabSelector != null) { | |
removeCallbacks(mTabSelector); | |
} | |
mTabSelector = new Runnable() { | |
public void run() { | |
final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2; | |
//smoothScrollTo(scrollPos, 0); | |
mTabSelector = null; | |
} | |
}; | |
post(mTabSelector); | |
} | |
public void showSpaceGap() { | |
if (!gapOpen) { | |
ResizeWidthAnimation anim = new ResizeWidthAnimation(pageIndicatorEmptySpace, barViews[0].getWidth() - dpToPx(20)); | |
anim.setDuration(DEFAULT_ANIM_TIME); | |
pageIndicatorEmptySpace.startAnimation(anim); | |
gapOpen = true; | |
} | |
} | |
public void hideSpaceGap() { | |
if (gapOpen) { | |
ResizeWidthAnimation anim = new ResizeWidthAnimation(pageIndicatorEmptySpace, 0); | |
anim.setDuration(DEFAULT_ANIM_TIME); | |
pageIndicatorEmptySpace.startAnimation(anim); | |
gapOpen = false; | |
} | |
} | |
public void toogleGapAnimation() { | |
ResizeWidthAnimation anim; | |
if (!gapOpen) { | |
anim = new ResizeWidthAnimation(pageIndicatorEmptySpace, barViews[0].getWidth() - dpToPx(20)); | |
gapOpen = true; | |
} else { | |
anim = new ResizeWidthAnimation(pageIndicatorEmptySpace, 0); | |
gapOpen = false; | |
} | |
anim.setDuration(DEFAULT_ANIM_TIME); | |
pageIndicatorEmptySpace.startAnimation(anim); | |
} | |
public boolean isGapOpen() { | |
return gapOpen; | |
} | |
private static class TabLinearView extends LinearLayout { | |
private int mIndex; | |
public TabLinearView(Context context) { | |
super(context, null, R.attr.vpiTabPageIndicatorStyle); | |
this.setOrientation(VERTICAL); | |
this.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); | |
} | |
public void setIndex(int index) { | |
this.mIndex = index; | |
} | |
public int getIndex() { | |
return mIndex; | |
} | |
} | |
public int pxToDp(int px) { | |
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics(); | |
int dp = Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT)); | |
return dp; | |
} | |
public int dpToPx(float dp) { | |
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); | |
float px = dp * (metrics.densityDpi / 160f); | |
return (int) px; | |
} | |
private static class ResizeWidthAnimation extends Animation { | |
private int mWidth; | |
private int mStartWidth; | |
private View mView; | |
public ResizeWidthAnimation(View view, int width) { | |
mView = view; | |
mWidth = width; | |
mStartWidth = view.getWidth(); | |
} | |
@Override | |
protected void applyTransformation(float interpolatedTime, Transformation t) { | |
int newWidth = mStartWidth + (int) ((mWidth - mStartWidth) * interpolatedTime); | |
mView.getLayoutParams().width = newWidth; | |
mView.requestLayout(); | |
} | |
@Override | |
public void initialize(int width, int height, int parentWidth, int parentHeight) { | |
super.initialize(width, height, parentWidth, parentHeight); | |
} | |
@Override | |
public boolean willChangeBounds() { | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment