package it.sephiroth.android.library.bottomnavigation;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import it.sephiroth.android.library.bottonnavigation.R;
import static android.util.Log.INFO;
import static android.util.Log.VERBOSE;
import static it.sephiroth.android.library.bottomnavigation.MiscUtils.log;
/**
* Created by alessandro on 4/3/16 at 10:55 PM.
* Project: MaterialBottomNavigation
*/
@SuppressLint ("ViewConstructor")
public class BottomNavigationShiftingItemView extends BottomNavigationItemViewAbstract {
private static final String TAG = BottomNavigationShiftingItemView.class.getSimpleName();
private final int paddingTop;
private final int paddingBottomActive;
private final int iconSize;
private final int paddingBottomInactive;
private final int textSize;
private int centerY;
private final float alphaActive;
private final float alphaInactive;
private final float alphaDisabled;
private final Interpolator interpolator = new DecelerateInterpolator();
private float textWidth;
private long animationDuration;
private final int colorActive;
private final int colorInactive;
private final int colorDisabled;
private float textX;
private int textY;
public BottomNavigationShiftingItemView(final BottomNavigation parent, boolean expanded, final MenuParser.Menu menu) {
super(parent, expanded, menu);
this.paddingTop = getResources().getDimensionPixelSize(R.dimen.bbn_shifting_item_padding_top);
this.paddingBottomActive = getResources().getDimensionPixelSize(R.dimen.bbn_shifting_item_padding_bottom_active);
this.paddingBottomInactive = getResources().getDimensionPixelSize(R.dimen.bbn_shifting_item_padding_bottom_inactive);
this.iconSize = getResources().getDimensionPixelSize(R.dimen.bbn_shifting_item_icon_size);
this.textSize = getResources().getDimensionPixelSize(R.dimen.bbn_shifting_text_size);
this.animationDuration = menu.getItemAnimationDuration();
this.colorActive = menu.getColorActive();
this.colorInactive = menu.getColorInactive();
this.colorDisabled = menu.getColorDisabled();
this.alphaInactive = Color.alpha(this.colorInactive) / ALPHA_MAX;
this.alphaDisabled = Color.alpha(this.colorDisabled) / ALPHA_MAX;
this.alphaActive = Math.max((float) Color.alpha(colorActive) / ALPHA_MAX, alphaInactive);
this.centerY = expanded ? paddingTop : paddingBottomInactive;
this.textPaint.setHinting(Paint.HINTING_ON);
this.textPaint.setLinearText(true);
this.textPaint.setSubpixelText(true);
this.textPaint.setTextSize(textSize);
this.textPaint.setColor(colorActive);
if (!expanded) {
this.textPaint.setAlpha(0);
}
if (BottomNavigation.DEBUG) {
log(TAG, VERBOSE, "colors: %x, %x, %x", colorDisabled, colorInactive, colorActive);
log(TAG, VERBOSE, "alphas: %g, %g, %g", alphaDisabled, alphaInactive, alphaActive);
}
}
@Override
public void setEnabled(final boolean enabled) {
super.setEnabled(enabled);
textPaint.setAlpha(
(int) ((isExpanded() ? (enabled ? alphaActive : alphaDisabled) : 0) * ALPHA_MAX));
if (null != icon) {
updateLayoutOnAnimation(getLayoutParams().width, 1, isExpanded());
}
requestLayout();
}
@Override
protected void onStatusChanged(final boolean expanded, final int size, final boolean animate) {
log(TAG, INFO, "[%s] onStatusChanged(%b, %d)", getItem().getTitle(), expanded, size);
if (!animate) {
updateLayoutOnAnimation(size, 1, expanded);
setCenterY(expanded ? paddingTop : paddingBottomInactive);
return;
}
final AnimatorSet set = new AnimatorSet();
set.setDuration(animationDuration * 2);
set.setInterpolator(interpolator);
final ValueAnimator animator1 = ValueAnimator.ofInt(getLayoutParams().width, size);
final ValueAnimator animator2 = ObjectAnimator.ofInt(this, "centerY", expanded ? paddingBottomInactive : paddingTop,
expanded ? paddingTop : paddingBottomInactive
);
animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(final ValueAnimator animation) {
int size = (int) animation.getAnimatedValue();
final float fraction = animation.getAnimatedFraction();
updateLayoutOnAnimation(size, fraction, expanded);
}
});
set.playTogether(animator1, animator2);
set.start();
}
private void updateLayoutOnAnimation(final int size, final float fraction, final boolean expanded) {
getLayoutParams().width = size;
final int color;
final boolean enabled = isEnabled();
final int srcColor = enabled ? (expanded ? colorInactive : colorActive) : colorDisabled;
final int dstColor = enabled ? (expanded ? colorActive : colorInactive) : colorDisabled;
final float srcAlpha = enabled ? alphaInactive : alphaDisabled;
final float dstAlpha = enabled ? alphaActive : alphaDisabled;
if (expanded) {
color = (Integer) evaluator.evaluate(fraction, srcColor, dstColor);
icon.setAlpha((int) ((srcAlpha + (fraction * (dstAlpha - srcAlpha))) * ALPHA_MAX));
textPaint.setAlpha((int) (((fraction * (dstAlpha))) * ALPHA_MAX));
} else {
color = (Integer) evaluator.evaluate(fraction, srcColor, dstColor);
final float alpha = 1.0F - fraction;
icon.setAlpha((int) ((srcAlpha + (alpha * (dstAlpha - srcAlpha))) * ALPHA_MAX));
textPaint.setAlpha((int) (((alpha * (dstAlpha))) * ALPHA_MAX));
}
icon.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
}
private void measureText() {
this.textWidth = textPaint.measureText(getItem().getTitle());
}
@Override
protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (null == this.icon) {
this.icon = getItem().getIcon(getContext()).mutate();
icon.setBounds(0, 0, iconSize, iconSize);
icon.setColorFilter(
isExpanded() ? (isEnabled() ? colorActive : colorDisabled) : (isEnabled() ? colorInactive : colorDisabled),
PorterDuff
.Mode
.SRC_ATOP
);
icon.setAlpha(
(int) (isExpanded() ? (isEnabled() ? alphaActive : alphaDisabled) * ALPHA_MAX
: (isEnabled() ? alphaInactive : alphaDisabled) * ALPHA_MAX));
}
if (textDirty) {
measureText();
textDirty = false;
}
if (changed) {
int w = right - left;
int h = bottom - top;
int centerX = (w - iconSize) / 2;
this.textY = h - paddingBottomActive;
this.textX = (w - textWidth) / 2;
icon.setBounds(centerX, centerY, centerX + iconSize, centerY + iconSize);
}
}
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
icon.draw(canvas);
canvas.drawText(
getItem().getTitle(),
textX,
textY,
textPaint
);
drawBadge(canvas);
}
@SuppressWarnings ("unused")
@proguard.annotation.Keep
public int getCenterY() {
return centerY;
}
@SuppressWarnings ("unused")
@proguard.annotation.Keep
public void setCenterY(int value) {
centerY = value;
requestLayout();
}
}