Merge "Single finger notification expansion." into jb-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a5e042f923
@@ -67,7 +67,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fadingEdge="none"
|
||||
android:overScrollMode="always"
|
||||
android:overScrollMode="ifContentScrolls"
|
||||
>
|
||||
<com.android.systemui.statusbar.policy.NotificationRowLayout
|
||||
android:id="@+id/latestItems"
|
||||
|
||||
@@ -65,5 +65,8 @@
|
||||
|
||||
<!-- Vibration duration for MultiWaveView used in SearchPanelView -->
|
||||
<integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
|
||||
|
||||
<!-- The length of the vibration when the notificaiotn pops open. -->
|
||||
<integer name="one_finger_pop_duration_ms">10</integer>
|
||||
</resources>
|
||||
|
||||
|
||||
@@ -150,4 +150,7 @@
|
||||
|
||||
<!-- Height of the carrier/wifi name label -->
|
||||
<dimen name="carrier_label_height">24dp</dimen>
|
||||
|
||||
<!-- The distance you can pull a notificaiton before it pops open -->
|
||||
<dimen name="one_finger_pop_limit">32dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -18,4 +18,5 @@
|
||||
<resources>
|
||||
<item type="id" name="expandable_tag" />
|
||||
<item type="id" name="user_expanded_tag" />
|
||||
<item type="id" name="user_lock_tag" />
|
||||
</resources>
|
||||
|
||||
@@ -22,24 +22,31 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.os.Vibrator;
|
||||
import android.util.Slog;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
public interface Callback {
|
||||
View getChildAtRawPosition(float x, float y);
|
||||
View getChildAtPosition(float x, float y);
|
||||
boolean canChildBeExpanded(View v);
|
||||
boolean setUserExpandedChild(View v, boolean userxpanded);
|
||||
boolean setUserExpandedChild(View v, boolean userExpanded);
|
||||
boolean setUserLockedChild(View v, boolean userLocked);
|
||||
}
|
||||
|
||||
private static final String TAG = "ExpandHelper";
|
||||
protected static final boolean DEBUG = false;
|
||||
protected static final boolean DEBUG_SCALE = false;
|
||||
protected static final boolean DEBUG_GLOW = false;
|
||||
private static final long EXPAND_DURATION = 250;
|
||||
private static final long GLOW_DURATION = 150;
|
||||
|
||||
@@ -63,6 +70,9 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
private Context mContext;
|
||||
|
||||
private boolean mStretching;
|
||||
private boolean mPullingWithOneFinger;
|
||||
private boolean mWatchingForPull;
|
||||
private boolean mHasPopped;
|
||||
private View mEventSource;
|
||||
private View mCurrView;
|
||||
private View mCurrViewTopGlow;
|
||||
@@ -70,7 +80,12 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
private float mOldHeight;
|
||||
private float mNaturalHeight;
|
||||
private float mInitialTouchFocusY;
|
||||
private float mInitialTouchY;
|
||||
private float mInitialTouchSpan;
|
||||
private int mTouchSlop;
|
||||
private int mLastMotionY;
|
||||
private float mPopLimit;
|
||||
private int mPopDuration;
|
||||
private Callback mCallback;
|
||||
private ScaleGestureDetector mDetector;
|
||||
private ViewScaler mScaler;
|
||||
@@ -78,6 +93,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
private AnimatorSet mGlowAnimationSet;
|
||||
private ObjectAnimator mGlowTopAnimation;
|
||||
private ObjectAnimator mGlowBottomAnimation;
|
||||
private Vibrator mVibrator;
|
||||
|
||||
private int mSmallSize;
|
||||
private int mLargeSize;
|
||||
@@ -85,6 +101,8 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
|
||||
private int mGravity;
|
||||
|
||||
private View mScrollView;
|
||||
|
||||
private class ViewScaler {
|
||||
View mView;
|
||||
|
||||
@@ -93,7 +111,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
mView = v;
|
||||
}
|
||||
public void setHeight(float h) {
|
||||
if (DEBUG) Slog.v(TAG, "SetHeight: setting to " + h);
|
||||
if (DEBUG_SCALE) Slog.v(TAG, "SetHeight: setting to " + h);
|
||||
ViewGroup.LayoutParams lp = mView.getLayoutParams();
|
||||
lp.height = (int)h;
|
||||
mView.setLayoutParams(lp);
|
||||
@@ -108,7 +126,8 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
}
|
||||
public int getNaturalHeight(int maximum) {
|
||||
ViewGroup.LayoutParams lp = mView.getLayoutParams();
|
||||
if (DEBUG) Slog.v(TAG, "Inspecting a child of type: " + mView.getClass().getName());
|
||||
if (DEBUG_SCALE) Slog.v(TAG, "Inspecting a child of type: " +
|
||||
mView.getClass().getName());
|
||||
int oldHeight = lp.height;
|
||||
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
mView.setLayoutParams(lp);
|
||||
@@ -142,6 +161,8 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
mGravity = Gravity.TOP;
|
||||
mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
|
||||
mScaleAnimation.setDuration(EXPAND_DURATION);
|
||||
mPopLimit = mContext.getResources().getDimension(R.dimen.one_finger_pop_limit);
|
||||
mPopDuration = mContext.getResources().getInteger(R.integer.one_finger_pop_duration_ms);
|
||||
|
||||
AnimatorListenerAdapter glowVisibilityController = new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
@@ -169,38 +190,30 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
mGlowAnimationSet.play(mGlowTopAnimation).with(mGlowBottomAnimation);
|
||||
mGlowAnimationSet.setDuration(GLOW_DURATION);
|
||||
|
||||
final ViewConfiguration configuration = ViewConfiguration.get(mContext);
|
||||
mTouchSlop = configuration.getScaledTouchSlop();
|
||||
|
||||
mDetector =
|
||||
new ScaleGestureDetector(context,
|
||||
new ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||
@Override
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
if (DEBUG) Slog.v(TAG, "onscalebegin()");
|
||||
if (DEBUG_SCALE) Slog.v(TAG, "onscalebegin()");
|
||||
float x = detector.getFocusX();
|
||||
float y = detector.getFocusY();
|
||||
|
||||
View v = null;
|
||||
if (mEventSource != null) {
|
||||
int[] location = new int[2];
|
||||
mEventSource.getLocationOnScreen(location);
|
||||
x += (float) location[0];
|
||||
y += (float) location[1];
|
||||
v = mCallback.getChildAtRawPosition(x, y);
|
||||
} else {
|
||||
v = mCallback.getChildAtPosition(x, y);
|
||||
}
|
||||
|
||||
// your fingers have to be somewhat close to the bounds of the view in question
|
||||
mInitialTouchFocusY = detector.getFocusY();
|
||||
mInitialTouchSpan = Math.abs(detector.getCurrentSpan());
|
||||
if (DEBUG) Slog.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");
|
||||
if (DEBUG_SCALE) Slog.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");
|
||||
|
||||
mStretching = initScale(v);
|
||||
mStretching = initScale(findView(x, y));
|
||||
return mStretching;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
if (DEBUG) Slog.v(TAG, "onscale() on " + mCurrView);
|
||||
if (DEBUG_SCALE) Slog.v(TAG, "onscale() on " + mCurrView);
|
||||
|
||||
// are we scaling or dragging?
|
||||
float span = Math.abs(detector.getCurrentSpan()) - mInitialTouchSpan;
|
||||
@@ -210,33 +223,71 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
drag *= mGravity == Gravity.BOTTOM ? -1f : 1f;
|
||||
float pull = Math.abs(drag) + Math.abs(span) + 1f;
|
||||
float hand = drag * Math.abs(drag) / pull + span * Math.abs(span) / pull;
|
||||
if (DEBUG) Slog.d(TAG, "current span handle is: " + hand);
|
||||
hand = hand + mOldHeight;
|
||||
float target = hand;
|
||||
if (DEBUG) Slog.d(TAG, "target is: " + target);
|
||||
hand = hand < mSmallSize ? mSmallSize : (hand > mLargeSize ? mLargeSize : hand);
|
||||
hand = hand > mNaturalHeight ? mNaturalHeight : hand;
|
||||
if (DEBUG) Slog.d(TAG, "scale continues: hand =" + hand);
|
||||
mScaler.setHeight(hand);
|
||||
float target = hand + mOldHeight;
|
||||
float newHeight = clamp(target);
|
||||
mScaler.setHeight(newHeight);
|
||||
|
||||
// glow if overscale
|
||||
float stretch = (float) Math.abs((target - hand) / mMaximumStretch);
|
||||
float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
|
||||
if (DEBUG) Slog.d(TAG, "stretch: " + stretch + " strength: " + strength);
|
||||
setGlow(GLOW_BASE + strength * (1f - GLOW_BASE));
|
||||
setGlow(calculateGlow(target, newHeight));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
if (DEBUG) Slog.v(TAG, "onscaleend()");
|
||||
if (DEBUG_SCALE) Slog.v(TAG, "onscaleend()");
|
||||
// I guess we're alone now
|
||||
if (DEBUG) Slog.d(TAG, "scale end");
|
||||
if (DEBUG_SCALE) Slog.d(TAG, "scale end");
|
||||
finishScale(false);
|
||||
clearView();
|
||||
mStretching = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private float clamp(float target) {
|
||||
float out = target;
|
||||
out = out < mSmallSize ? mSmallSize : (out > mLargeSize ? mLargeSize : out);
|
||||
out = out > mNaturalHeight ? mNaturalHeight : out;
|
||||
return out;
|
||||
}
|
||||
|
||||
private View findView(float x, float y) {
|
||||
View v = null;
|
||||
if (mEventSource != null) {
|
||||
int[] location = new int[2];
|
||||
mEventSource.getLocationOnScreen(location);
|
||||
x += (float) location[0];
|
||||
y += (float) location[1];
|
||||
v = mCallback.getChildAtRawPosition(x, y);
|
||||
} else {
|
||||
v = mCallback.getChildAtPosition(x, y);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private boolean isInside(View v, float x, float y) {
|
||||
if (DEBUG) Slog.d(TAG, "isinside (" + x + ", " + y + ")");
|
||||
|
||||
if (v == null) {
|
||||
if (DEBUG) Slog.d(TAG, "isinside null subject");
|
||||
return false;
|
||||
}
|
||||
if (mEventSource != null) {
|
||||
int[] location = new int[2];
|
||||
mEventSource.getLocationOnScreen(location);
|
||||
x += (float) location[0];
|
||||
y += (float) location[1];
|
||||
if (DEBUG) Slog.d(TAG, " to global (" + x + ", " + y + ")");
|
||||
}
|
||||
int[] location = new int[2];
|
||||
v.getLocationOnScreen(location);
|
||||
x -= (float) location[0];
|
||||
y -= (float) location[1];
|
||||
if (DEBUG) Slog.d(TAG, " to local (" + x + ", " + y + ")");
|
||||
if (DEBUG) Slog.d(TAG, " inside (" + v.getWidth() + ", " + v.getHeight() + ")");
|
||||
boolean inside = (x > 0f && y > 0f && x < v.getWidth() & y < v.getHeight());
|
||||
return inside;
|
||||
}
|
||||
|
||||
public void setEventSource(View eventSource) {
|
||||
mEventSource = eventSource;
|
||||
}
|
||||
@@ -245,13 +296,26 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
mGravity = gravity;
|
||||
}
|
||||
|
||||
public void setScrollView(View scrollView) {
|
||||
mScrollView = scrollView;
|
||||
}
|
||||
|
||||
private float calculateGlow(float target, float actual) {
|
||||
// glow if overscale
|
||||
if (DEBUG_GLOW) Slog.d(TAG, "target: " + target + " actual: " + actual);
|
||||
float stretch = (float) Math.abs((target - actual) / mMaximumStretch);
|
||||
float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
|
||||
if (DEBUG_GLOW) Slog.d(TAG, "stretch: " + stretch + " strength: " + strength);
|
||||
return (GLOW_BASE + strength * (1f - GLOW_BASE));
|
||||
}
|
||||
|
||||
public void setGlow(float glow) {
|
||||
if (!mGlowAnimationSet.isRunning() || glow == 0f) {
|
||||
if (mGlowAnimationSet.isRunning()) {
|
||||
mGlowAnimationSet.cancel();
|
||||
mGlowAnimationSet.end();
|
||||
}
|
||||
if (mCurrViewTopGlow != null && mCurrViewBottomGlow != null) {
|
||||
if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) {
|
||||
if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) {
|
||||
// animate glow in and out
|
||||
mGlowTopAnimation.setTarget(mCurrViewTopGlow);
|
||||
mGlowBottomAnimation.setTarget(mCurrViewBottomGlow);
|
||||
@@ -278,23 +342,115 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (DEBUG) Slog.d(TAG, "interceptTouch: act=" + (ev.getAction()) +
|
||||
" stretching=" + mStretching);
|
||||
" stretching=" + mStretching +
|
||||
" onefinger=" + mPullingWithOneFinger);
|
||||
// check for a two-finger gesture
|
||||
mDetector.onTouchEvent(ev);
|
||||
return mStretching;
|
||||
if (mStretching) {
|
||||
return true;
|
||||
} else {
|
||||
final int action = ev.getAction();
|
||||
if ((action == MotionEvent.ACTION_MOVE) && mPullingWithOneFinger) {
|
||||
return true;
|
||||
}
|
||||
if (mScrollView != null && mScrollView.getScrollY() > 0) {
|
||||
return false;
|
||||
}
|
||||
switch (action & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
if (mWatchingForPull) {
|
||||
final int x = (int) ev.getX();
|
||||
final int y = (int) ev.getY();
|
||||
final int yDiff = y - mLastMotionY;
|
||||
if (yDiff > mTouchSlop) {
|
||||
mLastMotionY = y;
|
||||
mPullingWithOneFinger = initScale(findView(x, y));
|
||||
if (mPullingWithOneFinger) {
|
||||
mInitialTouchY = mLastMotionY;
|
||||
mHasPopped = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mWatchingForPull = isInside(mScrollView, ev.getX(), ev.getY());
|
||||
mLastMotionY = (int) ev.getY();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (mPullingWithOneFinger) {
|
||||
finishScale(false);
|
||||
clearView();
|
||||
}
|
||||
mPullingWithOneFinger = false;
|
||||
mWatchingForPull = false;
|
||||
break;
|
||||
}
|
||||
return mPullingWithOneFinger;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
final int action = ev.getAction();
|
||||
if (DEBUG) Slog.d(TAG, "touch: act=" + (action) + " stretching=" + mStretching);
|
||||
if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + (action) +
|
||||
" stretching=" + mStretching +
|
||||
" onefinger=" + mPullingWithOneFinger);
|
||||
if (mStretching) {
|
||||
if (DEBUG) Slog.d(TAG, "detector ontouch");
|
||||
mDetector.onTouchEvent(ev);
|
||||
}
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
if (mPullingWithOneFinger) {
|
||||
final float rawHeight = ev.getY() - mInitialTouchY + mOldHeight;
|
||||
final float newHeight = clamp(rawHeight);
|
||||
final boolean wasClosed = (mOldHeight == mSmallSize);
|
||||
boolean isFinished = false;
|
||||
if (rawHeight > mNaturalHeight) {
|
||||
isFinished = true;
|
||||
}
|
||||
if (rawHeight < mSmallSize) {
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
final float pull = Math.abs(ev.getY() - mInitialTouchY);
|
||||
if (mHasPopped || pull > mPopLimit) {
|
||||
if (!mHasPopped) {
|
||||
vibrate(mPopDuration);
|
||||
mHasPopped = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mHasPopped) {
|
||||
mScaler.setHeight(newHeight);
|
||||
setGlow(GLOW_BASE);
|
||||
} else {
|
||||
setGlow(calculateGlow(4f * pull, 0f));
|
||||
}
|
||||
|
||||
final int x = (int) ev.getX();
|
||||
final int y = (int) ev.getY();
|
||||
View underPointer = findView(x, y);
|
||||
if (isFinished && underPointer != null && underPointer != mCurrView) {
|
||||
finishScale(false);
|
||||
initScale(underPointer);
|
||||
mInitialTouchY = ev.getY();
|
||||
mHasPopped = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (DEBUG) Slog.d(TAG, "cancel");
|
||||
mStretching = false;
|
||||
if (mPullingWithOneFinger) {
|
||||
finishScale(false);
|
||||
mPullingWithOneFinger = false;
|
||||
}
|
||||
clearView();
|
||||
break;
|
||||
}
|
||||
@@ -303,7 +459,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
private boolean initScale(View v) {
|
||||
if (v != null) {
|
||||
if (DEBUG) Slog.d(TAG, "scale begins on view: " + v);
|
||||
mStretching = true;
|
||||
mCallback.setUserLockedChild(v, true);
|
||||
setView(v);
|
||||
setGlow(GLOW_BASE);
|
||||
mScaler.setView(v);
|
||||
@@ -318,30 +474,34 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
if (DEBUG) Slog.d(TAG, "got mOldHeight: " + mOldHeight +
|
||||
" mNaturalHeight: " + mNaturalHeight);
|
||||
v.getParent().requestDisallowInterceptTouchEvent(true);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return mStretching;
|
||||
}
|
||||
|
||||
private void finishScale(boolean force) {
|
||||
float currentHeight = mScaler.getHeight();
|
||||
float targetHeight = mSmallSize;
|
||||
float h = mScaler.getHeight();
|
||||
final boolean wasClosed = (mOldHeight == mSmallSize);
|
||||
if (wasClosed) {
|
||||
h = (force || h > mSmallSize) ? mNaturalHeight : mSmallSize;
|
||||
targetHeight = (force || currentHeight > mSmallSize) ? mNaturalHeight : mSmallSize;
|
||||
} else {
|
||||
h = (force || h < mNaturalHeight) ? mSmallSize : mNaturalHeight;
|
||||
targetHeight = (force || currentHeight < mNaturalHeight) ? mSmallSize : mNaturalHeight;
|
||||
}
|
||||
if (DEBUG && mCurrView != null) mCurrView.setBackgroundColor(0);
|
||||
if (mScaleAnimation.isRunning()) {
|
||||
mScaleAnimation.cancel();
|
||||
}
|
||||
mScaleAnimation.setFloatValues(h);
|
||||
mScaleAnimation.setupStartValues();
|
||||
mScaleAnimation.start();
|
||||
mStretching = false;
|
||||
setGlow(0f);
|
||||
mCallback.setUserExpandedChild(mCurrView, h == mNaturalHeight);
|
||||
if (targetHeight != currentHeight) {
|
||||
mScaleAnimation.setFloatValues(targetHeight);
|
||||
mScaleAnimation.setupStartValues();
|
||||
mScaleAnimation.start();
|
||||
}
|
||||
mCallback.setUserLockedChild(mCurrView, false);
|
||||
if (DEBUG) Slog.d(TAG, "scale was finished on view: " + mCurrView);
|
||||
clearView();
|
||||
}
|
||||
|
||||
private void clearView() {
|
||||
@@ -357,7 +517,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
mCurrViewTopGlow = g.findViewById(R.id.top_glow);
|
||||
mCurrViewBottomGlow = g.findViewById(R.id.bottom_glow);
|
||||
if (DEBUG) {
|
||||
String debugLog = "Looking for glows: " +
|
||||
String debugLog = "Looking for glows: " +
|
||||
(mCurrViewTopGlow != null ? "found top " : "didn't find top") +
|
||||
(mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom");
|
||||
Slog.v(TAG, debugLog);
|
||||
@@ -369,6 +529,18 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
|
||||
public void onClick(View v) {
|
||||
initScale(v);
|
||||
finishScale(true);
|
||||
clearView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers haptic feedback.
|
||||
*/
|
||||
private synchronized void vibrate(long duration) {
|
||||
if (mVibrator == null) {
|
||||
mVibrator = (android.os.Vibrator)
|
||||
mContext.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
}
|
||||
mVibrator.vibrate(duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -783,16 +783,20 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
int N = mNotificationData.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
NotificationData.Entry entry = mNotificationData.get(i);
|
||||
if (i == (N-1)) {
|
||||
if (DEBUG) Slog.d(TAG, "expanding top notification at " + i);
|
||||
expandView(entry, true);
|
||||
} else {
|
||||
if (!entry.userExpanded()) {
|
||||
if (DEBUG) Slog.d(TAG, "collapsing notification at " + i);
|
||||
expandView(entry, false);
|
||||
if (!entry.userLocked()) {
|
||||
if (i == (N-1)) {
|
||||
if (DEBUG) Slog.d(TAG, "expanding top notification at " + i);
|
||||
expandView(entry, true);
|
||||
} else {
|
||||
if (DEBUG) Slog.d(TAG, "ignoring user-modified notification at " + i);
|
||||
if (!entry.userExpanded()) {
|
||||
if (DEBUG) Slog.d(TAG, "collapsing notification at " + i);
|
||||
expandView(entry, false);
|
||||
} else {
|
||||
if (DEBUG) Slog.d(TAG, "ignoring user-modified notification at " + i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (DEBUG) Slog.d(TAG, "ignoring notification being held by user at " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,18 @@ public class NotificationData {
|
||||
public boolean setUserExpanded(boolean userExpanded) {
|
||||
return NotificationData.setUserExpanded(row, userExpanded);
|
||||
}
|
||||
/**
|
||||
* Return whether the entry is being touched by the user.
|
||||
*/
|
||||
public boolean userLocked() {
|
||||
return NotificationData.getUserLocked(row);
|
||||
}
|
||||
/**
|
||||
* Set the flag indicating that this is being touched by the user.
|
||||
*/
|
||||
public boolean setUserLocked(boolean userLocked) {
|
||||
return NotificationData.setUserLocked(row, userLocked);
|
||||
}
|
||||
}
|
||||
private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
|
||||
private final Comparator<Entry> mEntryCmp = new Comparator<Entry>() {
|
||||
@@ -197,4 +209,18 @@ public class NotificationData {
|
||||
public static boolean setUserExpanded(View row, boolean userExpanded) {
|
||||
return writeBooleanTag(row, R.id.user_expanded_tag, userExpanded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the entry is being touched by the user.
|
||||
*/
|
||||
public static boolean getUserLocked(View row) {
|
||||
return readBooleanTag(row, R.id.user_lock_tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the entry is being touched by the user.
|
||||
*/
|
||||
public static boolean setUserLocked(View row, boolean userLocked) {
|
||||
return writeBooleanTag(row, R.id.user_lock_tag, userLocked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public class StatusBarWindowView extends FrameLayout
|
||||
int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
|
||||
mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight);
|
||||
mExpandHelper.setEventSource(this);
|
||||
mExpandHelper.setScrollView(scroller);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -78,6 +78,7 @@ public class NotificationRowLayout
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
mRealLayoutTransition = new LayoutTransition();
|
||||
mRealLayoutTransition.setAnimateParentHierarchy(true);
|
||||
setLayoutTransitionsEnabled(true);
|
||||
|
||||
setOrientation(LinearLayout.VERTICAL);
|
||||
@@ -161,7 +162,12 @@ public class NotificationRowLayout
|
||||
return NotificationData.setUserExpanded(v, userExpanded);
|
||||
}
|
||||
|
||||
public boolean setUserLockedChild(View v, boolean userLocked) {
|
||||
return NotificationData.setUserLocked(v, userLocked);
|
||||
}
|
||||
|
||||
public void onChildDismissed(View v) {
|
||||
if (DEBUG) Slog.v(TAG, "onChildDismissed: " + v + " mRemoveViews=" + mRemoveViews);
|
||||
final View veto = v.findViewById(R.id.veto);
|
||||
if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
|
||||
veto.performClick();
|
||||
@@ -225,6 +231,7 @@ public class NotificationRowLayout
|
||||
* get removed properly.
|
||||
*/
|
||||
public void setViewRemoval(boolean removeViews) {
|
||||
if (DEBUG) Slog.v(TAG, "setViewRemoval: " + removeViews);
|
||||
mRemoveViews = removeViews;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user