Fix FloatingToolbar flicker in reaction to text cursor blink.

1. Reposition the toolbar on predraw only when positioning has changed.
2. Update the toolbar popup's position only if the content rect changed.
3. Fix FloatingToolbarPopup.cancelOverflowAnimations().
   The previous implementation wasn't actually cancelling the animation.

(1) is enough to fix the bug. But (2) and (3) fix issues in the
toolbar directly related to this bug.

Bug: 22039189
Change-Id: I84ec793d788f9402a1f8635e68e3344746f6af07
This commit is contained in:
Abodunrinwa Toki
2015-06-25 21:33:51 -07:00
parent 869c230c14
commit c107b0ecdc
2 changed files with 39 additions and 22 deletions

View File

@@ -30,6 +30,8 @@ import com.android.internal.util.Preconditions;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.widget.FloatingToolbar;
import java.util.Arrays;
public class FloatingActionMode extends ActionMode {
private static final int MAX_HIDE_DURATION = 3000;
@@ -42,7 +44,9 @@ public class FloatingActionMode extends ActionMode {
private final Rect mContentRectOnWindow;
private final Rect mPreviousContentRectOnWindow;
private final int[] mViewPosition;
private final int[] mPreviousViewPosition;
private final Rect mViewRect;
private final Rect mPreviousViewRect;
private final Rect mScreenRect;
private final View mOriginatingView;
private final int mBottomAllowance;
@@ -75,7 +79,9 @@ public class FloatingActionMode extends ActionMode {
mContentRectOnWindow = new Rect();
mPreviousContentRectOnWindow = new Rect();
mViewPosition = new int[2];
mPreviousViewPosition = new int[2];
mViewRect = new Rect();
mPreviousViewRect = new Rect();
mScreenRect = new Rect();
mOriginatingView = Preconditions.checkNotNull(originatingView);
mOriginatingView.getLocationInWindow(mViewPosition);
@@ -129,9 +135,17 @@ public class FloatingActionMode extends ActionMode {
public void updateViewLocationInWindow() {
checkToolbarInitialized();
mOriginatingView.getLocationInWindow(mViewPosition);
mOriginatingView.getGlobalVisibleRect(mViewRect);
repositionToolbar();
if (!Arrays.equals(mViewPosition, mPreviousViewPosition)
|| !mViewRect.equals(mPreviousViewRect)) {
repositionToolbar();
mPreviousViewPosition[0] = mViewPosition[0];
mPreviousViewPosition[1] = mViewPosition[1];
mPreviousViewRect.set(mViewRect);
}
}
private void repositionToolbar() {

View File

@@ -85,6 +85,7 @@ public final class FloatingToolbar {
private final FloatingToolbarPopup mPopup;
private final Rect mContentRect = new Rect();
private final Rect mPreviousContentRect = new Rect();
private Menu mMenu;
private List<Object> mShowingMenuItems = new ArrayList<Object>();
@@ -178,11 +179,13 @@ public final class FloatingToolbar {
mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
mShowingMenuItems = getShowingMenuItemsReferences(menuItems);
}
mPopup.updateCoordinates(mContentRect);
if (!mPopup.isShowing()) {
mPopup.show(mContentRect);
} else if (!mPreviousContentRect.equals(mContentRect)) {
mPopup.updateCoordinates(mContentRect);
}
mWidthChanged = false;
mPreviousContentRect.set(mContentRect);
return this;
}
@@ -318,24 +321,8 @@ public final class FloatingToolbar {
};
private final AnimatorSet mDismissAnimation;
private final AnimatorSet mHideAnimation;
private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true) {
@Override
public void cancel() {
if (hasStarted() && !hasEnded()) {
super.cancel();
setOverflowPanelAsContent();
}
}
};
private final AnimationSet mCloseOverflowAnimation = new AnimationSet(true) {
@Override
public void cancel() {
if (hasStarted() && !hasEnded()) {
super.cancel();
setMainPanelAsContent();
}
}
};
private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true);
private final AnimationSet mCloseOverflowAnimation = new AnimationSet(true);
private final Runnable mOpenOverflow = new Runnable() {
@Override
@@ -657,8 +644,24 @@ public final class FloatingToolbar {
}
private void cancelOverflowAnimations() {
mOpenOverflowAnimation.cancel();
mCloseOverflowAnimation.cancel();
if (mOpenOverflowAnimation.hasStarted()
&& !mOpenOverflowAnimation.hasEnded()) {
// Remove the animation listener, stop the animation,
// then trigger the lister explicitly so it is not posted
// to the message queue.
mOpenOverflowAnimation.setAnimationListener(null);
mContentContainer.clearAnimation();
mOnOverflowOpened.onAnimationEnd(null);
}
if (mCloseOverflowAnimation.hasStarted()
&& !mCloseOverflowAnimation.hasEnded()) {
// Remove the animation listener, stop the animation,
// then trigger the lister explicitly so it is not posted
// to the message queue.
mCloseOverflowAnimation.setAnimationListener(null);
mContentContainer.clearAnimation();
mOnOverflowClosed.onAnimationEnd(null);
}
}
/**