Update context menu with tweaks from design.

This commit is contained in:
Rashad Sookram 2022-01-28 12:29:28 -05:00 committed by Cody Henthorne
parent 91c7e0a0ee
commit 45a91e0896
15 changed files with 191 additions and 98 deletions

View file

@ -4,6 +4,7 @@ import android.content.Context
import android.os.Build
import android.view.Gravity
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.PopupWindow
@ -30,6 +31,7 @@ class ConversationContextMenu(private val anchor: View, items: List<ActionItem>)
init {
setBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.signal_context_menu_background))
animationStyle = R.style.ConversationContextMenuAnimation
isFocusable = false
isOutsideTouchable = true
@ -38,6 +40,10 @@ class ConversationContextMenu(private val anchor: View, items: List<ActionItem>)
elevation = 20f
}
setTouchInterceptor { _, event ->
event.action == MotionEvent.ACTION_OUTSIDE
}
contextMenuList.setItems(items)
contentView.measure(

View file

@ -1466,6 +1466,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
itemView.getX(),
itemView.getY() + list.getTranslationY(),
bodyBubble.getX(),
bodyBubble.getY(),
bodyBubble.getWidth(),
audioUri,
messageRecord.isOutgoing());

View file

@ -363,13 +363,17 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
getHandler().postDelayed(shrinkBubble, SHRINK_BUBBLE_DELAY_MILLIS);
} else {
getHandler().removeCallbacks(shrinkBubble);
bodyBubble.animate()
.scaleX(1.0f)
.scaleY(1.0f);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
getHandler().postDelayed(shrinkBubble, SHRINK_BUBBLE_DELAY_MILLIS);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
getHandler().removeCallbacks(shrinkBubble);
bodyBubble.animate()
.scaleX(1.0f)
.scaleY(1.0f);
break;
}
return super.dispatchTouchEvent(ev);

View file

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.conversation
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Path
import android.view.View
import androidx.core.graphics.applyCanvas
@ -51,7 +50,8 @@ object ConversationItemSelection {
val path = Path()
val yTranslation = -conversationItem.y
val xTranslation = -conversationItem.x - conversationItem.bodyBubble.x
val yTranslation = -conversationItem.y - conversationItem.bodyBubble.y
val mp4Projection = conversationItem.getGiphyMp4PlayableProjection(list)
var scaledVideoBitmap = videoBitmap
@ -63,29 +63,30 @@ object ConversationItemSelection {
true
)
mp4Projection.translateX(xTranslation)
mp4Projection.translateY(yTranslation)
mp4Projection.applyToPath(path)
}
projections.use {
it.forEach { p ->
p.translateX(xTranslation)
p.translateY(yTranslation)
p.applyToPath(path)
}
}
val distanceToBubbleBottom = conversationItem.bodyBubble.height + conversationItem.bodyBubble.y.toInt()
return createBitmap(conversationItem.width, distanceToBubbleBottom).applyCanvas {
return createBitmap(conversationItem.bodyBubble.width, conversationItem.bodyBubble.height).applyCanvas {
if (drawConversationItem) {
draw(conversationItem)
conversationItem.bodyBubble.draw(this)
}
withClip(path) {
withTranslation(y = yTranslation) {
withTranslation(x = xTranslation, y = yTranslation) {
list.draw(this)
if (scaledVideoBitmap != null) {
drawBitmap(scaledVideoBitmap, mp4Projection.x, mp4Projection.y - yTranslation, null)
drawBitmap(scaledVideoBitmap, mp4Projection.x - xTranslation, mp4Projection.y - yTranslation, null)
}
}
}
@ -96,11 +97,4 @@ object ConversationItemSelection {
conversationItem.bodyBubble.scaleY = originalScale
}
}
private fun Canvas.draw(conversationItem: ConversationItem) {
val bodyBubble = conversationItem.bodyBubble
withTranslation(bodyBubble.x, bodyBubble.y) {
bodyBubble.draw(this@draw)
}
}
}

View file

@ -53,8 +53,7 @@ import kotlin.Unit;
public final class ConversationReactionOverlay extends RelativeLayout {
private static final Interpolator INTERPOLATOR = new DecelerateInterpolator();
private static final long TRANSITION_Y_DURATION = 150;
private static final Interpolator INTERPOLATOR = new DecelerateInterpolator();
private final Rect emojiViewGlobalRect = new Rect();
private final Rect emojiStripViewBounds = new Rect();
@ -89,10 +88,7 @@ public final class ConversationReactionOverlay extends RelativeLayout {
private ConversationContextMenu contextMenu;
private float touchDownDeadZoneSize;
private float distanceFromTouchDownPointToTopOfScrubberDeadZone;
private float distanceFromTouchDownPointToBottomOfScrubberDeadZone;
private int scrubberDistanceFromTouchDown;
private int scrubberHeight;
private int scrubberWidth;
private int selectedVerticalTranslation;
private int scrubberHorizontalMargin;
@ -137,15 +133,12 @@ public final class ConversationReactionOverlay extends RelativeLayout {
customEmojiIndex = emojiViews.length - 1;
distanceFromTouchDownPointToTopOfScrubberDeadZone = getResources().getDimensionPixelSize(R.dimen.conversation_reaction_scrub_deadzone_distance_from_touch_top);
distanceFromTouchDownPointToBottomOfScrubberDeadZone = getResources().getDimensionPixelSize(R.dimen.conversation_reaction_scrub_deadzone_distance_from_touch_bottom);
touchDownDeadZoneSize = getResources().getDimensionPixelSize(R.dimen.conversation_reaction_touch_deadzone_size);
scrubberDistanceFromTouchDown = getResources().getDimensionPixelOffset(R.dimen.conversation_reaction_scrubber_distance);
scrubberHeight = getResources().getDimensionPixelOffset(R.dimen.conversation_reaction_scrubber_height);
scrubberWidth = getResources().getDimensionPixelOffset(R.dimen.reaction_scrubber_width);
selectedVerticalTranslation = getResources().getDimensionPixelOffset(R.dimen.conversation_reaction_scrub_vertical_translation);
scrubberHorizontalMargin = getResources().getDimensionPixelOffset(R.dimen.conversation_reaction_scrub_horizontal_margin);
touchDownDeadZoneSize = getResources().getDimensionPixelSize(R.dimen.conversation_reaction_touch_deadzone_size);
scrubberWidth = getResources().getDimensionPixelOffset(R.dimen.reaction_scrubber_width);
selectedVerticalTranslation = getResources().getDimensionPixelOffset(R.dimen.conversation_reaction_scrub_vertical_translation);
scrubberHorizontalMargin = getResources().getDimensionPixelOffset(R.dimen.conversation_reaction_scrub_horizontal_margin);
animationEmojiStartDelayFactor = getResources().getInteger(R.integer.reaction_scrubber_emoji_reveal_duration_start_delay_factor);
@ -180,7 +173,7 @@ public final class ConversationReactionOverlay extends RelativeLayout {
}
ViewGroup.LayoutParams layoutParams = inputShade.getLayoutParams();
layoutParams.height = activity.findViewById(R.id.bottom_panel).getHeight();
layoutParams.height = getInputPanelHeight(activity);
inputShade.setLayoutParams(layoutParams);
toolbarShade.setVisibility(VISIBLE);
@ -191,12 +184,8 @@ public final class ConversationReactionOverlay extends RelativeLayout {
conversationItem.setLayoutParams(new LayoutParams(conversationItemSnapshot.getWidth(), conversationItemSnapshot.getHeight()));
conversationItem.setBackground(new BitmapDrawable(getResources(), conversationItemSnapshot));
float initialX = selectedConversationModel.getBitmapX();
boolean isMessageOnLeft = selectedConversationModel.isOutgoing() ^ ViewUtil.isLtr(this);
conversationItem.setX(initialX);
conversationItem.setY(selectedConversationModel.getBitmapY() - statusBarHeight);
conversationItem.setScaleX(ConversationItem.LONG_PRESS_SCALE_FACTOR);
conversationItem.setScaleY(ConversationItem.LONG_PRESS_SCALE_FACTOR);
@ -208,58 +197,70 @@ public final class ConversationReactionOverlay extends RelativeLayout {
});
}
private int getInputPanelHeight(@NonNull Activity activity) {
View bottomPanel = activity.findViewById(R.id.bottom_panel);
View emojiDrawer = activity.findViewById(R.id.emoji_drawer);
return bottomPanel.getHeight() + (emojiDrawer != null && emojiDrawer.getVisibility() == VISIBLE ? emojiDrawer.getHeight() : 0);
}
private void showAfterLayout(@NonNull Activity activity,
@NonNull ConversationMessage conversationMessage,
@NonNull PointF lastSeenDownPoint,
boolean isMessageOnLeft) {
contextMenu = new ConversationContextMenu(dropdownAnchor, getMenuActionItems(conversationMessage));
conversationItem.setX(selectedConversationModel.getBubbleX());
conversationItem.setY(selectedConversationModel.getItemY() + selectedConversationModel.getBubbleY() - statusBarHeight);
Bitmap conversationItemSnapshot = selectedConversationModel.getBitmap();
boolean isWideLayout = contextMenu.getMaxWidth() + scrubberWidth < getWidth();
int bubbleWidth = selectedConversationModel.getBubbleWidth();
float endX = selectedConversationModel.getBitmapX();
float endX = selectedConversationModel.getBubbleX();
float endY = conversationItem.getY();
float endApparentTop = endY;
float endScale = 1f;
float menuPadding = DimensionUnit.DP.toPixels(12f);
int reactionBarHeight = backgroundView.getHeight();
float menuPadding = DimensionUnit.DP.toPixels(12f);
float reactionBarTopPadding = DimensionUnit.DP.toPixels(32f);
int reactionBarHeight = backgroundView.getHeight();
float reactionBarBackgroundY;
if (isWideLayout) {
boolean everythingFitsVertically = scrubberHeight + conversationItemSnapshot.getHeight() < getHeight();
boolean everythingFitsVertically = reactionBarHeight + menuPadding + reactionBarTopPadding + conversationItemSnapshot.getHeight() < getHeight();
if (everythingFitsVertically) {
boolean reactionBarFitsAboveItem = conversationItem.getY() > scrubberHeight;
boolean reactionBarFitsAboveItem = conversationItem.getY() > reactionBarHeight + menuPadding + reactionBarTopPadding;
if (reactionBarFitsAboveItem) {
reactionBarBackgroundY = conversationItem.getY() - menuPadding - reactionBarHeight;
} else {
endY = reactionBarHeight + menuPadding;
reactionBarBackgroundY = 0f;
endY = reactionBarHeight + menuPadding + reactionBarTopPadding;
reactionBarBackgroundY = reactionBarTopPadding;
}
} else {
float spaceAvailableForItem = getHeight() - reactionBarHeight - menuPadding;
float spaceAvailableForItem = getHeight() - reactionBarHeight - menuPadding * 2;
endScale = spaceAvailableForItem / conversationItem.getHeight();
endY = reactionBarHeight + menuPadding - Util.halfOffsetFromScale(conversationItemSnapshot.getHeight(), endScale);
reactionBarBackgroundY = 0f;
endX += Util.halfOffsetFromScale(conversationItemSnapshot.getWidth(), endScale) * (isMessageOnLeft ? -1 : 1);
endY = reactionBarHeight + menuPadding + reactionBarTopPadding - Util.halfOffsetFromScale(conversationItemSnapshot.getHeight(), endScale);
reactionBarBackgroundY = reactionBarTopPadding;
}
} else {
boolean everythingFitsVertically = contextMenu.getMaxHeight() + conversationItemSnapshot.getHeight() + menuPadding + reactionBarHeight < getHeight();
boolean everythingFitsVertically = contextMenu.getMaxHeight() + conversationItemSnapshot.getHeight() + menuPadding + reactionBarHeight + reactionBarTopPadding < getHeight();
if (everythingFitsVertically) {
float itemBottom = selectedConversationModel.getBitmapY() + conversationItemSnapshot.getHeight();
boolean menuFitsBelowItem = itemBottom + menuPadding + contextMenu.getMaxHeight() <= getHeight();
float bubbleBottom = selectedConversationModel.getItemY() + selectedConversationModel.getBubbleY() + conversationItemSnapshot.getHeight();
boolean menuFitsBelowItem = bubbleBottom + menuPadding + contextMenu.getMaxHeight() <= getHeight() + statusBarHeight;
if (menuFitsBelowItem) {
reactionBarBackgroundY = conversationItem.getY() - menuPadding - reactionBarHeight;
if (reactionBarBackgroundY < 0) {
endY = backgroundView.getHeight();
reactionBarBackgroundY = 0f;
if (reactionBarBackgroundY < reactionBarTopPadding) {
endY = backgroundView.getHeight() + menuPadding;
reactionBarBackgroundY = reactionBarTopPadding;
}
} else {
endY = getHeight() - contextMenu.getMaxHeight() - menuPadding - conversationItemSnapshot.getHeight();
@ -267,30 +268,44 @@ public final class ConversationReactionOverlay extends RelativeLayout {
}
endApparentTop = endY;
} else if (reactionBarHeight + contextMenu.getMaxHeight() + menuPadding < getHeight()) {
float spaceAvailableForItem = (float) getHeight() - contextMenu.getMaxHeight() - menuPadding - reactionBarHeight;
} else if (reactionBarHeight + contextMenu.getMaxHeight() + menuPadding * 2 < getHeight()) {
float spaceAvailableForItem = (float) getHeight() - contextMenu.getMaxHeight() - menuPadding * 2 - reactionBarHeight - reactionBarTopPadding;
endScale = spaceAvailableForItem / conversationItemSnapshot.getHeight();
endY = reactionBarHeight - Util.halfOffsetFromScale(conversationItemSnapshot.getHeight(), endScale);
reactionBarBackgroundY = 0f;
endApparentTop = reactionBarHeight;
endX += Util.halfOffsetFromScale(conversationItemSnapshot.getWidth(), endScale) * (isMessageOnLeft ? -1 : 1);
endY = reactionBarHeight - Util.halfOffsetFromScale(conversationItemSnapshot.getHeight(), endScale) + menuPadding + reactionBarTopPadding;
reactionBarBackgroundY = reactionBarTopPadding;
endApparentTop = reactionBarHeight + menuPadding + reactionBarTopPadding;
} else {
contextMenu.setHeight(contextMenu.getMaxHeight() / 2);
int menuHeight = contextMenu.getHeight();
boolean fitsVertically = menuHeight + conversationItem.getHeight() + menuPadding + reactionBarHeight < getHeight();
boolean fitsVertically = menuHeight + conversationItem.getHeight() + menuPadding * 2 + reactionBarHeight + reactionBarTopPadding < getHeight();
if (fitsVertically) {
endY = getHeight() - menuHeight - menuPadding - conversationItemSnapshot.getHeight();
reactionBarBackgroundY = endY - reactionBarHeight;
float bubbleBottom = selectedConversationModel.getItemY() + selectedConversationModel.getBubbleY() + conversationItemSnapshot.getHeight();
boolean menuFitsBelowItem = bubbleBottom + menuPadding + menuHeight <= getHeight() + statusBarHeight;
if (menuFitsBelowItem) {
reactionBarBackgroundY = conversationItem.getY() - menuPadding - reactionBarHeight;
if (reactionBarBackgroundY < reactionBarTopPadding) {
endY = reactionBarTopPadding + reactionBarHeight + menuPadding;
reactionBarBackgroundY = reactionBarTopPadding;
}
} else {
endY = getHeight() - menuHeight - menuPadding - conversationItemSnapshot.getHeight();
reactionBarBackgroundY = endY - reactionBarHeight - menuPadding;
}
endApparentTop = endY;
} else {
float spaceAvailableForItem = (float) getHeight() - menuHeight - menuPadding - reactionBarHeight;
float spaceAvailableForItem = (float) getHeight() - menuHeight - menuPadding * 2 - reactionBarHeight - reactionBarTopPadding;
endScale = spaceAvailableForItem / conversationItemSnapshot.getHeight();
endY = reactionBarHeight - Util.halfOffsetFromScale(conversationItemSnapshot.getHeight(), endScale);
reactionBarBackgroundY = 0f;
endApparentTop = reactionBarHeight;
endX += Util.halfOffsetFromScale(conversationItemSnapshot.getWidth(), endScale) * (isMessageOnLeft ? -1 : 1);
endY = reactionBarHeight - Util.halfOffsetFromScale(conversationItemSnapshot.getHeight(), endScale) + menuPadding + reactionBarTopPadding;
reactionBarBackgroundY = reactionBarTopPadding;
endApparentTop = reactionBarHeight + menuPadding + reactionBarTopPadding;
}
}
}
@ -331,21 +346,21 @@ public final class ConversationReactionOverlay extends RelativeLayout {
float offsetX = isMessageOnLeft ? scrubberRight + menuPadding : scrubberX - contextMenu.getMaxWidth() - menuPadding;
contextMenu.show((int) offsetX, (int) Math.min(backgroundView.getY(), getHeight() - contextMenu.getMaxHeight()));
} else {
float contentX = selectedConversationModel.getContentX();
float offsetX = isMessageOnLeft ? contentX : - contextMenu.getMaxWidth() + contentX + bubbleWidth;
float contentX = selectedConversationModel.getBubbleX();
float offsetX = isMessageOnLeft ? contentX : -contextMenu.getMaxWidth() + contentX + bubbleWidth;
float menuTop = endApparentTop + (conversationItemSnapshot.getHeight() * endScale);
contextMenu.show((int) offsetX, (int) (menuTop + menuPadding));
}
conversationItem.animate()
.x(endX)
.scaleX(endScale)
.scaleY(endScale);
int revealDuration = getContext().getResources().getInteger(R.integer.reaction_scrubber_reveal_duration);
conversationItem.animate()
.x(endX)
.y(endY)
.setDuration(TRANSITION_Y_DURATION);
.scaleX(endScale)
.scaleY(endScale)
.setDuration(revealDuration);
}
@RequiresApi(api = 21)
@ -375,7 +390,7 @@ public final class ConversationReactionOverlay extends RelativeLayout {
private void hideInternal(@Nullable OnHideListener onHideListener) {
overlayState = OverlayState.HIDDEN;
int duration = getContext().getResources().getInteger(R.integer.reaction_scrubber_reveal_duration);
int duration = getContext().getResources().getInteger(R.integer.reaction_scrubber_hide_duration);
List<Animator> hides = new ArrayList<>(hideAnimators);
@ -395,16 +410,16 @@ public final class ConversationReactionOverlay extends RelativeLayout {
ObjectAnimator itemXAnim = new ObjectAnimator();
itemXAnim.setProperty(View.X);
itemXAnim.setFloatValues(selectedConversationModel.getBitmapX());
itemXAnim.setFloatValues(selectedConversationModel.getBubbleX());
itemXAnim.setTarget(conversationItem);
itemXAnim.setDuration(duration);
hides.add(itemXAnim);
ObjectAnimator itemYAnim = new ObjectAnimator();
itemYAnim.setProperty(View.Y);
itemYAnim.setFloatValues(selectedConversationModel.getBitmapY() - statusBarHeight);
itemYAnim.setFloatValues(selectedConversationModel.getItemY() + selectedConversationModel.getBubbleY() - statusBarHeight);
itemYAnim.setTarget(conversationItem);
itemYAnim.setDuration(TRANSITION_Y_DURATION);
itemYAnim.setDuration(duration);
hides.add(itemYAnim);
hideAnimatorSet.playTogether(hides);
@ -720,29 +735,28 @@ public final class ConversationReactionOverlay extends RelativeLayout {
private void initAnimators() {
int duration = getContext().getResources().getInteger(R.integer.reaction_scrubber_reveal_duration);
int revealDuration = getContext().getResources().getInteger(R.integer.reaction_scrubber_reveal_duration);
int revealOffset = getContext().getResources().getInteger(R.integer.reaction_scrubber_reveal_offset);
List<Animator> reveals = Stream.of(emojiViews)
.mapIndexed((idx, v) -> {
Animator anim = AnimatorInflaterCompat.loadAnimator(getContext(), R.animator.reactions_scrubber_reveal);
anim.setTarget(v);
anim.setStartDelay(idx * animationEmojiStartDelayFactor);
anim.setStartDelay(revealOffset + idx * animationEmojiStartDelayFactor);
return anim;
})
.toList();
Animator overlayRevealAnim = AnimatorInflaterCompat.loadAnimator(getContext(), android.R.animator.fade_in);
overlayRevealAnim.setDuration(duration);
reveals.add(overlayRevealAnim);
Animator backgroundRevealAnim = AnimatorInflaterCompat.loadAnimator(getContext(), android.R.animator.fade_in);
backgroundRevealAnim.setTarget(backgroundView);
backgroundRevealAnim.setDuration(duration);
backgroundRevealAnim.setDuration(revealDuration);
backgroundRevealAnim.setStartDelay(revealOffset);
reveals.add(backgroundRevealAnim);
Animator selectedRevealAnim = AnimatorInflaterCompat.loadAnimator(getContext(), android.R.animator.fade_in);
selectedRevealAnim.setTarget(selectedView);
selectedRevealAnim.setDuration(duration);
backgroundRevealAnim.setDuration(revealDuration);
backgroundRevealAnim.setStartDelay(revealOffset);
reveals.add(selectedRevealAnim);
revealAnimatorSet.setInterpolator(INTERPOLATOR);
@ -757,18 +771,20 @@ public final class ConversationReactionOverlay extends RelativeLayout {
})
.toList();
int hideDuration = getContext().getResources().getInteger(R.integer.reaction_scrubber_hide_duration);
Animator overlayHideAnim = AnimatorInflaterCompat.loadAnimator(getContext(), android.R.animator.fade_out);
overlayHideAnim.setDuration(duration);
overlayHideAnim.setDuration(hideDuration);
hideAnimators.add(overlayHideAnim);
Animator backgroundHideAnim = AnimatorInflaterCompat.loadAnimator(getContext(), android.R.animator.fade_out);
backgroundHideAnim.setTarget(backgroundView);
backgroundHideAnim.setDuration(duration);
backgroundHideAnim.setDuration(hideDuration);
hideAnimators.add(backgroundHideAnim);
Animator selectedHideAnim = AnimatorInflaterCompat.loadAnimator(getContext(), android.R.animator.fade_out);
selectedHideAnim.setTarget(selectedView);
selectedHideAnim.setDuration(duration);
selectedHideAnim.setDuration(hideDuration);
hideAnimators.add(selectedHideAnim);
hideAnimatorSet = newHideAnimatorSet();

View file

@ -9,9 +9,10 @@ import android.net.Uri
*/
data class SelectedConversationModel(
val bitmap: Bitmap,
val bitmapX: Float,
val bitmapY: Float,
val contentX: Float,
val itemX: Float,
val itemY: Float,
val bubbleX: Float,
val bubbleY: Float,
val bubbleWidth: Int,
val audioUri: Uri? = null,
val isOutgoing: Boolean,

View file

@ -118,13 +118,16 @@ class RecyclerViewColorizer(private val recyclerView: RecyclerView) {
colorPaint.xfermode = noLayerXfermode
}
val firstColor: Int
val lastColor: Int
if (chatColors.isGradient()) {
val mask = chatColors.chatBubbleMask as RotatableGradientDrawable
mask.setXfermode(colorPaint.xfermode)
mask.setBounds(0, 0, parent.width, parent.height)
mask.draw(canvas)
outOfBoundsPaint.color = chatColors.getColors().last()
firstColor = chatColors.getColors().first()
lastColor = chatColors.getColors().last()
} else {
colorPaint.color = chatColors.asSingleColor()
canvas.drawRect(
@ -135,9 +138,16 @@ class RecyclerViewColorizer(private val recyclerView: RecyclerView) {
colorPaint
)
outOfBoundsPaint.color = chatColors.asSingleColor()
firstColor = chatColors.asSingleColor()
lastColor = chatColors.asSingleColor()
}
outOfBoundsPaint.color = firstColor
canvas.drawRect(
0f, -parent.height.toFloat(), parent.width.toFloat(), 0f, outOfBoundsPaint
)
outOfBoundsPaint.color = lastColor
canvas.drawRect(
0f, parent.height.toFloat(), parent.width.toFloat(), parent.height * 2f, outOfBoundsPaint
)

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:interpolator="@android:interpolator/decelerate_quint"
android:fromXScale="0.9"
android:toXScale="1.0"
android:fromYScale="0.9"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="0%"
android:duration="220"
android:startOffset="150" />
<alpha
android:interpolator="@android:interpolator/decelerate_cubic"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="150"
android:startOffset="150" />
</set>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/res/anim/fade_out.xml
**
** Copyright 2007, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
<scale android:interpolator="@android:interpolator/decelerate_quint"
android:fromXScale="1.0" android:toXScale="0.9"
android:fromYScale="1.0" android:toYScale="0.9"
android:pivotX="50%" android:pivotY="0%"
android:duration="220" />
<alpha android:interpolator="@android:interpolator/decelerate_cubic"
android:fromAlpha="1.0" android:toAlpha="0.0"
android:duration="150" />
</set>

View file

@ -2,6 +2,7 @@
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="@integer/reaction_scrubber_reveal_duration"
android:startOffset="@integer/reaction_scrubber_reveal_offset"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="translationY"
android:valueFrom="@dimen/reaction_scrubber_anim_start_translation_y"
@ -9,6 +10,7 @@
<objectAnimator
android:duration="@integer/reaction_scrubber_reveal_duration"
android:startOffset="@integer/reaction_scrubber_reveal_offset"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="alpha"
android:valueFrom="0"

View file

@ -19,4 +19,9 @@
<item name="android:windowEnterAnimation">@anim/fade_in</item>
<item name="android:windowExitAnimation">@anim/fade_out</item>
</style>
<style name="ConversationContextMenuAnimation" parent="@android:style/Animation">
<item name="android:windowEnterAnimation">@anim/fade_in</item>
<item name="android:windowExitAnimation">@anim/shrink_fade_out</item>
</style>
</resources>

View file

@ -12,6 +12,7 @@
<color name="transparent_black_20">#33000000</color>
<color name="transparent_black_25">#40000000</color>
<color name="transparent_black_40">#66000000</color>
<color name="transparent_black_50">#80000000</color>
<color name="transparent_black_60">#99000000</color>
<color name="transparent_black_80">#CC000000</color>
<color name="transparent_black_90">#e6000000</color>

View file

@ -149,9 +149,7 @@
<dimen name="contact_selection_item_height">@dimen/selection_item_header_height</dimen>
<dimen name="conversation_reaction_scrubber_height">136dp</dimen>
<dimen name="conversation_reaction_scrubber_distance">25dp</dimen>
<dimen name="conversation_reaction_touch_deadzone_size">40dp</dimen>
<dimen name="conversation_reaction_scrub_deadzone_distance_from_touch_top">136dp</dimen>
<dimen name="conversation_reaction_scrub_deadzone_distance_from_touch_bottom">30dp</dimen>
<dimen name="conversation_reaction_scrub_vertical_translation">25dp</dimen>
<dimen name="conversation_reaction_scrub_horizontal_margin">16dp</dimen>

View file

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="reaction_scrubber_reveal_duration">400</integer>
<integer name="reaction_scrubber_reveal_duration">200</integer>
<integer name="reaction_scrubber_reveal_offset">100</integer>
<integer name="reaction_scrubber_hide_duration">150</integer>
<integer name="reaction_scrubber_reveal_emoji_duration">380</integer>
<integer name="reaction_scrubber_emoji_reveal_duration_start_delay_factor">10</integer>
</resources>

View file

@ -126,8 +126,8 @@
<color name="reactions_pill_text_color">@color/core_grey_60</color>
<color name="reactions_pill_selected_text_color">@color/core_grey_75</color>
<color name="reactions_screen_shade_color">@color/transparent_black_40</color>
<color name="reactions_status_bar_shade">#999999</color>
<color name="reactions_screen_shade_color">@color/transparent_black_50</color>
<color name="reactions_status_bar_shade">#808080</color>
<color name="recipient_contact_button_color">@color/core_grey_02</color>