mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-01 08:16:49 +00:00
Simplifying app icon popup
> Using a single linearLayout instead of multiple nested views > Using clipToOutline for rounded corners instead of using canvas.saveLayer > Removing nested view elevations and overdraw > Using LayoutTransition for animating layout changes, instead of manually creating animators Change-Id: I8e57092f52ca5a032a2756594fdd39788acc5a0d
This commit is contained in:
@@ -18,13 +18,17 @@ package com.android.launcher3.notification;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.RippleDrawable;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -33,6 +37,7 @@ import android.widget.TextView;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.touch.OverScroll;
|
||||
import com.android.launcher3.touch.SwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
@@ -42,13 +47,33 @@ import com.android.launcher3.util.Themes;
|
||||
* A {@link android.widget.FrameLayout} that contains a single notification,
|
||||
* e.g. icon + title + text.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public class NotificationMainView extends FrameLayout implements SwipeDetector.Listener {
|
||||
|
||||
private static FloatProperty<NotificationMainView> CONTENT_TRANSLATION =
|
||||
new FloatProperty<NotificationMainView>("contentTranslation") {
|
||||
@Override
|
||||
public void setValue(NotificationMainView view, float v) {
|
||||
view.setContentTranslation(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(NotificationMainView view) {
|
||||
return view.mTextAndBackground.getTranslationX();
|
||||
}
|
||||
};
|
||||
|
||||
// This is used only to track the notification view, so that it can be properly logged.
|
||||
public static final ItemInfo NOTIFICATION_ITEM_INFO = new ItemInfo();
|
||||
|
||||
private final ObjectAnimator mContentTranslateAnimator;
|
||||
|
||||
private NotificationInfo mNotificationInfo;
|
||||
private ViewGroup mTextAndBackground;
|
||||
private int mBackgroundColor;
|
||||
private TextView mTitleView;
|
||||
private TextView mTextView;
|
||||
private View mIconView;
|
||||
|
||||
private SwipeDetector mSwipeDetector;
|
||||
|
||||
@@ -62,25 +87,24 @@ public class NotificationMainView extends FrameLayout implements SwipeDetector.L
|
||||
|
||||
public NotificationMainView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
mContentTranslateAnimator = ObjectAnimator.ofFloat(this, CONTENT_TRANSLATION, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mTextAndBackground = (ViewGroup) findViewById(R.id.text_and_background);
|
||||
mTextAndBackground = findViewById(R.id.text_and_background);
|
||||
ColorDrawable colorBackground = (ColorDrawable) mTextAndBackground.getBackground();
|
||||
mBackgroundColor = colorBackground.getColor();
|
||||
RippleDrawable rippleBackground = new RippleDrawable(ColorStateList.valueOf(
|
||||
Themes.getAttrColor(getContext(), android.R.attr.colorControlHighlight)),
|
||||
colorBackground, null);
|
||||
mTextAndBackground.setBackground(rippleBackground);
|
||||
mTitleView = (TextView) mTextAndBackground.findViewById(R.id.title);
|
||||
mTextView = (TextView) mTextAndBackground.findViewById(R.id.text);
|
||||
}
|
||||
|
||||
public void applyNotificationInfo(NotificationInfo mainNotification, View iconView) {
|
||||
applyNotificationInfo(mainNotification, iconView, false);
|
||||
mTitleView = mTextAndBackground.findViewById(R.id.title);
|
||||
mTextView = mTextAndBackground.findViewById(R.id.text);
|
||||
mIconView = findViewById(R.id.popup_item_icon);
|
||||
}
|
||||
|
||||
public void setSwipeDetector(SwipeDetector swipeDetector) {
|
||||
@@ -90,8 +114,7 @@ public class NotificationMainView extends FrameLayout implements SwipeDetector.L
|
||||
/**
|
||||
* Sets the content of this view, animating it after a new icon shifts up if necessary.
|
||||
*/
|
||||
public void applyNotificationInfo(NotificationInfo mainNotification, View iconView,
|
||||
boolean animate) {
|
||||
public void applyNotificationInfo(NotificationInfo mainNotification, boolean animate) {
|
||||
mNotificationInfo = mainNotification;
|
||||
CharSequence title = mNotificationInfo.title;
|
||||
CharSequence text = mNotificationInfo.text;
|
||||
@@ -103,20 +126,30 @@ public class NotificationMainView extends FrameLayout implements SwipeDetector.L
|
||||
mTitleView.setText(TextUtils.isEmpty(title) ? text.toString() : title.toString());
|
||||
mTextView.setVisibility(GONE);
|
||||
}
|
||||
iconView.setBackground(mNotificationInfo.getIconForBackground(getContext(),
|
||||
mIconView.setBackground(mNotificationInfo.getIconForBackground(getContext(),
|
||||
mBackgroundColor));
|
||||
if (mNotificationInfo.intent != null) {
|
||||
setOnClickListener(mNotificationInfo);
|
||||
}
|
||||
setTranslationX(0);
|
||||
setContentTranslation(0);
|
||||
// Add a dummy ItemInfo so that logging populates the correct container and item types
|
||||
// instead of DEFAULT_CONTAINERTYPE and DEFAULT_ITEMTYPE, respectively.
|
||||
setTag(new ItemInfo());
|
||||
setTag(NOTIFICATION_ITEM_INFO);
|
||||
if (animate) {
|
||||
ObjectAnimator.ofFloat(mTextAndBackground, ALPHA, 0, 1).setDuration(150).start();
|
||||
}
|
||||
}
|
||||
|
||||
public void setContentTranslation(float translation) {
|
||||
mTextAndBackground.setTranslationX(translation);
|
||||
mIconView.setTranslationX(translation);
|
||||
}
|
||||
|
||||
public void setContentVisibility(int visibility) {
|
||||
mTextAndBackground.setVisibility(visibility);
|
||||
mIconView.setVisibility(visibility);
|
||||
}
|
||||
|
||||
public NotificationInfo getNotificationInfo() {
|
||||
return mNotificationInfo;
|
||||
}
|
||||
@@ -143,9 +176,9 @@ public class NotificationMainView extends FrameLayout implements SwipeDetector.L
|
||||
|
||||
@Override
|
||||
public boolean onDrag(float displacement, float velocity) {
|
||||
setTranslationX(canChildBeDismissed()
|
||||
setContentTranslation(canChildBeDismissed()
|
||||
? displacement : OverScroll.dampedScroll(displacement, getWidth()));
|
||||
animate().cancel();
|
||||
mContentTranslateAnimator.cancel();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -153,6 +186,7 @@ public class NotificationMainView extends FrameLayout implements SwipeDetector.L
|
||||
public void onDragEnd(float velocity, boolean fling) {
|
||||
final boolean willExit;
|
||||
final float endTranslation;
|
||||
final float startTranslation = mTextAndBackground.getTranslationX();
|
||||
|
||||
if (!canChildBeDismissed()) {
|
||||
willExit = false;
|
||||
@@ -160,28 +194,30 @@ public class NotificationMainView extends FrameLayout implements SwipeDetector.L
|
||||
} else if (fling) {
|
||||
willExit = true;
|
||||
endTranslation = velocity < 0 ? - getWidth() : getWidth();
|
||||
} else if (Math.abs(getTranslationX()) > getWidth() / 2) {
|
||||
} else if (Math.abs(startTranslation) > getWidth() / 2) {
|
||||
willExit = true;
|
||||
endTranslation = (getTranslationX() < 0 ? -getWidth() : getWidth());
|
||||
endTranslation = (startTranslation < 0 ? -getWidth() : getWidth());
|
||||
} else {
|
||||
willExit = false;
|
||||
endTranslation = 0;
|
||||
}
|
||||
|
||||
long duration = SwipeDetector.calculateDuration(velocity,
|
||||
(endTranslation - getTranslationX()) / getWidth());
|
||||
animate()
|
||||
.setDuration(duration)
|
||||
.setInterpolator(scrollInterpolatorForVelocity(velocity))
|
||||
.translationX(endTranslation)
|
||||
.withEndAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSwipeDetector.finishedScrolling();
|
||||
if (willExit) {
|
||||
onChildDismissed();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
(endTranslation - startTranslation) / getWidth());
|
||||
|
||||
mContentTranslateAnimator.removeAllListeners();
|
||||
mContentTranslateAnimator.setDuration(duration)
|
||||
.setInterpolator(scrollInterpolatorForVelocity(velocity));
|
||||
mContentTranslateAnimator.setFloatValues(startTranslation, endTranslation);
|
||||
mContentTranslateAnimator.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mSwipeDetector.finishedScrolling();
|
||||
if (willExit) {
|
||||
onChildDismissed();
|
||||
}
|
||||
}
|
||||
});
|
||||
mContentTranslateAnimator.start();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user