MaterialSearchActionView.java revision 524ded5f9d27dda75c53d256922a39c867857575
1c6801eb828627c37b8992584767c095dfe11df62Jin Cao/*
2c6801eb828627c37b8992584767c095dfe11df62Jin Cao * Copyright (C) 2014 Google Inc.
3c6801eb828627c37b8992584767c095dfe11df62Jin Cao * Licensed to The Android Open Source Project.
4c6801eb828627c37b8992584767c095dfe11df62Jin Cao *
5c6801eb828627c37b8992584767c095dfe11df62Jin Cao * Licensed under the Apache License, Version 2.0 (the "License");
6c6801eb828627c37b8992584767c095dfe11df62Jin Cao * you may not use this file except in compliance with the License.
7c6801eb828627c37b8992584767c095dfe11df62Jin Cao * You may obtain a copy of the License at
8c6801eb828627c37b8992584767c095dfe11df62Jin Cao *
9c6801eb828627c37b8992584767c095dfe11df62Jin Cao *      http://www.apache.org/licenses/LICENSE-2.0
10c6801eb828627c37b8992584767c095dfe11df62Jin Cao *
11c6801eb828627c37b8992584767c095dfe11df62Jin Cao * Unless required by applicable law or agreed to in writing, software
12c6801eb828627c37b8992584767c095dfe11df62Jin Cao * distributed under the License is distributed on an "AS IS" BASIS,
13c6801eb828627c37b8992584767c095dfe11df62Jin Cao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14c6801eb828627c37b8992584767c095dfe11df62Jin Cao * See the License for the specific language governing permissions and
15c6801eb828627c37b8992584767c095dfe11df62Jin Cao * limitations under the License.
16c6801eb828627c37b8992584767c095dfe11df62Jin Cao */
17c6801eb828627c37b8992584767c095dfe11df62Jin Cao
18c6801eb828627c37b8992584767c095dfe11df62Jin Caopackage com.android.mail.ui;
19c6801eb828627c37b8992584767c095dfe11df62Jin Cao
20c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.content.Context;
218ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Caoimport android.content.res.Resources;
22524ded5f9d27dda75c53d256922a39c867857575Jin Caoimport android.graphics.drawable.ColorDrawable;
23524ded5f9d27dda75c53d256922a39c867857575Jin Caoimport android.graphics.drawable.Drawable;
24524ded5f9d27dda75c53d256922a39c867857575Jin Caoimport android.support.annotation.DrawableRes;
25c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.text.Editable;
26c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.text.TextWatcher;
27c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.util.AttributeSet;
28c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.view.KeyEvent;
29c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.view.View;
30524ded5f9d27dda75c53d256922a39c867857575Jin Caoimport android.view.ViewGroup;
31c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.view.inputmethod.EditorInfo;
32c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.view.inputmethod.InputMethodManager;
33c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.widget.EditText;
34c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.widget.ImageView;
35c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.widget.LinearLayout;
36c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport android.widget.TextView;
37c6801eb828627c37b8992584767c095dfe11df62Jin Cao
38c6801eb828627c37b8992584767c095dfe11df62Jin Caoimport com.android.mail.R;
39524ded5f9d27dda75c53d256922a39c867857575Jin Caoimport com.android.mail.utils.ViewUtils;
40c6801eb828627c37b8992584767c095dfe11df62Jin Cao
41c6801eb828627c37b8992584767c095dfe11df62Jin Cao/**
42c6801eb828627c37b8992584767c095dfe11df62Jin Cao * Custom view for the action bar when search is displayed.
43c6801eb828627c37b8992584767c095dfe11df62Jin Cao */
44c6801eb828627c37b8992584767c095dfe11df62Jin Caopublic class MaterialSearchActionView extends LinearLayout implements TextWatcher,
4564168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao        View.OnClickListener, TextView.OnEditorActionListener, View.OnKeyListener {
46524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private Drawable mNormalBackgroundDrawable;
47524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private Drawable mTwoPaneLandConvModeBackgroundDrawable;
48524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private @DrawableRes int mNormalBackButtonDrawable;
49524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private @DrawableRes int mTwoPaneLandConvModeBackButtonDrawable;
50524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private @DrawableRes int mNormalClearTextButtonDrawable;
51524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private @DrawableRes int mTwoPaneLandConvModeClearTextButtonDrawable;
52524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private @DrawableRes int mNormalVoiceButtonDrawable;
53524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private @DrawableRes int mTwoPaneLandConvModeVoiceButtonDrawable;
54524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private int mNormalTextColor;
55524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private int mTwoPaneLandConvModeTextColor;
56524ded5f9d27dda75c53d256922a39c867857575Jin Cao
57c6801eb828627c37b8992584767c095dfe11df62Jin Cao    private MaterialSearchViewController mController;
58c6801eb828627c37b8992584767c095dfe11df62Jin Cao    private InputMethodManager mImm;
59c6801eb828627c37b8992584767c095dfe11df62Jin Cao    private boolean mShowingClose;
60c6801eb828627c37b8992584767c095dfe11df62Jin Cao    private boolean mSupportVoice;
61c6801eb828627c37b8992584767c095dfe11df62Jin Cao
62524ded5f9d27dda75c53d256922a39c867857575Jin Cao    private ImageView mBackButton;
63c6801eb828627c37b8992584767c095dfe11df62Jin Cao    private EditText mQueryText;
64c6801eb828627c37b8992584767c095dfe11df62Jin Cao    private ImageView mEndingButton;
65c6801eb828627c37b8992584767c095dfe11df62Jin Cao
66c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public MaterialSearchActionView(Context context) {
67524ded5f9d27dda75c53d256922a39c867857575Jin Cao        this(context, null);
68c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
69c6801eb828627c37b8992584767c095dfe11df62Jin Cao
70c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public MaterialSearchActionView(Context context, AttributeSet attrs) {
71c6801eb828627c37b8992584767c095dfe11df62Jin Cao        super(context, attrs);
72524ded5f9d27dda75c53d256922a39c867857575Jin Cao
73524ded5f9d27dda75c53d256922a39c867857575Jin Cao        final Resources res = getResources();
74524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mNormalBackgroundDrawable = new ColorDrawable(res.getColor(android.R.color.white));
75524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mTwoPaneLandConvModeBackgroundDrawable =
76524ded5f9d27dda75c53d256922a39c867857575Jin Cao                new ColorDrawable(res.getColor(R.color.actionbar_color));
77524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mNormalBackButtonDrawable = R.drawable.ic_arrow_back_24dp_with_rtl;
78524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mTwoPaneLandConvModeBackButtonDrawable = R.drawable.ic_arrow_back_wht_24dp;
79524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mNormalClearTextButtonDrawable = R.drawable.ic_close_24dp;
80524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mTwoPaneLandConvModeClearTextButtonDrawable = R.drawable.ic_close_wht_24dp;
81524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mNormalVoiceButtonDrawable = R.drawable.ic_mic_24dp;
82524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mTwoPaneLandConvModeVoiceButtonDrawable = R.drawable.ic_mic_white_24dp;
83524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mNormalTextColor = res.getColor(R.color.search_query_text);
84524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mTwoPaneLandConvModeTextColor = res.getColor(android.R.color.white);
85c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
86c6801eb828627c37b8992584767c095dfe11df62Jin Cao
87c6801eb828627c37b8992584767c095dfe11df62Jin Cao    // PUBLIC API
88c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public void setController(MaterialSearchViewController controller, String initialQuery,
89c6801eb828627c37b8992584767c095dfe11df62Jin Cao            boolean supportVoice) {
90c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mController = controller;
91c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mQueryText.setText(initialQuery);
92c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mSupportVoice = supportVoice;
93c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
94c6801eb828627c37b8992584767c095dfe11df62Jin Cao
95c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public void clearSearchQuery() {
96c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mQueryText.setText("");
97c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
98c6801eb828627c37b8992584767c095dfe11df62Jin Cao
99c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public void focusSearchBar(boolean hasFocus) {
100c6801eb828627c37b8992584767c095dfe11df62Jin Cao        if (hasFocus) {
101a70ab69fd489a1f10dd75fc84214bd970096ae02Jin Cao            mQueryText.requestFocus();
102c6801eb828627c37b8992584767c095dfe11df62Jin Cao            mImm.showSoftInput(mQueryText, 0);
103c6801eb828627c37b8992584767c095dfe11df62Jin Cao        } else {
104c6801eb828627c37b8992584767c095dfe11df62Jin Cao            mImm.hideSoftInputFromWindow(mQueryText.getWindowToken(), 0);
105c6801eb828627c37b8992584767c095dfe11df62Jin Cao        }
106c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
107c6801eb828627c37b8992584767c095dfe11df62Jin Cao
108524ded5f9d27dda75c53d256922a39c867857575Jin Cao    public void adjustViewForTwoPaneLandscape(boolean alignWithTL, int xEnd) {
109524ded5f9d27dda75c53d256922a39c867857575Jin Cao        final ViewGroup.LayoutParams params = getLayoutParams();
110524ded5f9d27dda75c53d256922a39c867857575Jin Cao        if (alignWithTL) {
111524ded5f9d27dda75c53d256922a39c867857575Jin Cao            setBackgroundDrawable(mTwoPaneLandConvModeBackgroundDrawable);
112524ded5f9d27dda75c53d256922a39c867857575Jin Cao            mBackButton.setImageResource(mTwoPaneLandConvModeBackButtonDrawable);
113524ded5f9d27dda75c53d256922a39c867857575Jin Cao            if (mShowingClose) {
114524ded5f9d27dda75c53d256922a39c867857575Jin Cao                mEndingButton.setImageResource(mTwoPaneLandConvModeClearTextButtonDrawable);
115524ded5f9d27dda75c53d256922a39c867857575Jin Cao            } else {
116524ded5f9d27dda75c53d256922a39c867857575Jin Cao                mEndingButton.setImageResource(mTwoPaneLandConvModeVoiceButtonDrawable);
117524ded5f9d27dda75c53d256922a39c867857575Jin Cao            }
118524ded5f9d27dda75c53d256922a39c867857575Jin Cao            mQueryText.setTextColor(mTwoPaneLandConvModeTextColor);
119524ded5f9d27dda75c53d256922a39c867857575Jin Cao
120524ded5f9d27dda75c53d256922a39c867857575Jin Cao            if (ViewUtils.isViewRtl(this)) {
121524ded5f9d27dda75c53d256922a39c867857575Jin Cao                int[] coords = new int[2];
122524ded5f9d27dda75c53d256922a39c867857575Jin Cao                getLocationInWindow(coords);
123524ded5f9d27dda75c53d256922a39c867857575Jin Cao                params.width = coords[0] + getWidth() - xEnd;
124524ded5f9d27dda75c53d256922a39c867857575Jin Cao            } else {
125524ded5f9d27dda75c53d256922a39c867857575Jin Cao                params.width = xEnd;
126524ded5f9d27dda75c53d256922a39c867857575Jin Cao            }
127524ded5f9d27dda75c53d256922a39c867857575Jin Cao        } else {
128524ded5f9d27dda75c53d256922a39c867857575Jin Cao            setBackgroundDrawable(mNormalBackgroundDrawable);
129524ded5f9d27dda75c53d256922a39c867857575Jin Cao            mBackButton.setImageResource(mNormalBackButtonDrawable);
130524ded5f9d27dda75c53d256922a39c867857575Jin Cao            if (mShowingClose) {
131524ded5f9d27dda75c53d256922a39c867857575Jin Cao                mEndingButton.setImageResource(mNormalClearTextButtonDrawable);
132524ded5f9d27dda75c53d256922a39c867857575Jin Cao            } else {
133524ded5f9d27dda75c53d256922a39c867857575Jin Cao                mEndingButton.setImageResource(mNormalVoiceButtonDrawable);
134524ded5f9d27dda75c53d256922a39c867857575Jin Cao            }
135524ded5f9d27dda75c53d256922a39c867857575Jin Cao            mQueryText.setTextColor(mNormalTextColor);
136524ded5f9d27dda75c53d256922a39c867857575Jin Cao            params.width = ViewGroup.LayoutParams.MATCH_PARENT;
137524ded5f9d27dda75c53d256922a39c867857575Jin Cao        }
138524ded5f9d27dda75c53d256922a39c867857575Jin Cao        setLayoutParams(params);
139524ded5f9d27dda75c53d256922a39c867857575Jin Cao    }
140524ded5f9d27dda75c53d256922a39c867857575Jin Cao
141c6801eb828627c37b8992584767c095dfe11df62Jin Cao    @Override
142c6801eb828627c37b8992584767c095dfe11df62Jin Cao    protected void onFinishInflate() {
143c6801eb828627c37b8992584767c095dfe11df62Jin Cao        super.onFinishInflate();
144c6801eb828627c37b8992584767c095dfe11df62Jin Cao
145c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
146524ded5f9d27dda75c53d256922a39c867857575Jin Cao        mBackButton = (ImageView) findViewById(R.id.search_actionbar_back_button);
147c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mBackButton.setOnClickListener(this);
148c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mQueryText = (EditText) findViewById(R.id.search_actionbar_query_text);
149c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mQueryText.addTextChangedListener(this);
150c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mQueryText.setOnClickListener(this);
151c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mQueryText.setOnEditorActionListener(this);
15264168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao        mQueryText.setOnKeyListener(this);
153c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mEndingButton = (ImageView) findViewById(R.id.search_actionbar_ending_button);
154c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mEndingButton.setOnClickListener(this);
1558ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao        setupEndingButton(mQueryText.getText());
1568ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao    }
1578ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao
1588ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao    private void setupEndingButton(CharSequence currentText) {
1598ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao        final Resources res = getResources();
1608ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao        if (!mSupportVoice || currentText.length() > 0) {
1618ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao            mShowingClose = true;
1628ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao            mEndingButton.setImageResource(R.drawable.ic_close_24dp);
1638ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao            mEndingButton.setContentDescription(res.getString(R.string.search_clear_desc));
1648ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao        } else {
1658ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao            mShowingClose = false;
1668ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao            mEndingButton.setImageResource(R.drawable.ic_mic_24dp);
1678ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao            mEndingButton.setContentDescription(res.getString(R.string.search_voice_desc));
1688ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao        }
169c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
170c6801eb828627c37b8992584767c095dfe11df62Jin Cao
171c6801eb828627c37b8992584767c095dfe11df62Jin Cao    @Override
172c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
173c6801eb828627c37b8992584767c095dfe11df62Jin Cao        // Only care about onTextChanged
174c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
175c6801eb828627c37b8992584767c095dfe11df62Jin Cao
176c6801eb828627c37b8992584767c095dfe11df62Jin Cao    @Override
177c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
178c6801eb828627c37b8992584767c095dfe11df62Jin Cao        mController.onQueryTextChanged(charSequence.toString());
1798ebcda94b7f6c91c2a7c4bbe9d1911ca63b37855Jin Cao        setupEndingButton(charSequence);
180c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
181c6801eb828627c37b8992584767c095dfe11df62Jin Cao
182c6801eb828627c37b8992584767c095dfe11df62Jin Cao    @Override
183c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public void afterTextChanged(Editable editable) {
184c6801eb828627c37b8992584767c095dfe11df62Jin Cao        // Only care about onTextChanged
185c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
186c6801eb828627c37b8992584767c095dfe11df62Jin Cao
187c6801eb828627c37b8992584767c095dfe11df62Jin Cao    @Override
188c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public void onClick(View view) {
189c6801eb828627c37b8992584767c095dfe11df62Jin Cao        if (view == mBackButton) {
190c6801eb828627c37b8992584767c095dfe11df62Jin Cao            mController.onSearchCanceled();
191c6801eb828627c37b8992584767c095dfe11df62Jin Cao            mQueryText.setText("");
192c6801eb828627c37b8992584767c095dfe11df62Jin Cao        } else if (view == mEndingButton) {
193c6801eb828627c37b8992584767c095dfe11df62Jin Cao            if (mShowingClose) {
194c6801eb828627c37b8992584767c095dfe11df62Jin Cao                mQueryText.setText("");
195c6801eb828627c37b8992584767c095dfe11df62Jin Cao                mController.showSearchActionBar(
196c6801eb828627c37b8992584767c095dfe11df62Jin Cao                        MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE);
197c6801eb828627c37b8992584767c095dfe11df62Jin Cao            } else {
198c6801eb828627c37b8992584767c095dfe11df62Jin Cao                mController.onVoiceSearch();
199c6801eb828627c37b8992584767c095dfe11df62Jin Cao            }
200c6801eb828627c37b8992584767c095dfe11df62Jin Cao        } else if (view == mQueryText) {
201c6801eb828627c37b8992584767c095dfe11df62Jin Cao            mController.showSearchActionBar(MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE);
202c6801eb828627c37b8992584767c095dfe11df62Jin Cao        }
203c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
204c6801eb828627c37b8992584767c095dfe11df62Jin Cao
205c6801eb828627c37b8992584767c095dfe11df62Jin Cao    @Override
206c6801eb828627c37b8992584767c095dfe11df62Jin Cao    public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
207c6801eb828627c37b8992584767c095dfe11df62Jin Cao        if (actionId == EditorInfo.IME_ACTION_SEARCH) {
208c6801eb828627c37b8992584767c095dfe11df62Jin Cao            mController.onSearchPerformed(mQueryText.getText().toString());
209c6801eb828627c37b8992584767c095dfe11df62Jin Cao        }
210c6801eb828627c37b8992584767c095dfe11df62Jin Cao        return false;
211c6801eb828627c37b8992584767c095dfe11df62Jin Cao    }
21264168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao
21364168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao    @Override
21464168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao    public boolean onKey(View v, int keyCode, KeyEvent event) {
21564168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao        // Hardware keyboard doesn't represent Enter as Search through imeOptions, so we need to
21664168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao        // capture them manually here.
21764168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao        if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) {
21864168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao            mController.onSearchPerformed(mQueryText.getText().toString());
21964168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao        }
22064168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao        return false;
22164168c6e3a4b770f3d60ef4b7d7a330046e5185eJin Cao    }
222c6801eb828627c37b8992584767c095dfe11df62Jin Cao}
223