mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1055606 - Animate tab strip when tabs added added or removed (r=mcomella)
This commit is contained in:
parent
714140e316
commit
bb787d958f
@ -82,9 +82,7 @@ public class TabStrip extends ThemedLinearLayout {
|
||||
switch (msg) {
|
||||
case RESTORED:
|
||||
case ADDED:
|
||||
// Refresh the list to make sure the new tab is
|
||||
// added in the right position.
|
||||
tabStripView.refreshTabs();
|
||||
tabStripView.addTab(tab);
|
||||
break;
|
||||
|
||||
case CLOSED:
|
||||
|
@ -11,11 +11,16 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
||||
|
||||
import com.nineoldandroids.animation.Animator;
|
||||
import com.nineoldandroids.animation.AnimatorSet;
|
||||
import com.nineoldandroids.animation.ObjectAnimator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -27,6 +32,10 @@ import org.mozilla.gecko.widget.TwoWayView;
|
||||
public class TabStripView extends TwoWayView {
|
||||
private static final String LOGTAG = "GeckoTabStrip";
|
||||
|
||||
private static final int ANIM_TIME_MS = 200;
|
||||
private static final AccelerateDecelerateInterpolator ANIM_INTERPOLATOR =
|
||||
new AccelerateDecelerateInterpolator();
|
||||
|
||||
private final TabStripAdapter adapter;
|
||||
private final Drawable divider;
|
||||
|
||||
@ -71,14 +80,110 @@ public class TabStripView extends TwoWayView {
|
||||
setItemChecked(selected, true);
|
||||
}
|
||||
|
||||
private void updateSelectedPosition() {
|
||||
private void updateSelectedPosition(boolean ensureVisible) {
|
||||
final int selected = getPositionForSelectedTab();
|
||||
if (selected != -1) {
|
||||
updateSelectedStyle(selected);
|
||||
ensurePositionIsVisible(selected);
|
||||
|
||||
if (ensureVisible) {
|
||||
ensurePositionIsVisible(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void animateRemoveTab(Tab removedTab) {
|
||||
final int removedPosition = adapter.getPositionForTab(removedTab);
|
||||
|
||||
final View removedView = getViewForTab(removedTab);
|
||||
|
||||
// The removed position might not have a matching child view
|
||||
// when it's not within the visible range of positions in the strip.
|
||||
if (removedView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't animate the removed child view (it just disappears)
|
||||
// but we still need its size of animate all affected children
|
||||
// within the visible viewport.
|
||||
final int removedSize = removedView.getWidth() + getItemMargin();
|
||||
|
||||
getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
|
||||
final int firstPosition = getFirstVisiblePosition();
|
||||
final List<Animator> childAnimators = new ArrayList<Animator>();
|
||||
|
||||
final int childCount = getChildCount();
|
||||
for (int i = removedPosition - firstPosition; i < childCount; i++) {
|
||||
final View child = getChildAt(i);
|
||||
|
||||
// TODO: optimize with Valueresolver
|
||||
final ObjectAnimator animator =
|
||||
ObjectAnimator.ofFloat(child, "translationX", removedSize, 0);
|
||||
childAnimators.add(animator);
|
||||
}
|
||||
|
||||
final AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(childAnimators);
|
||||
animatorSet.setDuration(ANIM_TIME_MS);
|
||||
animatorSet.setInterpolator(ANIM_INTERPOLATOR);
|
||||
animatorSet.start();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void animateNewTab(Tab newTab) {
|
||||
final int newPosition = adapter.getPositionForTab(newTab);
|
||||
if (newPosition < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
|
||||
final int firstPosition = getFirstVisiblePosition();
|
||||
|
||||
final View newChild = getChildAt(newPosition - firstPosition);
|
||||
if (newChild == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final List<Animator> childAnimators = new ArrayList<Animator>();
|
||||
childAnimators.add(
|
||||
ObjectAnimator.ofFloat(newChild, "translationY", newChild.getHeight(), 0));
|
||||
|
||||
// This will momentaneously add a gap on the right side
|
||||
// because TwoWayView doesn't provide APIs to control
|
||||
// view recycling programatically to handle these transitory
|
||||
// states in the container during animations.
|
||||
|
||||
final int tabSize = newChild.getWidth();
|
||||
final int newIndex = newPosition - firstPosition;
|
||||
final int childCount = getChildCount();
|
||||
for (int i = newIndex + 1; i < childCount; i++) {
|
||||
final View child = getChildAt(i);
|
||||
|
||||
childAnimators.add(
|
||||
ObjectAnimator.ofFloat(child, "translationX", -tabSize, 0));
|
||||
}
|
||||
|
||||
final AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(childAnimators);
|
||||
animatorSet.setDuration(ANIM_TIME_MS);
|
||||
animatorSet.setInterpolator(ANIM_INTERPOLATOR);
|
||||
animatorSet.start();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void ensurePositionIsVisible(final int position) {
|
||||
getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
|
||||
@Override
|
||||
@ -111,16 +216,24 @@ public class TabStripView extends TwoWayView {
|
||||
}
|
||||
|
||||
adapter.refresh(tabs);
|
||||
updateSelectedPosition();
|
||||
updateSelectedPosition(true);
|
||||
}
|
||||
|
||||
void clearTabs() {
|
||||
adapter.clear();
|
||||
}
|
||||
|
||||
void addTab(Tab tab) {
|
||||
// Refresh the list to make sure the new tab is
|
||||
// added in the right position.
|
||||
refreshTabs();
|
||||
animateNewTab(tab);
|
||||
}
|
||||
|
||||
void removeTab(Tab tab) {
|
||||
animateRemoveTab(tab);
|
||||
adapter.removeTab(tab);
|
||||
updateSelectedPosition();
|
||||
updateSelectedPosition(false);
|
||||
}
|
||||
|
||||
void selectTab(Tab tab) {
|
||||
@ -128,7 +241,7 @@ public class TabStripView extends TwoWayView {
|
||||
isPrivate = tab.isPrivate();
|
||||
refreshTabs();
|
||||
} else {
|
||||
updateSelectedPosition();
|
||||
updateSelectedPosition(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user