MaterialSearchActionView.java revision 524ded5f9d27dda75c53d256922a39c867857575
1/* 2 * Copyright (C) 2014 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.mail.ui; 19 20import android.content.Context; 21import android.content.res.Resources; 22import android.graphics.drawable.ColorDrawable; 23import android.graphics.drawable.Drawable; 24import android.support.annotation.DrawableRes; 25import android.text.Editable; 26import android.text.TextWatcher; 27import android.util.AttributeSet; 28import android.view.KeyEvent; 29import android.view.View; 30import android.view.ViewGroup; 31import android.view.inputmethod.EditorInfo; 32import android.view.inputmethod.InputMethodManager; 33import android.widget.EditText; 34import android.widget.ImageView; 35import android.widget.LinearLayout; 36import android.widget.TextView; 37 38import com.android.mail.R; 39import com.android.mail.utils.ViewUtils; 40 41/** 42 * Custom view for the action bar when search is displayed. 43 */ 44public class MaterialSearchActionView extends LinearLayout implements TextWatcher, 45 View.OnClickListener, TextView.OnEditorActionListener, View.OnKeyListener { 46 private Drawable mNormalBackgroundDrawable; 47 private Drawable mTwoPaneLandConvModeBackgroundDrawable; 48 private @DrawableRes int mNormalBackButtonDrawable; 49 private @DrawableRes int mTwoPaneLandConvModeBackButtonDrawable; 50 private @DrawableRes int mNormalClearTextButtonDrawable; 51 private @DrawableRes int mTwoPaneLandConvModeClearTextButtonDrawable; 52 private @DrawableRes int mNormalVoiceButtonDrawable; 53 private @DrawableRes int mTwoPaneLandConvModeVoiceButtonDrawable; 54 private int mNormalTextColor; 55 private int mTwoPaneLandConvModeTextColor; 56 57 private MaterialSearchViewController mController; 58 private InputMethodManager mImm; 59 private boolean mShowingClose; 60 private boolean mSupportVoice; 61 62 private ImageView mBackButton; 63 private EditText mQueryText; 64 private ImageView mEndingButton; 65 66 public MaterialSearchActionView(Context context) { 67 this(context, null); 68 } 69 70 public MaterialSearchActionView(Context context, AttributeSet attrs) { 71 super(context, attrs); 72 73 final Resources res = getResources(); 74 mNormalBackgroundDrawable = new ColorDrawable(res.getColor(android.R.color.white)); 75 mTwoPaneLandConvModeBackgroundDrawable = 76 new ColorDrawable(res.getColor(R.color.actionbar_color)); 77 mNormalBackButtonDrawable = R.drawable.ic_arrow_back_24dp_with_rtl; 78 mTwoPaneLandConvModeBackButtonDrawable = R.drawable.ic_arrow_back_wht_24dp; 79 mNormalClearTextButtonDrawable = R.drawable.ic_close_24dp; 80 mTwoPaneLandConvModeClearTextButtonDrawable = R.drawable.ic_close_wht_24dp; 81 mNormalVoiceButtonDrawable = R.drawable.ic_mic_24dp; 82 mTwoPaneLandConvModeVoiceButtonDrawable = R.drawable.ic_mic_white_24dp; 83 mNormalTextColor = res.getColor(R.color.search_query_text); 84 mTwoPaneLandConvModeTextColor = res.getColor(android.R.color.white); 85 } 86 87 // PUBLIC API 88 public void setController(MaterialSearchViewController controller, String initialQuery, 89 boolean supportVoice) { 90 mController = controller; 91 mQueryText.setText(initialQuery); 92 mSupportVoice = supportVoice; 93 } 94 95 public void clearSearchQuery() { 96 mQueryText.setText(""); 97 } 98 99 public void focusSearchBar(boolean hasFocus) { 100 if (hasFocus) { 101 mQueryText.requestFocus(); 102 mImm.showSoftInput(mQueryText, 0); 103 } else { 104 mImm.hideSoftInputFromWindow(mQueryText.getWindowToken(), 0); 105 } 106 } 107 108 public void adjustViewForTwoPaneLandscape(boolean alignWithTL, int xEnd) { 109 final ViewGroup.LayoutParams params = getLayoutParams(); 110 if (alignWithTL) { 111 setBackgroundDrawable(mTwoPaneLandConvModeBackgroundDrawable); 112 mBackButton.setImageResource(mTwoPaneLandConvModeBackButtonDrawable); 113 if (mShowingClose) { 114 mEndingButton.setImageResource(mTwoPaneLandConvModeClearTextButtonDrawable); 115 } else { 116 mEndingButton.setImageResource(mTwoPaneLandConvModeVoiceButtonDrawable); 117 } 118 mQueryText.setTextColor(mTwoPaneLandConvModeTextColor); 119 120 if (ViewUtils.isViewRtl(this)) { 121 int[] coords = new int[2]; 122 getLocationInWindow(coords); 123 params.width = coords[0] + getWidth() - xEnd; 124 } else { 125 params.width = xEnd; 126 } 127 } else { 128 setBackgroundDrawable(mNormalBackgroundDrawable); 129 mBackButton.setImageResource(mNormalBackButtonDrawable); 130 if (mShowingClose) { 131 mEndingButton.setImageResource(mNormalClearTextButtonDrawable); 132 } else { 133 mEndingButton.setImageResource(mNormalVoiceButtonDrawable); 134 } 135 mQueryText.setTextColor(mNormalTextColor); 136 params.width = ViewGroup.LayoutParams.MATCH_PARENT; 137 } 138 setLayoutParams(params); 139 } 140 141 @Override 142 protected void onFinishInflate() { 143 super.onFinishInflate(); 144 145 mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 146 mBackButton = (ImageView) findViewById(R.id.search_actionbar_back_button); 147 mBackButton.setOnClickListener(this); 148 mQueryText = (EditText) findViewById(R.id.search_actionbar_query_text); 149 mQueryText.addTextChangedListener(this); 150 mQueryText.setOnClickListener(this); 151 mQueryText.setOnEditorActionListener(this); 152 mQueryText.setOnKeyListener(this); 153 mEndingButton = (ImageView) findViewById(R.id.search_actionbar_ending_button); 154 mEndingButton.setOnClickListener(this); 155 setupEndingButton(mQueryText.getText()); 156 } 157 158 private void setupEndingButton(CharSequence currentText) { 159 final Resources res = getResources(); 160 if (!mSupportVoice || currentText.length() > 0) { 161 mShowingClose = true; 162 mEndingButton.setImageResource(R.drawable.ic_close_24dp); 163 mEndingButton.setContentDescription(res.getString(R.string.search_clear_desc)); 164 } else { 165 mShowingClose = false; 166 mEndingButton.setImageResource(R.drawable.ic_mic_24dp); 167 mEndingButton.setContentDescription(res.getString(R.string.search_voice_desc)); 168 } 169 } 170 171 @Override 172 public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { 173 // Only care about onTextChanged 174 } 175 176 @Override 177 public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { 178 mController.onQueryTextChanged(charSequence.toString()); 179 setupEndingButton(charSequence); 180 } 181 182 @Override 183 public void afterTextChanged(Editable editable) { 184 // Only care about onTextChanged 185 } 186 187 @Override 188 public void onClick(View view) { 189 if (view == mBackButton) { 190 mController.onSearchCanceled(); 191 mQueryText.setText(""); 192 } else if (view == mEndingButton) { 193 if (mShowingClose) { 194 mQueryText.setText(""); 195 mController.showSearchActionBar( 196 MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE); 197 } else { 198 mController.onVoiceSearch(); 199 } 200 } else if (view == mQueryText) { 201 mController.showSearchActionBar(MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE); 202 } 203 } 204 205 @Override 206 public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { 207 if (actionId == EditorInfo.IME_ACTION_SEARCH) { 208 mController.onSearchPerformed(mQueryText.getText().toString()); 209 } 210 return false; 211 } 212 213 @Override 214 public boolean onKey(View v, int keyCode, KeyEvent event) { 215 // Hardware keyboard doesn't represent Enter as Search through imeOptions, so we need to 216 // capture them manually here. 217 if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) { 218 mController.onSearchPerformed(mQueryText.getText().toString()); 219 } 220 return false; 221 } 222} 223