Merge "Fix remote input view clobbering" into nyc-dev

This commit is contained in:
TreeHugger Robot
2016-04-27 22:17:32 +00:00
committed by Android (Google) Code Review
3 changed files with 118 additions and 4 deletions

View File

@@ -3351,7 +3351,8 @@ public class Notification implements Parcelable
}
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.removeAllViews(R.id.actions);
@@ -3396,6 +3397,8 @@ public class Notification implements Parcelable
}
big.addView(R.id.actions, button);
}
} else {
big.setViewVisibility(R.id.actions_container, View.GONE);
}
CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY);

View File

@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.graphics.Rect;
@@ -118,6 +119,8 @@ public class NotificationContentView extends FrameLayout {
private int mTransformationStartVisibleType;
private boolean mUserExpanding;
private int mSingleLineWidthIndention;
private PendingIntent mPreviousExpandedRemoteInputIntent;
private PendingIntent mPreviousHeadsUpRemoteInputIntent;
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -280,13 +283,19 @@ public class NotificationContentView extends FrameLayout {
mContractedChild.animate().cancel();
removeView(mContractedChild);
}
mPreviousExpandedRemoteInputIntent =
mExpandedRemoteInput != null ? mExpandedRemoteInput.getPendingIntent() : null;
if (mExpandedChild != null) {
mExpandedChild.animate().cancel();
removeView(mExpandedChild);
mExpandedRemoteInput = null;
}
mPreviousHeadsUpRemoteInputIntent =
mHeadsUpRemoteInput != null ? mHeadsUpRemoteInput.getPendingIntent() : null;
if (mHeadsUpChild != null) {
mHeadsUpChild.animate().cancel();
removeView(mHeadsUpChild);
mHeadsUpRemoteInput = null;
}
mContractedChild = null;
mExpandedChild = null;
@@ -496,6 +505,12 @@ public class NotificationContentView extends FrameLayout {
}
int visibleType = calculateVisibleType();
if (visibleType != mVisibleType || force) {
View visibleView = getViewForVisibleType(visibleType);
if (visibleView != null) {
visibleView.setVisibility(VISIBLE);
transferRemoteInputFocus(visibleType);
}
if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
|| (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != 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
* @return the corresponding transformable view according to the given visible type
@@ -736,6 +764,8 @@ public class NotificationContentView extends FrameLayout {
updateShowingLegacyBackground();
selectLayout(false /* animate */, true /* force */);
setDark(mDark, false /* animate */, 0 /* delay */);
mPreviousExpandedRemoteInputIntent = null;
mPreviousHeadsUpRemoteInputIntent = null;
}
private void updateSingleLineView() {
@@ -771,19 +801,23 @@ public class NotificationContentView extends FrameLayout {
View bigContentView = mExpandedChild;
if (bigContentView != null) {
mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput);
mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput,
mPreviousExpandedRemoteInputIntent);
} else {
mExpandedRemoteInput = null;
}
View headsUpContentView = mHeadsUpChild;
if (headsUpContentView != null) {
mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput,
mPreviousHeadsUpRemoteInputIntent);
} else {
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(
com.android.internal.R.id.actions_container);
if (actionContainerCandidate instanceof FrameLayout) {
@@ -814,6 +848,24 @@ public class NotificationContentView extends FrameLayout {
existing.setBackgroundColor(NotificationColorUtil.ensureTextBackgroundColor(color,
mContext.getColor(R.color.remote_input_text),
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;
}

View File

@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.policy;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
@@ -197,6 +198,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
}
public void focus() {
setVisibility(VISIBLE);
mController.addRemoteInput(mEntry);
mEditText.setInnerFocusable(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
* un-focusable whenever the user navigates away from it or it becomes invisible.