summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml2
-rw-r--r--java/com/android/dialer/app/AndroidManifest.xml2
-rw-r--r--java/com/android/dialer/assisteddialing/AndroidManifest.xml4
-rw-r--r--java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml4
-rw-r--r--java/com/android/dialer/binary/google/AndroidManifest.xml2
-rw-r--r--java/com/android/dialer/shortcuts/AndroidManifest.xml2
-rw-r--r--java/com/android/dialer/smartdial/LatinSmartDialMap.java1
-rw-r--r--java/com/android/incallui/AndroidManifest.xml2
-rw-r--r--java/com/android/incallui/NewReturnToCallController.java8
-rw-r--r--java/com/android/incallui/autoresizetext/AndroidManifest.xml2
-rw-r--r--java/com/android/incallui/video/protocol/AndroidManifest.xml4
-rw-r--r--java/com/android/newbubble/NewBubble.java259
-rw-r--r--java/com/android/newbubble/RoundedRectRevealOutlineProvider.java105
-rw-r--r--java/com/android/newbubble/res/layout/new_bubble_base.xml1
-rw-r--r--java/com/android/voicemail/AndroidManifest.xml2
15 files changed, 272 insertions, 128 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d1585e039..b459a44c0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -21,7 +21,7 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="26"/>
+ android:targetSdkVersion="27"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
diff --git a/java/com/android/dialer/app/AndroidManifest.xml b/java/com/android/dialer/app/AndroidManifest.xml
index 12abaa6a9..3652c95ca 100644
--- a/java/com/android/dialer/app/AndroidManifest.xml
+++ b/java/com/android/dialer/app/AndroidManifest.xml
@@ -56,7 +56,7 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="26"/>
+ android:targetSdkVersion="27"/>
<application android:theme="@style/Theme.AppCompat">
diff --git a/java/com/android/dialer/assisteddialing/AndroidManifest.xml b/java/com/android/dialer/assisteddialing/AndroidManifest.xml
index 6625dff07..a19af3b72 100644
--- a/java/com/android/dialer/assisteddialing/AndroidManifest.xml
+++ b/java/com/android/dialer/assisteddialing/AndroidManifest.xml
@@ -17,6 +17,6 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="24"/>
+ android:targetSdkVersion="27"/>
-</manifest> \ No newline at end of file
+</manifest>
diff --git a/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml b/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml
index 5266b1376..3e79de38a 100644
--- a/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml
+++ b/java/com/android/dialer/assisteddialing/ui/AndroidManifest.xml
@@ -17,7 +17,7 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="24"/>
+ android:targetSdkVersion="27"/>
<application>
<activity
@@ -32,4 +32,4 @@
</activity>
</application>
-</manifest> \ No newline at end of file
+</manifest>
diff --git a/java/com/android/dialer/binary/google/AndroidManifest.xml b/java/com/android/dialer/binary/google/AndroidManifest.xml
index 018c2a73c..86f6bcb81 100644
--- a/java/com/android/dialer/binary/google/AndroidManifest.xml
+++ b/java/com/android/dialer/binary/google/AndroidManifest.xml
@@ -21,7 +21,7 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="26"/>
+ android:targetSdkVersion="27"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
diff --git a/java/com/android/dialer/shortcuts/AndroidManifest.xml b/java/com/android/dialer/shortcuts/AndroidManifest.xml
index 15f77944e..117005841 100644
--- a/java/com/android/dialer/shortcuts/AndroidManifest.xml
+++ b/java/com/android/dialer/shortcuts/AndroidManifest.xml
@@ -18,7 +18,7 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="26"/>
+ android:targetSdkVersion="27"/>
<application android:theme="@style/Theme.AppCompat">
diff --git a/java/com/android/dialer/smartdial/LatinSmartDialMap.java b/java/com/android/dialer/smartdial/LatinSmartDialMap.java
index c512c5d4a..656fd12b2 100644
--- a/java/com/android/dialer/smartdial/LatinSmartDialMap.java
+++ b/java/com/android/dialer/smartdial/LatinSmartDialMap.java
@@ -16,6 +16,7 @@
package com.android.dialer.smartdial;
+/** {@link SmartDialMap} for Latin based T9 dialpad searching. */
public class LatinSmartDialMap implements SmartDialMap {
private static final char[] LATIN_LETTERS_TO_DIGITS = {
diff --git a/java/com/android/incallui/AndroidManifest.xml b/java/com/android/incallui/AndroidManifest.xml
index d854a7fc8..af9970056 100644
--- a/java/com/android/incallui/AndroidManifest.xml
+++ b/java/com/android/incallui/AndroidManifest.xml
@@ -19,7 +19,7 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="26"/>
+ android:targetSdkVersion="27"/>
<uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
<!-- We use this to disable the status bar buttons of home, back and recent
diff --git a/java/com/android/incallui/NewReturnToCallController.java b/java/com/android/incallui/NewReturnToCallController.java
index 95da1c65e..d3d993027 100644
--- a/java/com/android/incallui/NewReturnToCallController.java
+++ b/java/com/android/incallui/NewReturnToCallController.java
@@ -219,11 +219,15 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
}
private void onPhotoAvatarReceived(@NonNull Drawable photo) {
- bubble.updatePhotoAvatar(photo);
+ if (bubble != null) {
+ bubble.updatePhotoAvatar(photo);
+ }
}
private void onLetterTileAvatarReceived(@NonNull Drawable photo) {
- bubble.updateAvatar(photo);
+ if (bubble != null) {
+ bubble.updateAvatar(photo);
+ }
}
private NewBubbleInfo generateBubbleInfo() {
diff --git a/java/com/android/incallui/autoresizetext/AndroidManifest.xml b/java/com/android/incallui/autoresizetext/AndroidManifest.xml
index 1b5c19355..e26670e52 100644
--- a/java/com/android/incallui/autoresizetext/AndroidManifest.xml
+++ b/java/com/android/incallui/autoresizetext/AndroidManifest.xml
@@ -19,7 +19,7 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="26"/>
+ android:targetSdkVersion="27"/>
<application />
</manifest>
diff --git a/java/com/android/incallui/video/protocol/AndroidManifest.xml b/java/com/android/incallui/video/protocol/AndroidManifest.xml
index cfb6b27ad..6f6558278 100644
--- a/java/com/android/incallui/video/protocol/AndroidManifest.xml
+++ b/java/com/android/incallui/video/protocol/AndroidManifest.xml
@@ -18,5 +18,5 @@
package="com.android.incallui.video.protocol">
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="26"/>
-</manifest> \ No newline at end of file
+ android:targetSdkVersion="27"/>
+</manifest>
diff --git a/java/com/android/newbubble/NewBubble.java b/java/com/android/newbubble/NewBubble.java
index 34a9585c1..d13952ba5 100644
--- a/java/com/android/newbubble/NewBubble.java
+++ b/java/com/android/newbubble/NewBubble.java
@@ -25,8 +25,8 @@ import android.annotation.SuppressLint;
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Path;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -38,7 +38,6 @@ import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.v4.graphics.ColorUtils;
import android.support.v4.os.BuildCompat;
-import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.transition.TransitionManager;
import android.transition.TransitionValues;
@@ -55,6 +54,7 @@ import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.ImageView;
@@ -87,8 +87,13 @@ public class NewBubble {
// This ensures the new window has had time to draw first.
private static final int WINDOW_REDRAW_DELAY_MILLIS = 50;
+ private static final int EXPAND_AND_COLLAPSE_ANIMATION_DURATION = 200;
+
private static Boolean canShowBubblesForTesting = null;
+ private final AccelerateDecelerateInterpolator accelerateDecelerateInterpolator =
+ new AccelerateDecelerateInterpolator();
+
private final Context context;
private final WindowManager windowManager;
@@ -233,7 +238,12 @@ public class NewBubble {
}
setPrimaryButtonAccessibilityAction(
context.getString(R.string.a11y_bubble_primary_button_collapse_action));
+
viewHolder.setDrawerVisibility(View.INVISIBLE);
+ viewHolder.getArrow().setVisibility(View.INVISIBLE);
+ // No click during animation to avoid jank.
+ viewHolder.setPrimaryButtonClickable(false);
+
View expandedView = viewHolder.getExpandedView();
expandedView
.getViewTreeObserver()
@@ -247,47 +257,46 @@ public class NewBubble {
savedYPosition = windowParams.y;
}
- // Calculate the move-to-middle distance
+ // Animation 1: animate x-move and y-move (if needed) together
int deltaX =
(int) viewHolder.getRoot().findViewById(R.id.bubble_primary_container).getX();
- float k = (float) moveUpDistance / deltaX;
+ float k = -(float) moveUpDistance / deltaX;
if (isDrawingFromRight()) {
deltaX = -deltaX;
}
-
- // Do X-move and Y-move together
-
- final int startX = windowParams.x - deltaX;
- final int startY = windowParams.y;
- ValueAnimator animator = ValueAnimator.ofFloat(startX, windowParams.x);
- animator.setInterpolator(new LinearOutSlowInInterpolator());
- animator.addUpdateListener(
- (valueAnimator) -> {
- // Update windowParams and the root layout.
- // We can't do ViewPropertyAnimation since it clips children.
- float newX = (float) valueAnimator.getAnimatedValue();
- if (moveUpDistance != 0) {
- windowParams.y = startY - (int) (Math.abs(newX - (float) startX) * k);
- }
- windowParams.x = (int) newX;
- windowManager.updateViewLayout(viewHolder.getRoot(), windowParams);
- });
- animator.addListener(
+ ValueAnimator xValueAnimator =
+ createBubbleMoveAnimator(
+ windowParams.x - deltaX, windowParams.x, windowParams.y, k);
+
+ // Show expanded view
+ expandedView.setVisibility(View.VISIBLE);
+
+ // Animator 2: reveal expanded view from top left or top right
+ View expandedMenu = viewHolder.getRoot().findViewById(R.id.bubble_expanded_menu);
+ ValueAnimator revealAnim =
+ createOpenCloseOutlineProvider(expandedMenu)
+ .createRevealAnimator(expandedMenu, false);
+ revealAnim.setInterpolator(accelerateDecelerateInterpolator);
+
+ // Animator 3: expanded view fade in
+ Animator fadeIn = ObjectAnimator.ofFloat(expandedView, "alpha", 0, 1);
+ fadeIn.setInterpolator(accelerateDecelerateInterpolator);
+
+ // Play all animation together
+ AnimatorSet expandAnimatorSet = new AnimatorSet();
+ expandAnimatorSet.playTogether(revealAnim, fadeIn, xValueAnimator);
+ expandAnimatorSet.setDuration(EXPAND_AND_COLLAPSE_ANIMATION_DURATION);
+ expandAnimatorSet.addListener(
new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- // Show expanded view
- expandedView.setVisibility(View.VISIBLE);
- expandedView.setTranslationY(-expandedView.getHeight());
- expandedView.setAlpha(0);
- expandedView
- .animate()
- .setInterpolator(new LinearOutSlowInInterpolator())
- .translationY(0)
- .alpha(1);
+ // Show arrow after animation
+ viewHolder.getArrow().setVisibility(View.VISIBLE);
+ // Safe to click primary button now
+ viewHolder.setPrimaryButtonClickable(true);
}
});
- animator.start();
+ expandAnimatorSet.start();
expandedView.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
@@ -315,89 +324,79 @@ public class NewBubble {
if (isUserAction && collapseEndAction == CollapseEnd.NOTHING) {
logBasicOrCallImpression(DialerImpression.Type.BUBBLE_COLLAPSE_BY_USER);
}
+
setPrimaryButtonAccessibilityAction(
context.getString(R.string.a11y_bubble_primary_button_expand_action));
- // Animate expanded view to move from its position to above primary button and hide
- collapseAnimation =
- expandedView
- .animate()
- .translationY(-expandedView.getHeight())
- .alpha(0)
- .setInterpolator(new FastOutLinearInInterpolator())
- .withEndAction(
- () -> {
- collapseAnimation = null;
- expanded = false;
- if (textShowing) {
- // Will do resize once the text is done.
- return;
- }
+ // Hide arrow before animation
+ viewHolder.getArrow().setVisibility(View.INVISIBLE);
+
+ // No click during animation to avoid jank.
+ viewHolder.setPrimaryButtonClickable(false);
- // Set drawer visibility to INVISIBLE instead of GONE to keep primary button fixed
- viewHolder.setDrawerVisibility(View.INVISIBLE);
-
- // Do X-move and Y-move together
- int deltaX =
- (int) viewHolder.getRoot().findViewById(R.id.bubble_primary_container).getX();
- int startX = windowParams.x;
- int startY = windowParams.y;
- float k =
- (savedYPosition != -1 && shouldRecoverYPosition)
- ? (savedYPosition - startY) / (float) deltaX
- : 0;
- Path path = new Path();
- path.moveTo(windowParams.x, windowParams.y);
- path.lineTo(
- windowParams.x - deltaX,
- (savedYPosition != -1 && shouldRecoverYPosition)
- ? savedYPosition
- : windowParams.y);
- // The position is not useful after collapse
- savedYPosition = -1;
-
- ValueAnimator animator = ValueAnimator.ofFloat(startX, startX - deltaX);
- animator.setInterpolator(new LinearOutSlowInInterpolator());
- animator.addUpdateListener(
- (valueAnimator) -> {
- // Update windowParams and the root layout.
- // We can't do ViewPropertyAnimation since it clips children.
- float newX = (float) valueAnimator.getAnimatedValue();
- if (k != 0) {
- windowParams.y = startY + (int) (Math.abs(newX - (float) startX) * k);
- }
- windowParams.x = (int) newX;
- windowManager.updateViewLayout(viewHolder.getRoot(), windowParams);
- });
- animator.addListener(
- new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- // If collapse on the right side, the primary button move left a bit after
- // drawer
- // visibility becoming GONE. To avoid it, we create a new ViewHolder.
- replaceViewHolder();
- }
- });
- animator.start();
-
- // If this collapse was to come before a hide, do it now.
- if (collapseEndAction == CollapseEnd.HIDE) {
- hide();
+ // Calculate animation values
+ int deltaX = (int) viewHolder.getRoot().findViewById(R.id.bubble_primary_container).getX();
+ float k =
+ (savedYPosition != -1 && shouldRecoverYPosition)
+ ? (savedYPosition - windowParams.y) / (float) deltaX
+ : 0;
+ // The position is not useful after collapse
+ savedYPosition = -1;
+
+ // Animation 1: animate x-move and y-move (if needed) together
+ ValueAnimator xValueAnimator =
+ createBubbleMoveAnimator(windowParams.x, windowParams.x - deltaX, windowParams.y, k);
+
+ // Animator 2: hide expanded view to top left or top right
+ View expandedMenu = viewHolder.getRoot().findViewById(R.id.bubble_expanded_menu);
+ ValueAnimator revealAnim =
+ createOpenCloseOutlineProvider(expandedMenu).createRevealAnimator(expandedMenu, true);
+ revealAnim.setInterpolator(accelerateDecelerateInterpolator);
+
+ // Animator 3: expanded view fade out
+ Animator fadeOut = ObjectAnimator.ofFloat(expandedView, "alpha", 1, 0);
+ fadeOut.setInterpolator(accelerateDecelerateInterpolator);
+
+ // Play all animation together
+ AnimatorSet collapseAnimatorSet = new AnimatorSet();
+ collapseAnimatorSet.setDuration(EXPAND_AND_COLLAPSE_ANIMATION_DURATION);
+ collapseAnimatorSet.playTogether(revealAnim, fadeOut, xValueAnimator);
+ collapseAnimatorSet.addListener(
+ new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ collapseAnimation = null;
+ expanded = false;
+
+ if (textShowing) {
+ // Will do resize once the text is done.
+ return;
+ }
+
+ // If this collapse was to come before a hide, do it now.
+ if (collapseEndAction == CollapseEnd.HIDE) {
+ hide();
+ }
+ collapseEndAction = CollapseEnd.NOTHING;
+
+ // If collapse on the right side, the primary button move left a bit after drawer
+ // visibility becoming GONE. To avoid it, we create a new ViewHolder.
+ // It also set primary button clickable back to true, so no need to reset manually.
+ replaceViewHolder();
+
+ // Resume normal gravity after any resizing is done.
+ handler.postDelayed(
+ () -> {
+ overrideGravity = null;
+ if (!viewHolder.isMoving()) {
+ viewHolder.undoGravityOverride();
}
- collapseEndAction = CollapseEnd.NOTHING;
-
- // Resume normal gravity after any resizing is done.
- handler.postDelayed(
- () -> {
- overrideGravity = null;
- if (!viewHolder.isMoving()) {
- viewHolder.undoGravityOverride();
- }
- },
- // Need to wait twice as long for resize and layout
- WINDOW_REDRAW_DELAY_MILLIS * 2);
- });
+ },
+ // Need to wait twice as long for resize and layout
+ WINDOW_REDRAW_DELAY_MILLIS * 2);
+ }
+ });
+ collapseAnimatorSet.start();
}
/**
@@ -917,18 +916,45 @@ public class NewBubble {
});
}
+ private RoundedRectRevealOutlineProvider createOpenCloseOutlineProvider(View view) {
+ int startRectX = isDrawingFromRight() ? view.getMeasuredWidth() : 0;
+ Rect startRect = new Rect(startRectX, 0, startRectX, 0);
+ Rect endRect = new Rect(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
+
+ float bubbleRadius = context.getResources().getDimension(R.dimen.bubble_radius);
+ return new RoundedRectRevealOutlineProvider(bubbleRadius, bubbleRadius, startRect, endRect);
+ }
+
+ private ValueAnimator createBubbleMoveAnimator(int startX, int endX, int startY, float k) {
+ ValueAnimator xValueAnimator = ValueAnimator.ofFloat(startX, endX);
+ xValueAnimator.setInterpolator(new LinearOutSlowInInterpolator());
+ xValueAnimator.addUpdateListener(
+ (valueAnimator) -> {
+ // Update windowParams and the root layout.
+ // We can't do ViewPropertyAnimation since it clips children.
+ float newX = (float) valueAnimator.getAnimatedValue();
+ if (k != 0) {
+ windowParams.y = startY + (int) (Math.abs(newX - (float) startX) * k);
+ }
+ windowParams.x = (int) newX;
+ windowManager.updateViewLayout(viewHolder.getRoot(), windowParams);
+ });
+ return xValueAnimator;
+ }
+
@VisibleForTesting
class ViewHolder {
public static final int CHILD_INDEX_AVATAR_AND_ICON = 0;
public static final int CHILD_INDEX_TEXT = 1;
- private final NewMoveHandler moveHandler;
+ private NewMoveHandler moveHandler;
private final NewWindowRoot root;
private final ViewAnimator primaryButton;
private final ImageView primaryIcon;
private final ImageView primaryAvatar;
private final TextView primaryText;
+ private final View arrow;
private final NewCheckableButton fullScreenButton;
private final NewCheckableButton muteButton;
@@ -946,6 +972,7 @@ public class NewBubble {
primaryAvatar = contentView.findViewById(R.id.bubble_icon_avatar);
primaryIcon = contentView.findViewById(R.id.bubble_icon_primary);
primaryText = contentView.findViewById(R.id.bubble_text);
+ arrow = contentView.findViewById(R.id.bubble_triangle);
fullScreenButton = contentView.findViewById(R.id.bubble_button_full_screen);
muteButton = contentView.findViewById(R.id.bubble_button_mute);
@@ -985,8 +1012,10 @@ public class NewBubble {
muteButton.setClickable(clickable);
audioRouteButton.setClickable(clickable);
endCallButton.setClickable(clickable);
+ setPrimaryButtonClickable(clickable);
+ }
- // For primaryButton
+ private void setPrimaryButtonClickable(boolean clickable) {
moveHandler.setClickable(clickable);
}
@@ -1024,6 +1053,10 @@ public class NewBubble {
return expandedView;
}
+ public View getArrow() {
+ return arrow;
+ }
+
public NewCheckableButton getFullScreenButton() {
return fullScreenButton;
}
diff --git a/java/com/android/newbubble/RoundedRectRevealOutlineProvider.java b/java/com/android/newbubble/RoundedRectRevealOutlineProvider.java
new file mode 100644
index 000000000..d204e0f1c
--- /dev/null
+++ b/java/com/android/newbubble/RoundedRectRevealOutlineProvider.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.newbubble;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+/**
+ * A {@link ViewOutlineProvider} that provides an outline that interpolates between two radii and
+ * two {@link Rect}s.
+ *
+ * <p>An example usage of this provider is an outline that starts out as a circle and ends as a
+ * rounded rectangle.
+ */
+public class RoundedRectRevealOutlineProvider extends ViewOutlineProvider {
+ private final float mStartRadius;
+ private final float mEndRadius;
+
+ private final Rect mStartRect;
+ private final Rect mEndRect;
+
+ private final Rect mOutline;
+ private float mOutlineRadius;
+
+ public RoundedRectRevealOutlineProvider(
+ float startRadius, float endRadius, Rect startRect, Rect endRect) {
+ mStartRadius = startRadius;
+ mEndRadius = endRadius;
+ mStartRect = startRect;
+ mEndRect = endRect;
+
+ mOutline = new Rect();
+ }
+
+ @Override
+ public void getOutline(View v, Outline outline) {
+ outline.setRoundRect(mOutline, mOutlineRadius);
+ }
+
+ /** Sets the progress, from 0 to 1, of the reveal animation. */
+ public void setProgress(float progress) {
+ mOutlineRadius = (1 - progress) * mStartRadius + progress * mEndRadius;
+
+ mOutline.left = (int) ((1 - progress) * mStartRect.left + progress * mEndRect.left);
+ mOutline.top = (int) ((1 - progress) * mStartRect.top + progress * mEndRect.top);
+ mOutline.right = (int) ((1 - progress) * mStartRect.right + progress * mEndRect.right);
+ mOutline.bottom = (int) ((1 - progress) * mStartRect.bottom + progress * mEndRect.bottom);
+ }
+
+ ValueAnimator createRevealAnimator(final View revealView, boolean isReversed) {
+ ValueAnimator valueAnimator =
+ isReversed ? ValueAnimator.ofFloat(1f, 0f) : ValueAnimator.ofFloat(0f, 1f);
+
+ valueAnimator.addListener(
+ new AnimatorListenerAdapter() {
+ private boolean mWasCanceled = false;
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ revealView.setOutlineProvider(RoundedRectRevealOutlineProvider.this);
+ revealView.setClipToOutline(true);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mWasCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mWasCanceled) {
+ revealView.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
+ revealView.setClipToOutline(false);
+ }
+ }
+ });
+
+ valueAnimator.addUpdateListener(
+ (currentValueAnimator) -> {
+ float progress = (Float) currentValueAnimator.getAnimatedValue();
+ setProgress(progress);
+ revealView.invalidateOutline();
+ });
+ return valueAnimator;
+ }
+}
diff --git a/java/com/android/newbubble/res/layout/new_bubble_base.xml b/java/com/android/newbubble/res/layout/new_bubble_base.xml
index 216dce0d2..f83b75395 100644
--- a/java/com/android/newbubble/res/layout/new_bubble_base.xml
+++ b/java/com/android/newbubble/res/layout/new_bubble_base.xml
@@ -108,6 +108,7 @@
android:rotation="45">
</RelativeLayout>
<RelativeLayout
+ android:id="@+id/bubble_expanded_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/bubble_triangle"
diff --git a/java/com/android/voicemail/AndroidManifest.xml b/java/com/android/voicemail/AndroidManifest.xml
index 817cf1b55..d64fb2504 100644
--- a/java/com/android/voicemail/AndroidManifest.xml
+++ b/java/com/android/voicemail/AndroidManifest.xml
@@ -18,7 +18,7 @@
<uses-sdk
android:minSdkVersion="23"
- android:targetSdkVersion="26"/>
+ android:targetSdkVersion="27"/>
<!-- Applications using this module should merge these permissions using android_manifest_merge -->