| /* |
| * Copyright (C) 2014 Google Inc. |
| * Licensed to The Android Open Source Project. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.mail.ui; |
| |
| import android.content.Context; |
| import android.content.res.Resources; |
| import android.graphics.drawable.ColorDrawable; |
| import android.graphics.drawable.Drawable; |
| import android.support.annotation.DrawableRes; |
| import android.text.Editable; |
| import android.text.TextWatcher; |
| import android.util.AttributeSet; |
| import android.view.ActionMode; |
| import android.view.KeyEvent; |
| import android.view.Menu; |
| import android.view.MenuItem; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.inputmethod.EditorInfo; |
| import android.view.inputmethod.InputMethodManager; |
| import android.widget.EditText; |
| import android.widget.ImageView; |
| import android.widget.LinearLayout; |
| import android.widget.TextView; |
| import android.widget.Toast; |
| |
| import com.android.mail.R; |
| import com.android.mail.utils.ViewUtils; |
| |
| /** |
| * Custom view for the action bar when search is displayed. |
| */ |
| public class MaterialSearchActionView extends LinearLayout implements TextWatcher, |
| View.OnClickListener, TextView.OnEditorActionListener, View.OnKeyListener { |
| // Dark drawables are used for when the search bar is visible (thus dark icon on light bg). |
| // Light drawables are used when we are showing the default action bar. |
| private Drawable mLightBgDrawable; |
| private Drawable mDarkBgDrawable; |
| private @DrawableRes int mLightBgBackDrawable; |
| private @DrawableRes int mDarkBgBackDrawable; |
| private @DrawableRes int mLightBgClearTextDrawable; |
| private @DrawableRes int mDarkBgClearTextDrawable; |
| private @DrawableRes int mLightBgVoiceDrawable; |
| private @DrawableRes int mDarkBgVoiceDrawable; |
| private int mLightBgTextColor; |
| private int mDarkBgTextColor; |
| |
| private MaterialSearchViewController mController; |
| private InputMethodManager mImm; |
| private boolean mSupportVoice; |
| private boolean mShowingClearButton; |
| private boolean mAlignWithTl; |
| |
| private ImageView mBackButton; |
| private EditText mQueryText; |
| private ImageView mEndingButton; |
| private Context mContext; |
| public final static int SEARCH_INPUT_LIMIT_NUMBER = 40; |
| |
| public MaterialSearchActionView(Context context) { |
| this(context, null); |
| } |
| |
| public MaterialSearchActionView(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| |
| final Resources res = getResources(); |
| mLightBgDrawable = new ColorDrawable(res.getColor(android.R.color.white)); |
| mDarkBgDrawable = new ColorDrawable(res.getColor(R.color.primary_color)); |
| mLightBgBackDrawable = R.drawable.ic_arrow_back_24dp_with_rtl; |
| mDarkBgBackDrawable = R.drawable.ic_arrow_back_wht_24dp_with_rtl; |
| mLightBgClearTextDrawable = R.drawable.ic_close_24dp; |
| mDarkBgClearTextDrawable = R.drawable.ic_close_wht_24dp; |
| mLightBgVoiceDrawable = R.drawable.ic_mic_24dp; |
| mDarkBgVoiceDrawable = R.drawable.ic_mic_wht_24dp; |
| mLightBgTextColor = res.getColor(R.color.search_query_text); |
| mDarkBgTextColor = res.getColor(android.R.color.white); |
| |
| mContext = context; |
| } |
| |
| // PUBLIC API |
| public void setController(MaterialSearchViewController controller, String initialQuery, |
| boolean supportVoice) { |
| mController = controller; |
| mQueryText.setText(initialQuery); |
| mSupportVoice = supportVoice; |
| } |
| |
| public void clearSearchQuery() { |
| mQueryText.setText(""); |
| } |
| |
| public void focusSearchBar(boolean hasFocus) { |
| if (hasFocus) { |
| mQueryText.requestFocus(); |
| mImm.showSoftInput(mQueryText, 0); |
| } else { |
| mImm.hideSoftInputFromWindow(mQueryText.getWindowToken(), 0); |
| } |
| } |
| |
| public void adjustViewForTwoPaneLandscape(boolean alignWithTl, int xEnd) { |
| mAlignWithTl = alignWithTl; |
| final ViewGroup.LayoutParams params = getLayoutParams(); |
| if (alignWithTl) { |
| setBackgroundDrawable(mDarkBgDrawable); |
| mBackButton.setImageResource(mDarkBgBackDrawable); |
| mQueryText.setTextColor(mDarkBgTextColor); |
| |
| if (ViewUtils.isViewRtl(this)) { |
| int[] coords = new int[2]; |
| getLocationInWindow(coords); |
| params.width = coords[0] + getWidth() - xEnd; |
| } else { |
| params.width = xEnd; |
| } |
| } else { |
| setBackgroundDrawable(mLightBgDrawable); |
| mBackButton.setImageResource(mLightBgBackDrawable); |
| mQueryText.setTextColor(mLightBgTextColor); |
| params.width = ViewGroup.LayoutParams.MATCH_PARENT; |
| } |
| setupEndingButton(mQueryText.getText()); |
| setLayoutParams(params); |
| } |
| |
| @Override |
| protected void onFinishInflate() { |
| super.onFinishInflate(); |
| |
| mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); |
| mBackButton = (ImageView) findViewById(R.id.search_actionbar_back_button); |
| mBackButton.setOnClickListener(this); |
| mQueryText = (EditText) findViewById(R.id.search_actionbar_query_text); |
| mQueryText.addTextChangedListener(this); |
| mQueryText.setOnClickListener(this); |
| mQueryText.setOnEditorActionListener(this); |
| mQueryText.setOnKeyListener(this); |
| // Disable CAB for search edittext |
| mQueryText.setCustomSelectionActionModeCallback(new ActionMode.Callback() { |
| @Override |
| public boolean onCreateActionMode(ActionMode mode, Menu menu) { |
| return false; |
| } |
| |
| @Override |
| public boolean onPrepareActionMode(ActionMode mode, Menu menu) { |
| return false; |
| } |
| |
| @Override |
| public boolean onActionItemClicked(ActionMode mode, MenuItem item) { |
| return false; |
| } |
| |
| @Override |
| public void onDestroyActionMode(ActionMode mode) { |
| } |
| }); |
| mEndingButton = (ImageView) findViewById(R.id.search_actionbar_ending_button); |
| mEndingButton.setOnClickListener(this); |
| setupEndingButton(mQueryText.getText()); |
| } |
| |
| private void setupEndingButton(CharSequence currentText) { |
| final Resources res = getResources(); |
| if (!mSupportVoice || currentText.length() > 0) { |
| if (mAlignWithTl) { |
| mEndingButton.setImageResource(mDarkBgClearTextDrawable); |
| } else { |
| mEndingButton.setImageResource(mLightBgClearTextDrawable); |
| } |
| mEndingButton.setContentDescription(res.getString(R.string.search_clear_desc)); |
| mShowingClearButton = true; |
| } else { |
| if (mAlignWithTl) { |
| mEndingButton.setImageResource(mDarkBgVoiceDrawable); |
| } else { |
| mEndingButton.setImageResource(mLightBgVoiceDrawable); |
| } |
| mEndingButton.setContentDescription(res.getString(R.string.search_voice_desc)); |
| mShowingClearButton = false; |
| } |
| } |
| |
| @Override |
| public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { |
| // Only care about onTextChanged |
| } |
| |
| @Override |
| public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { |
| mController.onQueryTextChanged(charSequence.toString()); |
| setupEndingButton(charSequence); |
| limitInputLength(charSequence); |
| } |
| |
| private void limitInputLength(CharSequence charSequence) { |
| if(charSequence.length()>=SEARCH_INPUT_LIMIT_NUMBER){ |
| Toast.makeText(mContext,R.string.search_input_limit_number,Toast.LENGTH_LONG).show(); |
| } |
| |
| } |
| |
| @Override |
| public void afterTextChanged(Editable editable) { |
| // Only care about onTextChanged |
| } |
| |
| @Override |
| public void onClick(View view) { |
| if (view == mBackButton) { |
| mController.onSearchCanceled(); |
| } else if (view == mEndingButton) { |
| if (mShowingClearButton) { |
| mQueryText.setText(""); |
| mController.showSearchActionBar( |
| MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE); |
| } else { |
| mController.onVoiceSearch(); |
| } |
| } else if (view == mQueryText) { |
| mController.showSearchActionBar(MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE); |
| } |
| } |
| |
| @Override |
| public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { |
| if (actionId == EditorInfo.IME_ACTION_SEARCH) { |
| mController.onSearchPerformed(mQueryText.getText().toString()); |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean onKey(View v, int keyCode, KeyEvent event) { |
| // Hardware keyboard doesn't represent Enter as Search through imeOptions, so we need to |
| // capture them manually here. |
| if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) { |
| mController.onSearchPerformed(mQueryText.getText().toString()); |
| return true; |
| } |
| return false; |
| } |
| |
| public String getQueryText(){ |
| return mQueryText.getText().toString(); |
| } |
| |
| public void setQueryText(String query){ |
| mQueryText.setText(query); |
| } |
| } |