• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.settings.datetime.timezone;
18 
19 import android.os.Bundle;
20 import android.support.annotation.VisibleForTesting;
21 import android.support.v7.widget.LinearLayoutManager;
22 import android.support.v7.widget.RecyclerView;
23 import android.view.LayoutInflater;
24 import android.view.Menu;
25 import android.view.MenuInflater;
26 import android.view.MenuItem;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.LinearLayout;
30 import android.widget.SearchView;
31 import android.widget.TextView;
32 
33 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
34 import com.android.settings.R;
35 import com.android.settings.core.InstrumentedFragment;
36 import com.android.settings.datetime.timezone.model.TimeZoneData;
37 import com.android.settings.datetime.timezone.model.TimeZoneDataLoader;
38 
39 import java.util.Locale;
40 
41 /**
42  * It's abstract class. Subclass should use it with {@class BaseTimeZoneAdapter} and
43  * {@class AdapterItem} to provide a list view with text search capability.
44  * The search matches the prefix of words in the search text.
45  */
46 public abstract class BaseTimeZonePicker extends InstrumentedFragment
47         implements SearchView.OnQueryTextListener {
48 
49     public static final String EXTRA_RESULT_REGION_ID =
50             "com.android.settings.datetime.timezone.result_region_id";
51     public static final String EXTRA_RESULT_TIME_ZONE_ID =
52             "com.android.settings.datetime.timezone.result_time_zone_id";
53     private final int mTitleResId;
54     private final int mSearchHintResId;
55     private final boolean mSearchEnabled;
56     private final boolean mDefaultExpandSearch;
57 
58     protected Locale mLocale;
59     private BaseTimeZoneAdapter mAdapter;
60     private RecyclerView mRecyclerView;
61     private TimeZoneData mTimeZoneData;
62 
63     private SearchView mSearchView;
64 
65     /**
66      * Constructor called by subclass.
67      * @param defaultExpandSearch whether expand the search view when first launching the fragment
68      */
BaseTimeZonePicker(int titleResId, int searchHintResId, boolean searchEnabled, boolean defaultExpandSearch)69     protected BaseTimeZonePicker(int titleResId, int searchHintResId,
70             boolean searchEnabled, boolean defaultExpandSearch) {
71         mTitleResId = titleResId;
72         mSearchHintResId = searchHintResId;
73         mSearchEnabled = searchEnabled;
74         mDefaultExpandSearch = defaultExpandSearch;
75     }
76 
77     @Override
onCreate(Bundle savedInstanceState)78     public void onCreate(Bundle savedInstanceState) {
79         super.onCreate(savedInstanceState);
80         setHasOptionsMenu(true);
81         getActivity().setTitle(mTitleResId);
82     }
83 
84     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)85     public View onCreateView(LayoutInflater inflater, ViewGroup container,
86             Bundle savedInstanceState) {
87         final View view = inflater.inflate(R.layout.time_zone_items_list, container, false);
88         mRecyclerView = view.findViewById(R.id.recycler_view);
89         mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(),
90                 LinearLayoutManager.VERTICAL, /* reverseLayout */ false));
91         mRecyclerView.setAdapter(mAdapter);
92 
93         // Initialize TimeZoneDataLoader only when mRecyclerView is ready to avoid race
94         // during onDateLoaderReady callback.
95         getLoaderManager().initLoader(0, null, new TimeZoneDataLoader.LoaderCreator(
96                 getContext(), this::onTimeZoneDataReady));
97         return view;
98     }
99 
onTimeZoneDataReady(TimeZoneData timeZoneData)100     public void onTimeZoneDataReady(TimeZoneData timeZoneData) {
101         if (mTimeZoneData == null && timeZoneData != null) {
102             mTimeZoneData = timeZoneData;
103             mAdapter = createAdapter(mTimeZoneData);
104             if (mRecyclerView != null) {
105                 mRecyclerView.setAdapter(mAdapter);
106             }
107         }
108     }
109 
getLocale()110     protected Locale getLocale() {
111         return getContext().getResources().getConfiguration().getLocales().get(0);
112     }
113 
114     /**
115      * Called when TimeZoneData is ready.
116      */
createAdapter(TimeZoneData timeZoneData)117     protected abstract BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData);
118 
119     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)120     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
121         if (mSearchEnabled) {
122             inflater.inflate(R.menu.time_zone_base_search_menu, menu);
123 
124             final MenuItem searchMenuItem = menu.findItem(R.id.time_zone_search_menu);
125             mSearchView = (SearchView) searchMenuItem.getActionView();
126 
127             mSearchView.setQueryHint(getText(mSearchHintResId));
128             mSearchView.setOnQueryTextListener(this);
129 
130             if (mDefaultExpandSearch) {
131                 searchMenuItem.expandActionView();
132                 mSearchView.setIconified(false);
133                 mSearchView.setActivated(true);
134                 mSearchView.setQuery("", true /* submit */);
135             }
136 
137             // Set zero margin and padding to align with the text horizontally in the preference
138             final TextView searchViewView = (TextView) mSearchView.findViewById(
139                     com.android.internal.R.id.search_src_text);
140             searchViewView.setPadding(0, searchViewView.getPaddingTop(), 0,
141                     searchViewView.getPaddingBottom());
142             final View editFrame = mSearchView.findViewById(
143                     com.android.internal.R.id.search_edit_frame);
144             final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) editFrame
145                     .getLayoutParams();
146             params.setMarginStart(0);
147             params.setMarginEnd(0);
148             editFrame.setLayoutParams(params);
149         }
150     }
151 
152     @Override
onQueryTextSubmit(String query)153     public boolean onQueryTextSubmit(String query) {
154         return false;
155     }
156 
157     @Override
onQueryTextChange(String newText)158     public boolean onQueryTextChange(String newText) {
159         if (mAdapter != null) {
160             mAdapter.getFilter().filter(newText);
161         }
162         return false;
163     }
164 
165     public interface OnListItemClickListener<T extends BaseTimeZoneAdapter.AdapterItem> {
onListItemClick(T item)166         void onListItemClick(T item);
167     }
168 
169 }
170