1 /* 2 * Copyright (C) 2017 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.car.dialer.ui.search; 18 19 import android.os.Bundle; 20 import android.text.TextUtils; 21 import android.view.View; 22 23 import androidx.annotation.NonNull; 24 import androidx.annotation.Nullable; 25 import androidx.fragment.app.Fragment; 26 import androidx.lifecycle.ViewModelProviders; 27 import androidx.recyclerview.widget.RecyclerView; 28 29 import com.android.car.dialer.R; 30 import com.android.car.dialer.log.L; 31 import com.android.car.dialer.ui.common.DialerListBaseFragment; 32 import com.android.car.dialer.ui.contact.ContactDetailsFragment; 33 import com.android.car.telephony.common.Contact; 34 import com.android.car.ui.toolbar.Toolbar; 35 import com.android.car.ui.toolbar.ToolbarController; 36 37 /** 38 * A fragment that will take a search query, look up contacts that match and display those 39 * results as a list. 40 */ 41 public class ContactResultsFragment extends DialerListBaseFragment implements 42 ContactResultsAdapter.OnShowContactDetailListener, Toolbar.OnSearchListener { 43 44 /** 45 * Creates a new instance of the {@link ContactResultsFragment}. 46 * 47 * @param initialSearchQuery An optional search query that will be inputted when the fragment 48 * starts up. 49 */ newInstance(@ullable String initialSearchQuery)50 public static ContactResultsFragment newInstance(@Nullable String initialSearchQuery) { 51 ContactResultsFragment fragment = new ContactResultsFragment(); 52 Bundle args = new Bundle(); 53 args.putString(SEARCH_QUERY, initialSearchQuery); 54 fragment.setArguments(args); 55 return fragment; 56 } 57 58 public static final String FRAGMENT_TAG = "ContactResultsFragment"; 59 60 private static final String TAG = "CD.ContactResultsFragment"; 61 private static final String SEARCH_QUERY = "SearchQuery"; 62 63 private ContactResultsViewModel mContactResultsViewModel; 64 private final ContactResultsAdapter mAdapter = new ContactResultsAdapter(this); 65 66 private RecyclerView.OnScrollListener mOnScrollChangeListener; 67 private ToolbarController mToolbar; 68 69 @Override onCreate(Bundle savedInstanceState)70 public void onCreate(Bundle savedInstanceState) { 71 super.onCreate(savedInstanceState); 72 73 mContactResultsViewModel = ViewModelProviders.of(this).get( 74 ContactResultsViewModel.class); 75 mContactResultsViewModel.getContactSearchResults().observe(this, 76 contactResults -> { 77 mAdapter.setData(contactResults); 78 showContent(); 79 }); 80 81 // Set the initial search query, if one was provided from a Intent.ACTION_SEARCH 82 if (getArguments() != null) { 83 String initialQuery = getArguments().getString(SEARCH_QUERY); 84 if (!TextUtils.isEmpty(initialQuery)) { 85 setSearchQuery(initialQuery); 86 } 87 getArguments().clear(); 88 } 89 } 90 91 @Override onViewCreated(View view, Bundle savedInstanceState)92 public void onViewCreated(View view, Bundle savedInstanceState) { 93 super.onViewCreated(view, savedInstanceState); 94 getRecyclerView().setAdapter(mAdapter); 95 96 mOnScrollChangeListener = new RecyclerView.OnScrollListener() { 97 @Override 98 public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { 99 } 100 101 @Override 102 public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { 103 if (dy != 0) { 104 // Clear the focus to dismiss the keyboard. 105 getActivity().getCurrentFocus().clearFocus(); 106 } 107 } 108 }; 109 getRecyclerView().addOnScrollListener(mOnScrollChangeListener); 110 } 111 112 @Override onDestroyView()113 public void onDestroyView() { 114 super.onDestroyView(); 115 getRecyclerView().removeOnScrollListener(mOnScrollChangeListener); 116 } 117 118 @Override setupToolbar(@onNull ToolbarController toolbar)119 protected void setupToolbar(@NonNull ToolbarController toolbar) { 120 super.setupToolbar(toolbar); 121 mToolbar = toolbar; 122 mToolbar.registerOnSearchListener(this); 123 mToolbar.setSearchIcon(R.drawable.ic_app_icon); 124 setSearchQuery(mContactResultsViewModel.getSearchQuery()); 125 } 126 127 @Override onStop()128 public void onStop() { 129 super.onStop(); 130 mToolbar.unregisterOnSearchListener(this); 131 } 132 133 /** Sets the search query that should be used to filter contacts. */ setSearchQuery(String query)134 public void setSearchQuery(String query) { 135 if (mToolbar != null) { 136 mToolbar.setSearchQuery(query); 137 } else { 138 onSearch(query); 139 } 140 } 141 142 /** Triggered by search view text change. */ 143 @Override onSearch(String newQuery)144 public void onSearch(String newQuery) { 145 L.d(TAG, "onSearch: %s", newQuery); 146 mContactResultsViewModel.setSearchQuery(newQuery); 147 } 148 149 @Override onShowContactDetail(Contact contact)150 public void onShowContactDetail(Contact contact) { 151 Fragment contactDetailsFragment = ContactDetailsFragment.newInstance(contact); 152 pushContentFragment(contactDetailsFragment, ContactDetailsFragment.FRAGMENT_TAG); 153 } 154 155 @Override getToolbarState()156 protected Toolbar.State getToolbarState() { 157 return Toolbar.State.SEARCH; 158 } 159 } 160