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.app.SearchManager;
     21 import android.content.Context;
     22 import android.database.Cursor;
     23 import android.net.Uri;
     24 import android.os.AsyncTask;
     25 import android.util.AttributeSet;
     26 import android.view.LayoutInflater;
     27 import android.view.View;
     28 import android.view.ViewGroup;
     29 import android.widget.AdapterView;
     30 import android.widget.BaseAdapter;
     31 import android.widget.ImageView;
     32 import android.widget.LinearLayout;
     33 import android.widget.ListView;
     34 import android.widget.TextView;
     35 
     36 import com.android.mail.R;
     37 import com.android.mail.providers.SearchRecentSuggestionsProvider;
     38 import com.google.common.collect.Lists;
     39 
     40 import java.util.List;
     41 
     42 /**
     43  * Custom quantum-styled search view that overlays the main activity.
     44  */
     45 public class MaterialSearchSuggestionsList extends LinearLayout
     46         implements AdapterView.OnItemClickListener, View.OnClickListener {
     47     private MaterialSearchViewController mController;
     48     private SearchRecentSuggestionsProvider mSuggestionsProvider;
     49     private List<SuggestionItem> mSuggestions = Lists.newArrayList();
     50     private String mQuery;
     51 
     52     private MaterialSearchViewListAdapter mAdapter;
     53     private QuerySuggestionsTask mQueryTask;
     54 
     55     public MaterialSearchSuggestionsList(Context context) {
     56         super(context);
     57     }
     58 
     59     public MaterialSearchSuggestionsList(Context context, AttributeSet attrs) {
     60         super(context, attrs);
     61     }
     62 
     63     // PUBLIC API
     64     public void setController(MaterialSearchViewController controller,
     65             SearchRecentSuggestionsProvider suggestionsProvider) {
     66         mController = controller;
     67         mSuggestionsProvider = suggestionsProvider;
     68     }
     69 
     70     public void setQuery(String query) {
     71         mQuery = query;
     72         if (mQueryTask != null) {
     73             mQueryTask.cancel(true);
     74         }
     75         mQueryTask = new QuerySuggestionsTask();
     76         mQueryTask.execute(query);
     77     }
     78 
     79     // PRIVATE API
     80     @Override
     81     protected void onFinishInflate() {
     82         super.onFinishInflate();
     83 
     84         final ListView listView = (ListView) findViewById(R.id.search_overlay_suggestion_list);
     85         listView.setOnItemClickListener(this);
     86         final View dummyHolder = findViewById(R.id.search_overlay_scrim);
     87         dummyHolder.setOnClickListener(this);
     88 
     89         // set up the adapter
     90         mAdapter = new MaterialSearchViewListAdapter(getContext(), R.layout.search_suggestion_item);
     91         listView.setAdapter(mAdapter);
     92     }
     93 
     94     @Override
     95     public void setVisibility(int visibility) {
     96         if (!isShown() && visibility == VISIBLE) {
     97             // When we go from gone to visible, re-query for suggestions in case they changed.
     98             setQuery(mQuery);
     99         }
    100         super.setVisibility(visibility);
    101     }
    102 
    103     @Override
    104     public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
    105         mController.onSearchPerformed(mSuggestions.get(position).suggestion);
    106     }
    107 
    108     @Override
    109     public void onClick(View view) {
    110         mController.showSearchActionBar(
    111                 MaterialSearchViewController.SEARCH_VIEW_STATE_ONLY_ACTIONBAR);
    112     }
    113 
    114     // Background task for querying the suggestions list
    115     private class QuerySuggestionsTask extends AsyncTask<String, Void, List<SuggestionItem>> {
    116         @Override
    117         protected List<SuggestionItem> doInBackground(String... strings) {
    118             String query = strings[0];
    119             if (query == null) {
    120                 query = "";
    121             }
    122 
    123             Cursor c = null;
    124             final List<SuggestionItem> result = Lists.newArrayList();
    125             try {
    126                 c = mSuggestionsProvider.query(query);
    127 
    128                 if (c != null && c.moveToFirst()) {
    129                     final int textIndex = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY);
    130                     final int iconIndex = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
    131                     do {
    132                         final String suggestion = c.getString(textIndex);
    133                         final Uri iconUri = Uri.parse(c.getString(iconIndex));
    134                         result.add(new SuggestionItem(suggestion, iconUri));
    135                     } while (c.moveToNext());
    136                 }
    137             } finally {
    138                 if (c != null) {
    139                     c.close();
    140                 }
    141             }
    142 
    143             return result;
    144         }
    145 
    146         @Override
    147         protected void onPostExecute(List<SuggestionItem> strings) {
    148             if (!isCancelled()) {
    149                 // Should not have any race conditions here since we cancel the previous asynctask
    150                 // before starting the new one. It's unlikely that the new task finishes fast enough
    151                 // to get to onPostExecute when this one is in addAll.
    152                 mSuggestions.clear();
    153                 mSuggestions.addAll(strings);
    154                 mAdapter.notifyDataSetChanged();
    155             }
    156         }
    157     }
    158 
    159     private static class SuggestionItem {
    160         final String suggestion;
    161         final Uri icon;
    162 
    163         public SuggestionItem(String s, Uri i) {
    164             suggestion = s;
    165             icon = i;
    166         }
    167     }
    168 
    169     // Custom adapter to populate our list
    170     private class MaterialSearchViewListAdapter extends BaseAdapter {
    171         private final Context mContext;
    172         private final int mResId;
    173         private LayoutInflater mInflater;
    174 
    175         public MaterialSearchViewListAdapter(Context context, int resource) {
    176             super();
    177             mContext = context;
    178             mResId = resource;
    179         }
    180 
    181         private LayoutInflater getInflater() {
    182             if (mInflater == null) {
    183                 mInflater = LayoutInflater.from(mContext);
    184             }
    185             return mInflater;
    186         }
    187 
    188         @Override
    189         public int getCount() {
    190             return mSuggestions.size();
    191         }
    192 
    193         @Override
    194         public Object getItem(int i) {
    195             return mSuggestions.get(i);
    196         }
    197 
    198         @Override
    199         public long getItemId(int i) {
    200             return 0;
    201         }
    202 
    203         @Override
    204         public View getView(int position, View convertView, ViewGroup parent) {
    205             if (convertView == null) {
    206                 convertView = getInflater().inflate(mResId, parent, false);
    207             }
    208 
    209             final SuggestionItem item = mSuggestions.get(position);
    210             final TextView text =
    211                     (TextView) convertView.findViewById(R.id.search_overlay_item_text);
    212             text.setText(item.suggestion);
    213             text.setContentDescription(getResources().getString(R.string.search_suggestion_desc,
    214                     item.suggestion));
    215             ((ImageView) convertView.findViewById(R.id.search_overlay_item_icon))
    216                     .setImageURI(item.icon);
    217 
    218             return convertView;
    219         }
    220     }
    221 }
    222