Home | History | Annotate | Download | only in ui
      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 
     18 package com.android.mail.ui;
     19 
     20 import android.content.Context;
     21 import android.content.res.Resources;
     22 import android.graphics.drawable.ColorDrawable;
     23 import android.graphics.drawable.Drawable;
     24 import android.support.annotation.DrawableRes;
     25 import android.text.Editable;
     26 import android.text.TextWatcher;
     27 import android.util.AttributeSet;
     28 import android.view.ActionMode;
     29 import android.view.KeyEvent;
     30 import android.view.Menu;
     31 import android.view.MenuItem;
     32 import android.view.View;
     33 import android.view.ViewGroup;
     34 import android.view.inputmethod.EditorInfo;
     35 import android.view.inputmethod.InputMethodManager;
     36 import android.widget.EditText;
     37 import android.widget.ImageView;
     38 import android.widget.LinearLayout;
     39 import android.widget.TextView;
     40 
     41 import com.android.mail.R;
     42 import com.android.mail.utils.ViewUtils;
     43 
     44 /**
     45  * Custom view for the action bar when search is displayed.
     46  */
     47 public class MaterialSearchActionView extends LinearLayout implements TextWatcher,
     48         View.OnClickListener, TextView.OnEditorActionListener, View.OnKeyListener {
     49     // Dark drawables are used for when the search bar is visible (thus dark icon on light bg).
     50     // Light drawables are used when we are showing the default action bar.
     51     private Drawable mLightBgDrawable;
     52     private Drawable mDarkBgDrawable;
     53     private @DrawableRes int mLightBgBackDrawable;
     54     private @DrawableRes int mDarkBgBackDrawable;
     55     private @DrawableRes int mLightBgClearTextDrawable;
     56     private @DrawableRes int mDarkBgClearTextDrawable;
     57     private @DrawableRes int mLightBgVoiceDrawable;
     58     private @DrawableRes int mDarkBgVoiceDrawable;
     59     private int mLightBgTextColor;
     60     private int mDarkBgTextColor;
     61 
     62     private MaterialSearchViewController mController;
     63     private InputMethodManager mImm;
     64     private boolean mSupportVoice;
     65     private boolean mShowingClearButton;
     66     private boolean mAlignWithTl;
     67 
     68     private ImageView mBackButton;
     69     private EditText mQueryText;
     70     private ImageView mEndingButton;
     71 
     72     public MaterialSearchActionView(Context context) {
     73         this(context, null);
     74     }
     75 
     76     public MaterialSearchActionView(Context context, AttributeSet attrs) {
     77         super(context, attrs);
     78 
     79         final Resources res = getResources();
     80         mLightBgDrawable = new ColorDrawable(res.getColor(android.R.color.white));
     81         mDarkBgDrawable = new ColorDrawable(res.getColor(R.color.primary_color));
     82         mLightBgBackDrawable = R.drawable.ic_arrow_back_24dp_with_rtl;
     83         mDarkBgBackDrawable = R.drawable.ic_arrow_back_wht_24dp_with_rtl;
     84         mLightBgClearTextDrawable = R.drawable.ic_close_24dp;
     85         mDarkBgClearTextDrawable = R.drawable.ic_close_wht_24dp;
     86         mLightBgVoiceDrawable = R.drawable.ic_mic_24dp;
     87         mDarkBgVoiceDrawable = R.drawable.ic_mic_wht_24dp;
     88         mLightBgTextColor = res.getColor(R.color.search_query_text);
     89         mDarkBgTextColor = res.getColor(android.R.color.white);
     90     }
     91 
     92     // PUBLIC API
     93     public void setController(MaterialSearchViewController controller, String initialQuery,
     94             boolean supportVoice) {
     95         mController = controller;
     96         mQueryText.setText(initialQuery);
     97         mSupportVoice = supportVoice;
     98     }
     99 
    100     public void clearSearchQuery() {
    101         mQueryText.setText("");
    102     }
    103 
    104     public void focusSearchBar(boolean hasFocus) {
    105         if (hasFocus) {
    106             mQueryText.requestFocus();
    107             mImm.showSoftInput(mQueryText, 0);
    108         } else {
    109             mImm.hideSoftInputFromWindow(mQueryText.getWindowToken(), 0);
    110         }
    111     }
    112 
    113     public void adjustViewForTwoPaneLandscape(boolean alignWithTl, int xEnd) {
    114         mAlignWithTl = alignWithTl;
    115         final ViewGroup.LayoutParams params = getLayoutParams();
    116         if (alignWithTl) {
    117             setBackgroundDrawable(mDarkBgDrawable);
    118             mBackButton.setImageResource(mDarkBgBackDrawable);
    119             mQueryText.setTextColor(mDarkBgTextColor);
    120 
    121             if (ViewUtils.isViewRtl(this)) {
    122                 int[] coords = new int[2];
    123                 getLocationInWindow(coords);
    124                 params.width = coords[0] + getWidth() - xEnd;
    125             } else {
    126                 params.width = xEnd;
    127             }
    128         } else {
    129             setBackgroundDrawable(mLightBgDrawable);
    130             mBackButton.setImageResource(mLightBgBackDrawable);
    131             mQueryText.setTextColor(mLightBgTextColor);
    132             params.width = ViewGroup.LayoutParams.MATCH_PARENT;
    133         }
    134         setupEndingButton(mQueryText.getText());
    135         setLayoutParams(params);
    136     }
    137 
    138     @Override
    139     protected void onFinishInflate() {
    140         super.onFinishInflate();
    141 
    142         mImm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
    143         mBackButton = (ImageView) findViewById(R.id.search_actionbar_back_button);
    144         mBackButton.setOnClickListener(this);
    145         mQueryText = (EditText) findViewById(R.id.search_actionbar_query_text);
    146         mQueryText.addTextChangedListener(this);
    147         mQueryText.setOnClickListener(this);
    148         mQueryText.setOnEditorActionListener(this);
    149         mQueryText.setOnKeyListener(this);
    150         // Disable CAB for search edittext
    151         mQueryText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
    152             @Override
    153             public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    154                 return false;
    155             }
    156 
    157             @Override
    158             public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
    159                 return false;
    160             }
    161 
    162             @Override
    163             public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
    164                 return false;
    165             }
    166 
    167             @Override
    168             public void onDestroyActionMode(ActionMode mode) {
    169             }
    170         });
    171         mEndingButton = (ImageView) findViewById(R.id.search_actionbar_ending_button);
    172         mEndingButton.setOnClickListener(this);
    173         setupEndingButton(mQueryText.getText());
    174     }
    175 
    176     private void setupEndingButton(CharSequence currentText) {
    177         final Resources res = getResources();
    178         if (!mSupportVoice || currentText.length() > 0) {
    179             if (mAlignWithTl) {
    180                 mEndingButton.setImageResource(mDarkBgClearTextDrawable);
    181             } else {
    182                 mEndingButton.setImageResource(mLightBgClearTextDrawable);
    183             }
    184             mEndingButton.setContentDescription(res.getString(R.string.search_clear_desc));
    185             mShowingClearButton = true;
    186         } else {
    187             if (mAlignWithTl) {
    188                 mEndingButton.setImageResource(mDarkBgVoiceDrawable);
    189             } else {
    190                 mEndingButton.setImageResource(mLightBgVoiceDrawable);
    191             }
    192             mEndingButton.setContentDescription(res.getString(R.string.search_voice_desc));
    193             mShowingClearButton = false;
    194         }
    195     }
    196 
    197     @Override
    198     public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
    199         // Only care about onTextChanged
    200     }
    201 
    202     @Override
    203     public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
    204         mController.onQueryTextChanged(charSequence.toString());
    205         setupEndingButton(charSequence);
    206     }
    207 
    208     @Override
    209     public void afterTextChanged(Editable editable) {
    210         // Only care about onTextChanged
    211     }
    212 
    213     @Override
    214     public void onClick(View view) {
    215         if (view == mBackButton) {
    216             mController.onSearchCanceled();
    217         } else if (view == mEndingButton) {
    218             if (mShowingClearButton) {
    219                 mQueryText.setText("");
    220                 mController.showSearchActionBar(
    221                         MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE);
    222             } else {
    223                 mController.onVoiceSearch();
    224             }
    225         } else if (view == mQueryText) {
    226             mController.showSearchActionBar(MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE);
    227         }
    228     }
    229 
    230     @Override
    231     public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
    232         if (actionId == EditorInfo.IME_ACTION_SEARCH) {
    233             mController.onSearchPerformed(mQueryText.getText().toString());
    234         }
    235         return false;
    236     }
    237 
    238     @Override
    239     public boolean onKey(View v, int keyCode, KeyEvent event) {
    240         // Hardware keyboard doesn't represent Enter as Search through imeOptions, so we need to
    241         // capture them manually here.
    242         if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) {
    243             mController.onSearchPerformed(mQueryText.getText().toString());
    244         }
    245         return false;
    246     }
    247 }
    248