1ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing/* 2ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Copyright (C) 2015 The Android Open Source Project 3ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * 4ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * in compliance with the License. You may obtain a copy of the License at 6ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * 7ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * http://www.apache.org/licenses/LICENSE-2.0 8ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * 9ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Unless required by applicable law or agreed to in writing, software distributed under the License 10ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * or implied. See the License for the specific language governing permissions and limitations under 12ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * the License. 13ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 14be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gupackage android.support.v17.leanback.widget; 15ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 16ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.content.Context; 17ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.database.DataSetObserver; 18ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.media.AudioManager; 19ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v17.leanback.R; 20ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v7.widget.RecyclerView; 21ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.support.v7.widget.RecyclerView.ViewHolder; 22ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.util.Log; 23ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.KeyEvent; 24ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.LayoutInflater; 25ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.View; 26ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.view.ViewGroup; 274158705d3f0751d419a08c47a659abeae5f6c196Kris Giesingimport android.view.ViewParent; 284158705d3f0751d419a08c47a659abeae5f6c196Kris Giesingimport android.view.inputmethod.EditorInfo; 294158705d3f0751d419a08c47a659abeae5f6c196Kris Giesingimport android.view.inputmethod.InputMethodManager; 30ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.widget.AdapterView.OnItemSelectedListener; 314158705d3f0751d419a08c47a659abeae5f6c196Kris Giesingimport android.widget.EditText; 32ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.widget.ImageView; 33ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport android.widget.TextView; 344158705d3f0751d419a08c47a659abeae5f6c196Kris Giesingimport android.widget.TextView.OnEditorActionListener; 35ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 36ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport java.util.ArrayList; 37ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesingimport java.util.List; 38ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 39ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing/** 40ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidedActionAdapter instantiates views for guided actions, and manages their interactions. 41ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Presentation (view creation and state animation) is delegated to a {@link 42ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * GuidedActionsStylist}, while clients are notified of interactions via 43ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@link GuidedActionAdapter.ClickListener} and {@link GuidedActionAdapter.FocusListener}. 44be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu * @hide 45ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 46be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gupublic class GuidedActionAdapter extends RecyclerView.Adapter { 47ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private static final String TAG = "GuidedActionAdapter"; 48ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private static final boolean DEBUG = false; 49ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 504158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing private static final String TAG_EDIT = "EditableAction"; 514158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing private static final boolean DEBUG_EDIT = false; 524158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 53ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 54ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Object listening for click events within a {@link GuidedActionAdapter}. 55ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 56ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public interface ClickListener { 57ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 58ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 59ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Called when the user clicks on an action. 60ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 61ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onGuidedActionClicked(GuidedAction action); 62be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu 63ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 64ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 65ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 66ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Object listening for focus events within a {@link GuidedActionAdapter}. 67ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 68ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public interface FocusListener { 69ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 70ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 71ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Called when the user focuses on an action. 72ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 73ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onGuidedActionFocused(GuidedAction action); 74ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 75ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 76ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 774158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing * Object listening for edit events within a {@link GuidedActionAdapter}. 784158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing */ 794158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing public interface EditListener { 804158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 814158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing /** 82c1741246af607f6be2389056da0182c40f938348Dake Gu * Called when the user exits edit mode on an action. 834158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing */ 8416ab389e0bd11594059f8164a1477045ee625154Dake Gu public void onGuidedActionEditCanceled(GuidedAction action); 85bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu 86bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu /** 87bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu * Called when the user exits edit mode on an action and process confirm button in IME. 88bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu */ 89bcc19824dc43bc2e1bf23bccb1263f8de87ac013Dake Gu public long onGuidedActionEditedAndProceed(GuidedAction action); 90c1741246af607f6be2389056da0182c40f938348Dake Gu 91c1741246af607f6be2389056da0182c40f938348Dake Gu /** 92c1741246af607f6be2389056da0182c40f938348Dake Gu * Called when Ime Open 93c1741246af607f6be2389056da0182c40f938348Dake Gu */ 94c1741246af607f6be2389056da0182c40f938348Dake Gu public void onImeOpen(); 95c1741246af607f6be2389056da0182c40f938348Dake Gu 96c1741246af607f6be2389056da0182c40f938348Dake Gu /** 97c1741246af607f6be2389056da0182c40f938348Dake Gu * Called when Ime Close 98c1741246af607f6be2389056da0182c40f938348Dake Gu */ 99c1741246af607f6be2389056da0182c40f938348Dake Gu public void onImeClose(); 1004158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 1014158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 102be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu private final boolean mIsSubAdapter; 103ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private final ActionOnKeyListener mActionOnKeyListener; 104ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private final ActionOnFocusListener mActionOnFocusListener; 1054158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing private final ActionEditListener mActionEditListener; 106ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private final List<GuidedAction> mActions; 107ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private ClickListener mClickListener; 10843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu private final GuidedActionsStylist mStylist; 109ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private final View.OnClickListener mOnClickListener = new View.OnClickListener() { 110ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 111ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onClick(View v) { 11243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (v != null && v.getWindowToken() != null && getRecyclerView() != null) { 113be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder) 114be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu getRecyclerView().getChildViewHolder(v); 115ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing GuidedAction action = avh.getAction(); 116b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (action.hasTextEditable()) { 11743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme by click"); 11843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mGroup.openIme(GuidedActionAdapter.this, avh); 119b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu } else if (action.hasEditableActivatorView()) { 120b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu if (DEBUG_EDIT) Log.v(TAG_EDIT, "toggle editing mode by click"); 121b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu getGuidedActionsStylist().setEditingMode(avh, avh.getAction(), 122b88b36aa081a500eb0e9d4be0bac85b33cd57ddeDake Gu !avh.isInEditingActivatorView()); 12343e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } else { 12443e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu handleCheckedActions(avh); 12543e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (action.isEnabled() && !action.infoOnly()) { 12643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu performOnActionClick(avh); 12743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 128ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 129ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 130ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 131ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing }; 13243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu GuidedActionAdapterGroup mGroup; 133ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 134ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 135ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Constructs a GuidedActionAdapter with the given list of guided actions, the given click and 136ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * focus listeners, and the given presenter. 137ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param actions The list of guided actions this adapter will manage. 138ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param focusListener The focus listener for items in this adapter. 139ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param presenter The presenter that will manage the display of items in this adapter. 140ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 141ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public GuidedActionAdapter(List<GuidedAction> actions, ClickListener clickListener, 142be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu FocusListener focusListener, GuidedActionsStylist presenter, boolean isSubAdapter) { 143ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing super(); 144be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mActions = actions == null ? new ArrayList<GuidedAction>() : 145be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu new ArrayList<GuidedAction>(actions); 146ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mClickListener = clickListener; 147ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mStylist = presenter; 1484158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing mActionOnKeyListener = new ActionOnKeyListener(); 149ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mActionOnFocusListener = new ActionOnFocusListener(focusListener); 15043e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mActionEditListener = new ActionEditListener(); 151be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mIsSubAdapter = isSubAdapter; 152ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 153ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 154ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 155ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Sets the list of actions managed by this adapter. 156ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param actions The list of actions to be managed. 157ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 158ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void setActions(List<GuidedAction> actions) { 159ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mActionOnFocusListener.unFocus(); 160ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mActions.clear(); 161ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mActions.addAll(actions); 162ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing notifyDataSetChanged(); 163ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 164ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 165ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 166ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the count of actions managed by this adapter. 167ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The count of actions managed by this adapter. 168ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 169ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public int getCount() { 170ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return mActions.size(); 171ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 172ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 173ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 174ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Returns the GuidedAction at the given position in the managed list. 175ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param position The position of the desired GuidedAction. 176ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @return The GuidedAction at the given position. 177ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 178ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public GuidedAction getItem(int position) { 179ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return mActions.get(position); 180ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 181ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 182ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 18343e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu * Return index of action in array 18443e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu * @param action Action to search index. 18543e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu * @return Index of Action in array. 18643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu */ 18743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu public int indexOf(GuidedAction action) { 18843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu return mActions.indexOf(action); 18943e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 19043e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu 19143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu /** 19243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu * @return GuidedActionsStylist used to build the actions list UI. 19343e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu */ 19443e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu public GuidedActionsStylist getGuidedActionsStylist() { 19543e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu return mStylist; 19643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 19743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu 19843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu /** 199ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Sets the click listener for items managed by this adapter. 200ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param clickListener The click listener for this adapter. 201ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 202ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void setClickListener(ClickListener clickListener) { 203ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mClickListener = clickListener; 204ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 205ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 206ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 207ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Sets the focus listener for items managed by this adapter. 208ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @param focusListener The focus listener for this adapter. 209ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 210ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void setFocusListener(FocusListener focusListener) { 211ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mActionOnFocusListener.setFocusListener(focusListener); 212ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 213ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 214ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 215ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Used for serialization only. 216ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * @hide 217ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 218ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public List<GuidedAction> getActions() { 219ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return new ArrayList<GuidedAction>(mActions); 220ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 221ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 222ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 223ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@inheritDoc} 224ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 225ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 226e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu public int getItemViewType(int position) { 227e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu return mStylist.getItemViewType(mActions.get(position)); 228e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu } 229e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu 23043e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu private RecyclerView getRecyclerView() { 231be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu return mIsSubAdapter ? mStylist.getSubActionsGridView() : mStylist.getActionsGridView(); 232ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 233ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 234ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 235ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@inheritDoc} 236ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 237ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 238ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 239e2f7aef2f45dcdfe116995b64f9a7be5c68a36a1Dake Gu GuidedActionsStylist.ViewHolder vh = mStylist.onCreateViewHolder(parent, viewType); 240be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu View v = vh.itemView; 241ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing v.setOnKeyListener(mActionOnKeyListener); 242ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing v.setOnClickListener(mOnClickListener); 243ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing v.setOnFocusChangeListener(mActionOnFocusListener); 244ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 245c1741246af607f6be2389056da0182c40f938348Dake Gu setupListeners(vh.getEditableTitleView()); 246c1741246af607f6be2389056da0182c40f938348Dake Gu setupListeners(vh.getEditableDescriptionView()); 247c1741246af607f6be2389056da0182c40f938348Dake Gu 248be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu return vh; 249c1741246af607f6be2389056da0182c40f938348Dake Gu } 250c1741246af607f6be2389056da0182c40f938348Dake Gu 251c1741246af607f6be2389056da0182c40f938348Dake Gu private void setupListeners(EditText edit) { 2524158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing if (edit != null) { 2534158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing edit.setPrivateImeOptions("EscapeNorth=1;"); 2544158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing edit.setOnEditorActionListener(mActionEditListener); 255ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing if (edit instanceof ImeKeyMonitor) { 256ac07e9d12b10138d4a449522f7082a40f18861e2Kris Giesing ImeKeyMonitor monitor = (ImeKeyMonitor)edit; 2574158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing monitor.setImeKeyListener(mActionEditListener); 2584158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 2594158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 260ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 261ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 262ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 263ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@inheritDoc} 264ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 265ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 266ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onBindViewHolder(ViewHolder holder, int position) { 267ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (position >= mActions.size()) { 268ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return; 269ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 270be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu final GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder)holder; 271ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing GuidedAction action = mActions.get(position); 272be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onBindViewHolder(avh, action); 273ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 274ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 275ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 276ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * {@inheritDoc} 277ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 278ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 279ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public int getItemCount() { 280ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return mActions.size(); 281ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 282ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 283ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private class ActionOnFocusListener implements View.OnFocusChangeListener { 284ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 285ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private FocusListener mFocusListener; 286ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private View mSelectedView; 287ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 288ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing ActionOnFocusListener(FocusListener focusListener) { 289ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mFocusListener = focusListener; 290ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 291ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 292ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void setFocusListener(FocusListener focusListener) { 293ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mFocusListener = focusListener; 294ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 295ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 296ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void unFocus() { 29743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (mSelectedView != null && getRecyclerView() != null) { 29843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu ViewHolder vh = getRecyclerView().getChildViewHolder(mSelectedView); 299ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (vh != null) { 300be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder)vh; 301be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onAnimateItemFocused(avh, false); 302ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } else { 303ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing Log.w(TAG, "RecyclerView returned null view holder", 304ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing new Throwable()); 305ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 306ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 307ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 308ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 309ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 310ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public void onFocusChange(View v, boolean hasFocus) { 31143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (getRecyclerView() == null) { 31243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu return; 31343e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 314be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder) 315be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu getRecyclerView().getChildViewHolder(v); 316ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (hasFocus) { 317ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mSelectedView = v; 318ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (mFocusListener != null) { 319ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // We still call onGuidedActionFocused so that listeners can clear 320ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // state if they want. 321ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mFocusListener.onGuidedActionFocused(avh.getAction()); 322ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 323ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } else { 324ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (mSelectedView == v) { 325be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onAnimateItemPressedCancelled(avh); 326ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mSelectedView = null; 327ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 328ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 329be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onAnimateItemFocused(avh, hasFocus); 330ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 331ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 332ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 333be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public GuidedActionsStylist.ViewHolder findSubChildViewHolder(View v) { 33443e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu // Needed because RecyclerView.getChildViewHolder does not traverse the hierarchy 33543e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (getRecyclerView() == null) { 33643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu return null; 33743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 338be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedActionsStylist.ViewHolder result = null; 33943e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu ViewParent parent = v.getParent(); 34043e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu while (parent != getRecyclerView() && parent != null && v != null) { 34143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu v = (View)parent; 34243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu parent = parent.getParent(); 34343e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 34443e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (parent != null && v != null) { 345be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu result = (GuidedActionsStylist.ViewHolder)getRecyclerView().getChildViewHolder(v); 34643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 34743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu return result; 34843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 34943e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu 350be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public void handleCheckedActions(GuidedActionsStylist.ViewHolder avh) { 35143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu GuidedAction action = avh.getAction(); 35243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu int actionCheckSetId = action.getCheckSetId(); 35343e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (getRecyclerView() != null && actionCheckSetId != GuidedAction.NO_CHECK_SET) { 35443e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu // Find any actions that are checked and are in the same group 35543e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu // as the selected action. Fade their checkmarks out. 35611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu if (actionCheckSetId != GuidedAction.CHECKBOX_CHECK_SET_ID) { 35711cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu for (int i = 0, size = mActions.size(); i < size; i++) { 35811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu GuidedAction a = mActions.get(i); 35911cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu if (a != action && a.getCheckSetId() == actionCheckSetId && a.isChecked()) { 36011cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu a.setChecked(false); 361be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedActionsStylist.ViewHolder vh = (GuidedActionsStylist.ViewHolder) 362be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu getRecyclerView().findViewHolderForPosition(i); 36311cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu if (vh != null) { 364be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onAnimateItemChecked(vh, false); 36511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu } 36643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 36743e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 36843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 36943e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu 37043e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu // If we we'ren't already checked, fade our checkmark in. 37143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (!action.isChecked()) { 37243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu action.setChecked(true); 373be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onAnimateItemChecked(avh, true); 37411cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu } else { 37511cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu if (actionCheckSetId == GuidedAction.CHECKBOX_CHECK_SET_ID) { 37611cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu action.setChecked(false); 377be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onAnimateItemChecked(avh, false); 37811cb62de8bfc6b5b6d22811ad12a1e60451b82beDake Gu } 37943e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 38043e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 38143e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 38243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu 383be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu public void performOnActionClick(GuidedActionsStylist.ViewHolder avh) { 38443e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (mClickListener != null) { 38543e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mClickListener.onGuidedActionClicked(avh.getAction()); 38643e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu } 387c1741246af607f6be2389056da0182c40f938348Dake Gu } 388c1741246af607f6be2389056da0182c40f938348Dake Gu 389ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private class ActionOnKeyListener implements View.OnKeyListener { 390ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 391ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing private boolean mKeyPressed = false; 392ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 393ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing /** 394ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing * Now only handles KEYCODE_ENTER and KEYCODE_NUMPAD_ENTER key event. 395ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing */ 396ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing @Override 397ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing public boolean onKey(View v, int keyCode, KeyEvent event) { 39843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu if (v == null || event == null || getRecyclerView() == null) { 399ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return false; 400ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 401ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing boolean handled = false; 402ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing switch (keyCode) { 403ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing case KeyEvent.KEYCODE_DPAD_CENTER: 404ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing case KeyEvent.KEYCODE_NUMPAD_ENTER: 405ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing case KeyEvent.KEYCODE_BUTTON_X: 406ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing case KeyEvent.KEYCODE_BUTTON_Y: 407ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing case KeyEvent.KEYCODE_ENTER: 408ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 409be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu GuidedActionsStylist.ViewHolder avh = (GuidedActionsStylist.ViewHolder) 410be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu getRecyclerView().getChildViewHolder(v); 411ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing GuidedAction action = avh.getAction(); 412ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 413ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (!action.isEnabled() || action.infoOnly()) { 414ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (event.getAction() == KeyEvent.ACTION_DOWN) { 415ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing // TODO: requires API 19 416ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing //playSound(v, AudioManager.FX_KEYPRESS_INVALID); 417ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 418ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return true; 419ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 420ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 421ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing switch (event.getAction()) { 422ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing case KeyEvent.ACTION_DOWN: 423a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu if (DEBUG) { 424a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu Log.d(TAG, "Enter Key down"); 425a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu } 426ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (!mKeyPressed) { 427ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mKeyPressed = true; 428be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onAnimateItemPressed(avh, mKeyPressed); 429ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 430ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing break; 431ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing case KeyEvent.ACTION_UP: 432a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu if (DEBUG) { 433a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu Log.d(TAG, "Enter Key up"); 434a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu } 435a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu // Sometimes we are losing ACTION_DOWN for the first ENTER after pressed 436a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu // Escape in IME. 437ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing if (mKeyPressed) { 438ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing mKeyPressed = false; 439be6eb618b4ba8a74d69fa04c77c717b1fcbea818Dake Gu mStylist.onAnimateItemPressed(avh, mKeyPressed); 440ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 441ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing break; 442ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing default: 443ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing break; 444ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 445ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing break; 446ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing default: 447ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing break; 448ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 449ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing return handled; 450ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 451ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing 452ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing } 4534158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 4544158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing private class ActionEditListener implements OnEditorActionListener, 4554158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing ImeKeyMonitor.ImeKeyListener { 4564158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 4574158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing @Override 4584158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 4594158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME action: " + actionId); 4604158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing boolean handled = false; 4614158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing if (actionId == EditorInfo.IME_ACTION_NEXT || 4624158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing actionId == EditorInfo.IME_ACTION_DONE) { 46343e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mGroup.fillAndGoNext(GuidedActionAdapter.this, v); 464a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu handled = true; 465a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu } else if (actionId == EditorInfo.IME_ACTION_NONE) { 466a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme escape north"); 467a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu // Escape north handling: stay on current item, but close editor 468a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu handled = true; 46943e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mGroup.fillAndStay(GuidedActionAdapter.this, v); 470a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu } 471a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu return handled; 472a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu } 4734158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 4744158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing @Override 4754158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing public boolean onKeyPreIme(EditText editText, int keyCode, KeyEvent event) { 4764158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME key: " + keyCode); 4774158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { 47843e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mGroup.fillAndStay(GuidedActionAdapter.this, editText); 47971afae9a0c4fd555c16a8e0a9727ba8c21bc39a8Dake Gu return true; 480a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu } else if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == 481a97810e4e2ec2552f8247ebdadf323dae70d9e3fDake Gu KeyEvent.ACTION_UP) { 48243e10e99e55c1c2eeca31fa13e9cc84160850f59Dake Gu mGroup.fillAndGoNext(GuidedActionAdapter.this, editText); 48371afae9a0c4fd555c16a8e0a9727ba8c21bc39a8Dake Gu return true; 4844158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 4854158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing return false; 4864158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 4874158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 4884158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing } 4894158705d3f0751d419a08c47a659abeae5f6c196Kris Giesing 490ebd3d9078dbaebd10a9506ca086435eb63e8a2d2Kris Giesing} 491