1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.documentsui.queries; 18 19 import android.app.Dialog; 20 import android.content.Context; 21 import android.os.Bundle; 22 import android.text.TextUtils; 23 import android.view.LayoutInflater; 24 import android.view.View; 25 import android.view.ViewGroup; 26 import android.widget.AdapterView; 27 import android.widget.ArrayAdapter; 28 import android.widget.ListView; 29 import android.widget.TextView; 30 31 import androidx.annotation.NonNull; 32 import androidx.annotation.Nullable; 33 import androidx.appcompat.widget.SearchView; 34 import androidx.appcompat.widget.Toolbar; 35 import androidx.fragment.app.DialogFragment; 36 import androidx.fragment.app.Fragment; 37 import androidx.fragment.app.FragmentManager; 38 39 import com.android.documentsui.BaseActivity; 40 import com.android.documentsui.Injector; 41 import com.android.documentsui.R; 42 43 import java.util.List; 44 45 public class SearchFragment extends DialogFragment 46 implements SearchView.OnQueryTextListener{ 47 48 private static final String TAG = "SearchFragment"; 49 private static final String KEY_QUERY = "query"; 50 private static final int MAX_DISPLAY_ITEMS = 8; 51 52 private SearchViewManager mSearchViewManager; 53 54 private SearchView mSearchView; 55 private ViewGroup mSearchChipGroup; 56 private ListView mListView; 57 private ArrayAdapter<String> mAdapter; 58 59 private List<String> mHistoryList; 60 showFragment(FragmentManager fm, String initQuery)61 public static void showFragment(FragmentManager fm, String initQuery) { 62 final SearchFragment fragment = new SearchFragment(); 63 final Bundle args = new Bundle(); 64 args.putString(KEY_QUERY, initQuery); 65 fragment.setArguments(args); 66 fragment.setStyle(DialogFragment.STYLE_NO_FRAME, R.style.DocumentsTheme); 67 fragment.show(fm, TAG); 68 } 69 get(FragmentManager fm)70 public static SearchFragment get(FragmentManager fm) { 71 final Fragment fragment = fm.findFragmentByTag(TAG); 72 return fragment instanceof SearchFragment 73 ? (SearchFragment) fragment 74 : null; 75 } 76 onChipClicked(View view)77 private void onChipClicked(View view) { 78 final Object tag = view.getTag(); 79 if (tag instanceof SearchChipData) { 80 mSearchViewManager.onMirrorChipClick((SearchChipData) tag); 81 dismiss(); 82 } 83 } 84 onHistoryItemClicked(AdapterView<?> parent, View view, int position, long id)85 private void onHistoryItemClicked(AdapterView<?> parent, View view, int position, long id) { 86 final String item = mHistoryList.get(position); 87 mSearchViewManager.setHistorySearch(); 88 mSearchView.setQuery(item, true); 89 } 90 91 @Nullable 92 @Override onCreateView(@onNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)93 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, 94 @Nullable Bundle savedInstanceState) { 95 final View view = inflater.inflate(R.layout.fragment_search, container, false); 96 97 final Toolbar toolbar = view.findViewById(R.id.toolbar); 98 toolbar.setNavigationOnClickListener(v -> { 99 mSearchViewManager.cancelSearch(); 100 dismiss(); 101 }); 102 103 mSearchView = view.findViewById(R.id.search_view); 104 mSearchChipGroup = view.findViewById(R.id.search_chip_group); 105 mListView = view.findViewById(R.id.history_list); 106 107 return view; 108 } 109 110 @Override onActivityCreated(@ullable Bundle savedInstanceState)111 public void onActivityCreated(@Nullable Bundle savedInstanceState) { 112 super.onActivityCreated(savedInstanceState); 113 114 final BaseActivity activity = (BaseActivity) getActivity(); 115 final Injector injector = activity.getInjector(); 116 mSearchViewManager = injector.searchManager; 117 118 final String currentQuery = getArguments().getString(KEY_QUERY, ""); 119 120 mSearchView.onActionViewExpanded(); 121 mSearchView.setQuery(currentQuery, false); 122 mSearchView.setOnQueryTextListener(this); 123 mHistoryList = SearchHistoryManager.getInstance( 124 getContext().getApplicationContext()).getHistoryList(currentQuery); 125 126 mSearchViewManager.bindChips(mSearchChipGroup); 127 if (mSearchChipGroup.getVisibility() == View.VISIBLE) { 128 for (int i = 0, size = mSearchChipGroup.getChildCount(); i < size; i++) { 129 mSearchChipGroup.getChildAt(i).setOnClickListener(this::onChipClicked); 130 } 131 } 132 133 mAdapter = new HistoryListAdapter(getContext(), mHistoryList); 134 mListView.setAdapter(mAdapter); 135 mListView.setOnItemClickListener(this::onHistoryItemClicked); 136 } 137 138 @Override onStart()139 public void onStart() { 140 super.onStart(); 141 getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, 142 ViewGroup.LayoutParams.MATCH_PARENT); 143 } 144 145 @Override onCreateDialog(@ullable Bundle savedInstanceState)146 public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { 147 return new Dialog(getActivity(), getTheme()){ 148 @Override 149 public void onBackPressed() { 150 if (TextUtils.isEmpty(mSearchView.getQuery())) { 151 mSearchViewManager.cancelSearch(); 152 } else { 153 mSearchViewManager.restoreSearch(false); 154 } 155 dismiss(); 156 } 157 }; 158 } 159 160 @Override 161 public boolean onQueryTextSubmit(String s) { 162 if (!TextUtils.isEmpty(mSearchView.getQuery())) { 163 mSearchViewManager.setCurrentSearch(s); 164 mSearchViewManager.restoreSearch(false); 165 mSearchViewManager.recordHistory(); 166 dismiss(); 167 } 168 return true; 169 } 170 171 @Override 172 public boolean onQueryTextChange(String s) { 173 if (!TextUtils.isEmpty(mSearchView.getQuery())) { 174 mSearchViewManager.setCurrentSearch(s); 175 mSearchViewManager.restoreSearch(true); 176 dismiss(); 177 } else { 178 mHistoryList = SearchHistoryManager.getInstance( 179 mSearchView.getContext().getApplicationContext()).getHistoryList(""); 180 mAdapter.clear(); 181 mAdapter.addAll(mHistoryList); 182 } 183 return true; 184 } 185 186 private class HistoryListAdapter extends ArrayAdapter<String> { 187 188 public HistoryListAdapter(Context context, List<String> list) { 189 super(context, R.layout.item_history, list); 190 } 191 192 @Override 193 public View getView(int position, View convertView, ViewGroup parent) { 194 if (convertView == null) { 195 convertView = getLayoutInflater().inflate(R.layout.item_history, parent, false); 196 } 197 final String history = getItem(position); 198 final TextView text = convertView.findViewById(android.R.id.title); 199 final View button = convertView.findViewById(android.R.id.icon); 200 201 text.setText(history); 202 button.setOnClickListener(v -> { 203 mSearchViewManager.removeHistory(history); 204 mHistoryList.remove(history); 205 notifyDataSetChanged(); 206 }); 207 button.setContentDescription( 208 getContext().getString(R.string.delete_search_history, history)); 209 210 return convertView; 211 } 212 213 @Override 214 public int getCount() { 215 final int count = super.getCount(); 216 return count > MAX_DISPLAY_ITEMS ? MAX_DISPLAY_ITEMS : count; 217 } 218 } 219 } 220