Merge "Fix remote input view clobbering" into nyc-dev am: 1a101db
am: 326475cd
* commit '326475cdb42b7b50ff80e175b450cd43af531924':
Fix remote input view clobbering
Change-Id: Ieb9b6490e115a5cb91059b0499d520a1e9b38035
This commit is contained in:
@@ -3351,7 +3351,8 @@ public class Notification implements Parcelable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void resetStandardTemplateWithActions(RemoteViews big) {
|
private void resetStandardTemplateWithActions(RemoteViews big) {
|
||||||
big.setViewVisibility(R.id.actions_container, View.GONE);
|
// actions_container is only reset when there are no actions to avoid focus issues with
|
||||||
|
// remote inputs.
|
||||||
big.setViewVisibility(R.id.actions, View.GONE);
|
big.setViewVisibility(R.id.actions, View.GONE);
|
||||||
big.removeAllViews(R.id.actions);
|
big.removeAllViews(R.id.actions);
|
||||||
|
|
||||||
@@ -3396,6 +3397,8 @@ public class Notification implements Parcelable
|
|||||||
}
|
}
|
||||||
big.addView(R.id.actions, button);
|
big.addView(R.id.actions, button);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
big.setViewVisibility(R.id.actions_container, View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY);
|
CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.systemui.statusbar;
|
package com.android.systemui.statusbar;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.app.RemoteInput;
|
import android.app.RemoteInput;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -118,6 +119,8 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
private int mTransformationStartVisibleType;
|
private int mTransformationStartVisibleType;
|
||||||
private boolean mUserExpanding;
|
private boolean mUserExpanding;
|
||||||
private int mSingleLineWidthIndention;
|
private int mSingleLineWidthIndention;
|
||||||
|
private PendingIntent mPreviousExpandedRemoteInputIntent;
|
||||||
|
private PendingIntent mPreviousHeadsUpRemoteInputIntent;
|
||||||
|
|
||||||
public NotificationContentView(Context context, AttributeSet attrs) {
|
public NotificationContentView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@@ -280,13 +283,19 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
mContractedChild.animate().cancel();
|
mContractedChild.animate().cancel();
|
||||||
removeView(mContractedChild);
|
removeView(mContractedChild);
|
||||||
}
|
}
|
||||||
|
mPreviousExpandedRemoteInputIntent =
|
||||||
|
mExpandedRemoteInput != null ? mExpandedRemoteInput.getPendingIntent() : null;
|
||||||
if (mExpandedChild != null) {
|
if (mExpandedChild != null) {
|
||||||
mExpandedChild.animate().cancel();
|
mExpandedChild.animate().cancel();
|
||||||
removeView(mExpandedChild);
|
removeView(mExpandedChild);
|
||||||
|
mExpandedRemoteInput = null;
|
||||||
}
|
}
|
||||||
|
mPreviousHeadsUpRemoteInputIntent =
|
||||||
|
mHeadsUpRemoteInput != null ? mHeadsUpRemoteInput.getPendingIntent() : null;
|
||||||
if (mHeadsUpChild != null) {
|
if (mHeadsUpChild != null) {
|
||||||
mHeadsUpChild.animate().cancel();
|
mHeadsUpChild.animate().cancel();
|
||||||
removeView(mHeadsUpChild);
|
removeView(mHeadsUpChild);
|
||||||
|
mHeadsUpRemoteInput = null;
|
||||||
}
|
}
|
||||||
mContractedChild = null;
|
mContractedChild = null;
|
||||||
mExpandedChild = null;
|
mExpandedChild = null;
|
||||||
@@ -496,6 +505,12 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
int visibleType = calculateVisibleType();
|
int visibleType = calculateVisibleType();
|
||||||
if (visibleType != mVisibleType || force) {
|
if (visibleType != mVisibleType || force) {
|
||||||
|
View visibleView = getViewForVisibleType(visibleType);
|
||||||
|
if (visibleView != null) {
|
||||||
|
visibleView.setVisibility(VISIBLE);
|
||||||
|
transferRemoteInputFocus(visibleType);
|
||||||
|
}
|
||||||
|
|
||||||
if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
|
if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
|
||||||
|| (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
|
|| (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
|
||||||
|| (visibleType == VISIBLE_TYPE_SINGLELINE && mSingleLineView != null)
|
|| (visibleType == VISIBLE_TYPE_SINGLELINE && mSingleLineView != null)
|
||||||
@@ -559,6 +574,19 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void transferRemoteInputFocus(int visibleType) {
|
||||||
|
if (visibleType == VISIBLE_TYPE_HEADSUP
|
||||||
|
&& mHeadsUpRemoteInput != null
|
||||||
|
&& (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive())) {
|
||||||
|
mHeadsUpRemoteInput.stealFocusFrom(mExpandedRemoteInput);
|
||||||
|
}
|
||||||
|
if (visibleType == VISIBLE_TYPE_EXPANDED
|
||||||
|
&& mExpandedRemoteInput != null
|
||||||
|
&& (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive())) {
|
||||||
|
mExpandedRemoteInput.stealFocusFrom(mHeadsUpRemoteInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param visibleType one of the static enum types in this view
|
* @param visibleType one of the static enum types in this view
|
||||||
* @return the corresponding transformable view according to the given visible type
|
* @return the corresponding transformable view according to the given visible type
|
||||||
@@ -736,6 +764,8 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
updateShowingLegacyBackground();
|
updateShowingLegacyBackground();
|
||||||
selectLayout(false /* animate */, true /* force */);
|
selectLayout(false /* animate */, true /* force */);
|
||||||
setDark(mDark, false /* animate */, 0 /* delay */);
|
setDark(mDark, false /* animate */, 0 /* delay */);
|
||||||
|
mPreviousExpandedRemoteInputIntent = null;
|
||||||
|
mPreviousHeadsUpRemoteInputIntent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSingleLineView() {
|
private void updateSingleLineView() {
|
||||||
@@ -771,19 +801,23 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
|
|
||||||
View bigContentView = mExpandedChild;
|
View bigContentView = mExpandedChild;
|
||||||
if (bigContentView != null) {
|
if (bigContentView != null) {
|
||||||
mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput);
|
mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput,
|
||||||
|
mPreviousExpandedRemoteInputIntent);
|
||||||
} else {
|
} else {
|
||||||
mExpandedRemoteInput = null;
|
mExpandedRemoteInput = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
View headsUpContentView = mHeadsUpChild;
|
View headsUpContentView = mHeadsUpChild;
|
||||||
if (headsUpContentView != null) {
|
if (headsUpContentView != null) {
|
||||||
mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
|
mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput,
|
||||||
|
mPreviousHeadsUpRemoteInputIntent);
|
||||||
} else {
|
} else {
|
||||||
mHeadsUpRemoteInput = null;
|
mHeadsUpRemoteInput = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
|
private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry,
|
||||||
|
boolean hasRemoteInput, PendingIntent existingPendingIntent) {
|
||||||
View actionContainerCandidate = view.findViewById(
|
View actionContainerCandidate = view.findViewById(
|
||||||
com.android.internal.R.id.actions_container);
|
com.android.internal.R.id.actions_container);
|
||||||
if (actionContainerCandidate instanceof FrameLayout) {
|
if (actionContainerCandidate instanceof FrameLayout) {
|
||||||
@@ -814,6 +848,24 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
existing.setBackgroundColor(NotificationColorUtil.ensureTextBackgroundColor(color,
|
existing.setBackgroundColor(NotificationColorUtil.ensureTextBackgroundColor(color,
|
||||||
mContext.getColor(R.color.remote_input_text),
|
mContext.getColor(R.color.remote_input_text),
|
||||||
mContext.getColor(R.color.remote_input_hint)));
|
mContext.getColor(R.color.remote_input_hint)));
|
||||||
|
|
||||||
|
if (existingPendingIntent != null || existing.isActive()) {
|
||||||
|
// The current action could be gone, or the pending intent no longer valid.
|
||||||
|
// If we find a matching action in the new notification, focus, otherwise close.
|
||||||
|
Notification.Action[] actions = entry.notification.getNotification().actions;
|
||||||
|
if (existingPendingIntent != null) {
|
||||||
|
existing.setPendingIntent(existingPendingIntent);
|
||||||
|
}
|
||||||
|
if (existing.updatePendingIntentFromActions(actions)) {
|
||||||
|
if (!existing.isActive()) {
|
||||||
|
existing.focus();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (existing.isActive()) {
|
||||||
|
existing.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.policy;
|
package com.android.systemui.statusbar.policy;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.RemoteInput;
|
import android.app.RemoteInput;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -197,6 +198,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void focus() {
|
public void focus() {
|
||||||
|
setVisibility(VISIBLE);
|
||||||
mController.addRemoteInput(mEntry);
|
mController.addRemoteInput(mEntry);
|
||||||
mEditText.setInnerFocusable(true);
|
mEditText.setInnerFocusable(true);
|
||||||
mEditText.mShowImeOnInputConnection = true;
|
mEditText.mShowImeOnInputConnection = true;
|
||||||
@@ -275,6 +277,63 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return mEditText.isFocused();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stealFocusFrom(RemoteInputView other) {
|
||||||
|
other.close();
|
||||||
|
setPendingIntent(other.mPendingIntent);
|
||||||
|
setRemoteInput(other.mRemoteInputs, other.mRemoteInput);
|
||||||
|
focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to find an action in {@param actions} that matches the current pending intent
|
||||||
|
* of this view and updates its state to that of the found action
|
||||||
|
*
|
||||||
|
* @return true if a matching action was found, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean updatePendingIntentFromActions(Notification.Action[] actions) {
|
||||||
|
boolean found = false;
|
||||||
|
if (mPendingIntent == null || actions == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Intent current = mPendingIntent.getIntent();
|
||||||
|
if (current == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Notification.Action a : actions) {
|
||||||
|
RemoteInput[] inputs = a.getRemoteInputs();
|
||||||
|
if (a.actionIntent == null || inputs == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Intent candidate = a.actionIntent.getIntent();
|
||||||
|
if (!current.filterEquals(candidate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteInput input = null;
|
||||||
|
for (RemoteInput i : inputs) {
|
||||||
|
if (i.getAllowFreeFormInput()) {
|
||||||
|
input = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (input == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
setPendingIntent(a.actionIntent);
|
||||||
|
setRemoteInput(inputs, input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PendingIntent getPendingIntent() {
|
||||||
|
return mPendingIntent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EditText that changes appearance based on whether it's focusable and becomes
|
* An EditText that changes appearance based on whether it's focusable and becomes
|
||||||
* un-focusable whenever the user navigates away from it or it becomes invisible.
|
* un-focusable whenever the user navigates away from it or it becomes invisible.
|
||||||
|
|||||||
Reference in New Issue
Block a user