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