Skip to content

Instantly share code, notes, and snippets.

@SebastianEngel
Last active August 22, 2016 10:12
Show Gist options
  • Save SebastianEngel/9099e004e8b2c3b4c364 to your computer and use it in GitHub Desktop.
Save SebastianEngel/9099e004e8b2c3b4c364 to your computer and use it in GitHub Desktop.
Implementation of fixed tabs - Stackoverflow question. Note that these classes must be placed into a package "android.support.v4.view" as ViewPager.DecorView is not public.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.app.ui.NonSwipeableViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTwoTabsStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:orientation="horizontal"
style="@style/LocationsTabViewPagerIndicator" />
</com.example.app.ui.NonSwipeableViewPager>
</FrameLayout>
/**
* Subclass of {@link PagerTwoTitlesStrip} and so implementation of a {@link android.widget.LinearLayout}
* used as a {@link android.support.v4.view.ViewPager} indicator. This view holds two {@link android.widget.TextView}s, each being
* the title of the two pages. The title of the 'current' tab is underlined by a tab indicator.
*
* <p>Inspired by Google's {@link PagerTabStrip}</p>
*/
public class PagerTwoTabsStrip extends PagerTwoTitlesStrip {
@SuppressWarnings("unused")
private static final String LOG_TAG = PagerTwoTabsStrip.class.getName();
private static final int INDICATOR_HEIGHT = 4; // dp
private final Paint tabPaint = new Paint();
private int indicatorHeight;
public PagerTwoTabsStrip(Context context) {
this(context, null);
}
public PagerTwoTabsStrip(Context context, AttributeSet attrs) {
super(context, attrs);
// Note: this follows the rules for Resources#getDimensionPixelOffset/Size:
// sizes round up, offsets round down.
final float density = context.getResources().getDisplayMetrics().density;
indicatorHeight = (int) (INDICATOR_HEIGHT * density + 0.5f);
tabPaint.setColor(getResources().getColor(R.color.white));
setWillNotDraw(false);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final int bottom = getHeight();
final int left = activeTabTextView.getLeft();
final int right = activeTabTextView.getRight();
final int top = bottom - indicatorHeight;
canvas.drawRect(left, top, right, bottom, tabPaint);
}
}
/**
* Implementation of a {@link android.widget.LinearLayout} used as a {@link android.support.v4.view.ViewPager} indicator.
* This view holds two {@link android.widget.TextView}s, each being the title of the two pages.
*
* <p>Inspired by Google's {@link PagerTitleStrip}</p>
*/
public class PagerTwoTitlesStrip extends LinearLayout implements ViewPager.Decor {
@SuppressWarnings("unused")
private static final String LOG_TAG = PagerTwoTitlesStrip.class.getName();
private static final int[] ATTRS = new int[] {
android.R.attr.textAppearance,
android.R.attr.textSize,
android.R.attr.textColor,
android.R.attr.gravity
};
/**
* The currently active (selected) tab's TextView.
*/
TextView activeTabTextView;
/**
* TextView holding the text of the first tab.
*/
private TextView tab1TextView;
/**
* TextView holding the text of the second tab.
*/
private TextView tab2TextView;
private ViewPager viewPager;
public PagerTwoTitlesStrip(Context context) {
super(context);
}
public PagerTwoTitlesStrip(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutParams linearLayoutParams = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1);
// Setup tab 1
tab1TextView = new TextView(context);
tab1TextView.setText(R.string.view_tab_locations_mapview);
tab1TextView.setSingleLine();
tab1TextView.setGravity(Gravity.CENTER);
tab1TextView.setPadding(0, 18, 0, 19);
tab1TextView.setOnTouchListener(new TabOnTouchListener(tab1TextView, 0));
// Setup tab 2
tab2TextView = new TextView(context);
tab2TextView.setText(R.string.view_tab_locations_listview);
tab2TextView.setSingleLine();
tab2TextView.setGravity(Gravity.CENTER);
tab2TextView.setPadding(0, 18, 0, 19);
tab2TextView.setOnTouchListener(new TabOnTouchListener(tab2TextView, 1));
// Style the text
final TypedArray attributes = context.obtainStyledAttributes(attrs, ATTRS);
final int textAppearance = attributes.getResourceId(0, 0);
if (textAppearance != 0) {
tab1TextView.setTextAppearance(context, textAppearance);
tab2TextView.setTextAppearance(context, textAppearance);
}
final int textSize = attributes.getDimensionPixelSize(1, 0);
if (textSize != 0) {
tab1TextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
tab2TextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
if (attributes.hasValue(2)) {
final int textColor = attributes.getColor(2, 0);
tab1TextView.setTextColor(textColor);
tab2TextView.setTextColor(textColor);
}
attributes.recycle();
setActiveTab(tab1TextView);
addView(tab1TextView, linearLayoutParams);
addView(tab2TextView, linearLayoutParams);
}
private class TabOnTouchListener implements OnTouchListener {
private int itemId;
private TabOnTouchListener(TextView textView, int itemId) {
this.itemId = itemId;
}
@Override
public boolean onTouch(View view, MotionEvent event) {
TextView textView = ((TextView) view);
setActiveTab(textView);
viewPager.setCurrentItem(itemId);
return true;
}
}
private void setActiveTab(TextView activeTabTextView) {
tab1TextView.setTextColor(getResources().getColor(R.color.bsr_orange));
tab2TextView.setTextColor(getResources().getColor(R.color.bsr_orange));
this.activeTabTextView = activeTabTextView;
activeTabTextView.setTextColor(getResources().getColor(R.color.white));
invalidate();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
final ViewParent parent = getParent();
if (!(parent instanceof ViewPager)) {
throw new IllegalStateException(
"PagerTwoTitlesStrip must be a direct child of a ViewPager.");
}
viewPager = (ViewPager) parent;
}
}
...
<style name="LocationsTabViewPagerIndicator">
<item name="android:background">@color/anthracite</item>
<item name="android:textColor">@color/white</item>
</style>
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment