Customize TabView to vertical

This commit is contained in:
khanhduytran0 2020-10-04 13:12:38 +07:00
parent 2037ca27e8
commit 00df18073f

View File

@ -77,7 +77,7 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
/** /**
* VerticalTabLayout provides a horizontal layout to display tabs. * VerticalTabLayout provides a vertical layout to display tabs.
* *
* <p>Population of the tabs to display is * <p>Population of the tabs to display is
* done through {@link Tab} instances. You create tabs via {@link #newTab()}. From there you can * done through {@link Tab} instances. You create tabs via {@link #newTab()}. From there you can
@ -299,7 +299,7 @@ public class VerticalTabLayout extends ScrollView {
ThemeUtils.checkAppCompatTheme(context); ThemeUtils.checkAppCompatTheme(context);
// Disable the Scroll Bar // Disable the Scroll Bar
setVerticalScrollBarEnabled(false); // setVerticalScrollBarEnabled(false);
// Add the TabStrip // Add the TabStrip
mTabStrip = new SlidingTabStrip(context); mTabStrip = new SlidingTabStrip(context);
@ -982,21 +982,18 @@ public class VerticalTabLayout extends ScrollView {
} }
private LinearLayout.LayoutParams createLayoutParamsForTabs() { private LinearLayout.LayoutParams createLayoutParamsForTabs() {
// Horizontal: WRAP_CONTENT, MATCH_PARENT
final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
updateTabViewLayoutParams(lp); updateTabViewLayoutParams(lp);
return lp; return lp;
} }
private void updateTabViewLayoutParams(LinearLayout.LayoutParams lp) { private void updateTabViewLayoutParams(LinearLayout.LayoutParams lp) {
if (mMode == MODE_FIXED && mTabGravity == GRAVITY_FILL) { if (mMode == MODE_FIXED && mTabGravity == GRAVITY_FILL) {
// Horizontal: width 0 lp.width = 0;
lp.height = 0;
lp.weight = 1; lp.weight = 1;
} else { } else {
// Horizontal: width WRAP_CONTENT lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
lp.weight = 0; lp.weight = 0;
} }
} }
@ -1009,17 +1006,15 @@ public class VerticalTabLayout extends ScrollView {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// If we have a MeasureSpec which allows us to decide our height, try and use the default // If we have a MeasureSpec which allows us to decide our height, try and use the default
// height // height
// Horizintal: idealHeight
final int idealHeight = dpToPx(getDefaultHeight()) + getPaddingTop() + getPaddingBottom(); final int idealHeight = dpToPx(getDefaultHeight()) + getPaddingTop() + getPaddingBottom();
// final int idealWidth = dpToPx(getDefaultHeight()) + getPaddingLeft() + getPaddingRight();
switch (MeasureSpec.getMode(heightMeasureSpec)) { switch (MeasureSpec.getMode(heightMeasureSpec)) {
case MeasureSpec.AT_MOST: case MeasureSpec.AT_MOST:
heightMeasureSpec = MeasureSpec.makeMeasureSpec( heightMeasureSpec = MeasureSpec.makeMeasureSpec(
Math.min(idealHeight, MeasureSpec.getSize(heightMeasureSpec)), Math.min(idealHeight, MeasureSpec.getSize(heightMeasureSpec)),
MeasureSpec.EXACTLY); MeasureSpec.EXACTLY);
break; break;
case MeasureSpec.UNSPECIFIED: case 0 /* MeasureSpec.UNSPECIFIED */:
heightMeasureSpec = MeasureSpec.makeMeasureSpec(idealHeight, MeasureSpec.EXACTLY); heightMeasureSpec = MeasureSpec.makeMeasureSpec(idealHeight, MeasureSpec.EXACTLY);
break; break;
} }
@ -1216,8 +1211,7 @@ public class VerticalTabLayout extends ScrollView {
switch (mMode) { switch (mMode) {
case MODE_FIXED: case MODE_FIXED:
// Horizontal: CENTER_HORIZONTAL mTabStrip.setGravity(Gravity.CENTER_HORIZONTAL);
mTabStrip.setGravity(Gravity.CENTER_VERTICAL);
break; break;
case MODE_SCROLLABLE: case MODE_SCROLLABLE:
mTabStrip.setGravity(GravityCompat.START); mTabStrip.setGravity(GravityCompat.START);
@ -1798,14 +1792,19 @@ public class VerticalTabLayout extends ScrollView {
private int mLayoutDirection = -1; private int mLayoutDirection = -1;
private int mIndicatorLeft = -1; private int mIndicatorTop = -1;
private int mIndicatorRight = -1; private int mIndicatorBottom = -1;
private ValueAnimator mIndicatorAnimator; private ValueAnimator mIndicatorAnimator;
SlidingTabStrip(Context context) { SlidingTabStrip(Context context) {
super(context); super(context);
setWillNotDraw(false); setWillNotDraw(false);
// Easy way to get vertical tab view
setOrientation(VERTICAL);
mSelectedIndicatorPaint = new Paint(); mSelectedIndicatorPaint = new Paint();
} }
@ -1938,32 +1937,32 @@ public class VerticalTabLayout extends ScrollView {
private void updateIndicatorPosition() { private void updateIndicatorPosition() {
final View selectedTitle = getChildAt(mSelectedPosition); final View selectedTitle = getChildAt(mSelectedPosition);
int left, right; int top, bottom;
if (selectedTitle != null && selectedTitle.getWidth() > 0) { if (selectedTitle != null && selectedTitle.getWidth() > 0) {
left = selectedTitle.getLeft(); top = selectedTitle.getTop();
right = selectedTitle.getRight(); bottom = selectedTitle.getBottom();
if (mSelectionOffset > 0f && mSelectedPosition < getChildCount() - 1) { if (mSelectionOffset > 0f && mSelectedPosition < getChildCount() - 1) {
// Draw the selection partway between the tabs // Draw the selection partway between the tabs
View nextTitle = getChildAt(mSelectedPosition + 1); View nextTitle = getChildAt(mSelectedPosition + 1);
left = (int) (mSelectionOffset * nextTitle.getLeft() + top = (int) (mSelectionOffset * nextTitle.getTop() +
(1.0f - mSelectionOffset) * left); (1.0f - mSelectionOffset) * top);
right = (int) (mSelectionOffset * nextTitle.getRight() + bottom = (int) (mSelectionOffset * nextTitle.getBottom() +
(1.0f - mSelectionOffset) * right); (1.0f - mSelectionOffset) * bottom);
} }
} else { } else {
left = right = -1; top = bottom = -1;
} }
setIndicatorPosition(left, right); setIndicatorPosition(top, bottom);
} }
void setIndicatorPosition(int left, int right) { void setIndicatorPosition(int top, int bottom) {
if (left != mIndicatorLeft || right != mIndicatorRight) { if (top != mIndicatorTop || bottom != mIndicatorBottom) {
// If the indicator's left/right has changed, invalidate // If the indicator's left/right has changed, invalidate
mIndicatorLeft = left; mIndicatorTop = top;
mIndicatorRight = right; mIndicatorBottom = bottom;
ViewCompat.postInvalidateOnAnimation(this); ViewCompat.postInvalidateOnAnimation(this);
} }
} }
@ -1983,36 +1982,40 @@ public class VerticalTabLayout extends ScrollView {
return; return;
} }
final int targetLeft = targetView.getLeft(); final int targetTop = targetView.getTop();
final int targetRight = targetView.getRight(); final int targetBottom = targetView.getBottom();
final int startLeft; final int startTop;
final int startRight; final int startBottom;
if (Math.abs(position - mSelectedPosition) <= 1) { if (Math.abs(position - mSelectedPosition) <= 1) {
// If the views are adjacent, we'll animate from edge-to-edge // If the views are adjacent, we'll animate from edge-to-edge
startLeft = mIndicatorLeft; startTop = mIndicatorTop;
startRight = mIndicatorRight; startBottom = mIndicatorBottom;
} else { } else {
// Else, we'll just grow from the nearest edge // Else, we'll just grow from the nearest edge
final int offset = dpToPx(MOTION_NON_ADJACENT_OFFSET); final int offset = dpToPx(MOTION_NON_ADJACENT_OFFSET);
if (position < mSelectedPosition) { if (position < mSelectedPosition) {
// We're going end-to-start // We're going end-to-start
/*
if (isRtl) { if (isRtl) {
startLeft = startRight = targetLeft - offset; startTop = startBottom = targetTop - offset;
} else { } else {
startLeft = startRight = targetRight + offset; */
} startTop = startBottom = targetBottom + offset;
// }
} else { } else {
// We're going start-to-end // We're going start-to-end
/*
if (isRtl) { if (isRtl) {
startLeft = startRight = targetRight + offset; startLeft = startRight = targetRight + offset;
} else { } else {
startLeft = startRight = targetLeft - offset; */
} startTop = startBottom = targetTop - offset;
// }
} }
} }
if (startLeft != targetLeft || startRight != targetRight) { if (startTop != targetTop || startBottom != targetBottom) {
ValueAnimator animator = mIndicatorAnimator = new ValueAnimator(); ValueAnimator animator = mIndicatorAnimator = new ValueAnimator();
animator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR); animator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
animator.setDuration(duration); animator.setDuration(duration);
@ -2022,8 +2025,8 @@ public class VerticalTabLayout extends ScrollView {
public void onAnimationUpdate(ValueAnimator animator) { public void onAnimationUpdate(ValueAnimator animator) {
final float fraction = animator.getAnimatedFraction(); final float fraction = animator.getAnimatedFraction();
setIndicatorPosition( setIndicatorPosition(
AnimationUtils.lerp(startLeft, targetLeft, fraction), AnimationUtils.lerp(startTop, targetTop, fraction),
AnimationUtils.lerp(startRight, targetRight, fraction)); AnimationUtils.lerp(startBottom, targetBottom, fraction));
} }
}); });
animator.addListener(new AnimatorListenerAdapter() { animator.addListener(new AnimatorListenerAdapter() {
@ -2041,14 +2044,10 @@ public class VerticalTabLayout extends ScrollView {
public void draw(Canvas canvas) { public void draw(Canvas canvas) {
super.draw(canvas); super.draw(canvas);
// Thick colored underline below the current selection // Thick colored line at the left side of the current selection
if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) { if (mIndicatorTop >= 0 && mIndicatorBottom > mIndicatorTop) {
canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight, canvas.drawRect(0, mIndicatorTop,
mIndicatorRight, getHeight(), mSelectedIndicatorPaint); mSelectedIndicatorHeight, mIndicatorBottom, mSelectedIndicatorPaint);
// ADD: Try the VERTICAL
canvas.drawRect(mIndicatorLeft, getWidth() - mSelectedIndicatorHeight,
mIndicatorRight, getWidth(), mSelectedIndicatorPaint);
} }
} }
} }