/*
* Copyright (C) 2015 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
*/
package com.android.systemui.statusbar.policy;
import com.android.systemui.R;
import android.annotation.NonNull;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* Host for the remote input.
*/
public class RemoteInputView extends FrameLayout implements View.OnClickListener {
private static final String TAG = "RemoteInput";
private RemoteEditText mEditText;
private ProgressBar mProgressBar;
private PendingIntent mPendingIntent;
private RemoteInput mRemoteInput;
private Notification.Action mAction;
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mProgressBar = (ProgressBar) findViewById(R.id.remote_input_progress);
mEditText = (RemoteEditText) getChildAt(0);
mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter key
final boolean isSoftImeEvent = event == null
&& (actionId == EditorInfo.IME_ACTION_DONE
|| actionId == EditorInfo.IME_ACTION_NEXT
|| actionId == EditorInfo.IME_ACTION_SEND);
final boolean isKeyboardEnterKey = event != null
&& KeyEvent.isConfirmKey(event.getKeyCode())
&& event.getAction() == KeyEvent.ACTION_DOWN;
if (isSoftImeEvent || isKeyboardEnterKey) {
sendRemoteInput();
return true;
}
return false;
}
});
mEditText.setOnClickListener(this);
mEditText.setInnerFocusable(false);
}
private void sendRemoteInput() {
Bundle results = new Bundle();
results.putString(mRemoteInput.getResultKey(), mEditText.getText().toString());
Intent fillInIntent = new Intent();
RemoteInput.addResultsToIntent(mAction.getRemoteInputs(), fillInIntent,
results);
mEditText.setEnabled(false);
mProgressBar.setVisibility(VISIBLE);
try {
mPendingIntent.send(mContext, 0, fillInIntent);
} catch (PendingIntent.CanceledException e) {
Log.i(TAG, "Unable to send remote input result", e);
}
}
public static RemoteInputView inflate(Context context, ViewGroup root,
Notification.Action action, RemoteInput remoteInput) {
RemoteInputView v = (RemoteInputView)
LayoutInflater.from(context).inflate(R.layout.remote_input, root, false);
v.mEditText.setHint(action.title);
v.mPendingIntent = action.actionIntent;
v.mRemoteInput = remoteInput;
v.mAction = action;
return v;
}
@Override
public void onClick(View v) {
if (v == mEditText) {
if (!mEditText.isFocusable()) {
mEditText.setInnerFocusable(true);
InputMethodManager imm = InputMethodManager.getInstance();
if (imm != null) {
imm.viewClicked(mEditText);
imm.showSoftInput(mEditText, 0);
}
}
}
}
/**
* 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.
*/
public static class RemoteEditText extends EditText {
private final Drawable mBackground;
public RemoteEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mBackground = getBackground();
}
private void defocusIfNeeded() {
if (isFocusable() && isEnabled()) {
setInnerFocusable(false);
}
}
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (!isShown()) {
defocusIfNeeded();
}
}
@Override
protected void onFocusLost() {
super.onFocusLost();
defocusIfNeeded();
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
defocusIfNeeded();
}
return super.onKeyPreIme(keyCode, event);
}
void setInnerFocusable(boolean focusable) {
setFocusableInTouchMode(focusable);
setFocusable(focusable);
setCursorVisible(focusable);
if (focusable) {
requestFocus();
setBackground(mBackground);
} else {
setBackground(null);
}
}
}
}