Skip to content

Instantly share code, notes, and snippets.

@mkuprionis
Created May 14, 2014 10:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mkuprionis/6346a0ead20966d7eb1e to your computer and use it in GitHub Desktop.
Save mkuprionis/6346a0ead20966d7eb1e to your computer and use it in GitHub Desktop.
Embeded ActionBar tabs

Copied from Cyril Mottier's post on G+

His comments:

In order to implement tabs I decided to go for an entirely custom solution. I created the tab bar from scratch and added it as a custom ActionBar View. The tabs container is called TabBarView and extends LinearLayout. TabBarView actually handles the "selection strip".

The TabBarView is then filled with several TabView (one for each tab). The main purpose of TabView is to provide a nice API to deal with icon and the optional text (only visible in landscape) and handle the long press gesture (long pressing a tab displays a hint).

Once the TabBarView is initialized with a bunch of TabView, it is added as a custom View to the ActionBar:

getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); getActionBar().setCustomView(R.layout.tab_bar);

Finally an OnPageChangeListener is set to ViewPager to be notified of scroll events. These events are forwarded to the TabBarView so that it can redraw the selection strip accordingly.

public class TabBarView extends LinearLayout {
private static final int STRIP_HEIGHT = 6;
public final Paint mPaint;
private int mStripHeight;
private float mOffset;
private int mSelectedTab = -1;
public TabBarView(Context context) {
this(context, null);
}
public TabBarView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.actionBarTabBarStyle);
}
public TabBarView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mStripHeight = (int) (STRIP_HEIGHT * getResources().getDisplayMetrics().density + .5f);
}
public void setStripColor(int color) {
if (mPaint.getColor() != color) {
mPaint.setColor(color);
invalidate();
}
}
public void setStripHeight(int height) {
if (mStripHeight != height) {
mStripHeight = height;
invalidate();
}
}
public void setSelectedTab(int tabIndex) {
if (tabIndex < 0) {
tabIndex = 0;
}
final int childCount = getChildCount();
if (tabIndex >= childCount) {
tabIndex = childCount - 1;
}
if (mSelectedTab != tabIndex) {
mSelectedTab = tabIndex;
invalidate();
}
}
public void setOffset(float offset) {
if (mOffset != offset) {
mOffset = offset;
invalidate();
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
// Draw the strip manually
final View child = getChildAt(mSelectedTab);
if (child != null) {
int left = child.getLeft();
int right = child.getRight();
if (mOffset > 0) {
final View nextChild = getChildAt(mSelectedTab + 1);
if (nextChild != null) {
left = (int) (child.getLeft() + mOffset * (nextChild.getLeft() - child.getLeft()));
right = (int) (child.getRight() + mOffset * (nextChild.getRight() - child.getRight()));
}
}
canvas.drawRect(left, getHeight() - mStripHeight, right, getHeight(), mPaint);
}
}
}
public class TabView extends LinearLayout {
private ImageView mImageView;
private TextView mTextView;
public TabView(Context context) {
this(context, null);
}
public TabView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.actionBarTabStyle);
}
public TabView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInflater.from(context).inflate(R.layout.tab_view_merge, this);
mImageView = (ImageView) findViewById(R.id.image);
mTextView = (TextView) findViewById(R.id.text);
}
public void setIcon(int resId) {
setIcon(getContext().getResources().getDrawable(resId));
}
public void setIcon(Drawable icon) {
if (icon != null) {
mImageView.setVisibility(View.VISIBLE);
mImageView.setImageDrawable(icon);
} else {
mImageView.setImageResource(View.GONE);
}
}
public void setText(int resId) {
setText(getContext().getString(resId));
}
public void setText(CharSequence text) {
if (!TextUtils.isEmpty(text)) {
if (mTextView != null) {
mTextView.setVisibility(View.VISIBLE);
mTextView.setText(text);
}
} else {
if (mTextView != null) {
mTextView.setVisibility(View.GONE);
}
}
updateHint();
}
@Override
public void setContentDescription(CharSequence contentDescription) {
super.setContentDescription(contentDescription);
updateHint();
}
private void updateHint() {
boolean needHint = false;
if (mTextView == null || mTextView.getVisibility() == View.GONE) {
if (!TextUtils.isEmpty(getContentDescription())) {
needHint = true;
} else {
needHint = false;
}
}
if (needHint) {
setOnLongClickListener(mOnLongClickListener);
} else {
setOnLongClickListener(null);
setLongClickable(false);
}
}
private OnLongClickListener mOnLongClickListener = new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
final int[] screenPos = new int[2];
getLocationOnScreen(screenPos);
final Context context = getContext();
final int width = getWidth();
final int height = getHeight();
final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
Toast cheatSheet = Toast.makeText(context, getContentDescription(), Toast.LENGTH_SHORT);
// Show under the tab
cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, (screenPos[0] + width / 2) - screenWidth / 2,
height);
cheatSheet.show();
return true;
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment