[go: nahoru, domu]

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