• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.settings.dashboard.profileselector;
18 
19 import static android.content.Intent.EXTRA_USER_ID;
20 
21 import android.annotation.IntDef;
22 import android.app.Activity;
23 import android.content.Context;
24 import android.content.res.ColorStateList;
25 import android.os.Bundle;
26 import android.os.UserHandle;
27 import android.os.UserManager;
28 import android.text.TextUtils;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.FrameLayout;
33 import android.widget.LinearLayout;
34 
35 import androidx.annotation.VisibleForTesting;
36 import androidx.fragment.app.Fragment;
37 import androidx.fragment.app.FragmentStatePagerAdapter;
38 import androidx.recyclerview.widget.RecyclerView;
39 import androidx.viewpager.widget.ViewPager;
40 
41 import com.android.settings.R;
42 import com.android.settings.SettingsActivity;
43 import com.android.settings.Utils;
44 import com.android.settings.dashboard.DashboardFragment;
45 
46 import com.google.android.material.tabs.TabLayout;
47 
48 import java.lang.annotation.Retention;
49 import java.lang.annotation.RetentionPolicy;
50 import java.util.Locale;
51 
52 /**
53  * Base fragment class for profile settings.
54  */
55 public abstract class ProfileSelectFragment extends DashboardFragment {
56 
57     private static final String TAG = "ProfileSelectFragment";
58 
59     /**
60      * Denotes the profile type.
61      */
62     @Retention(RetentionPolicy.SOURCE)
63     @IntDef({
64             ProfileType.PERSONAL,
65             ProfileType.WORK,
66             ProfileType.ALL
67     })
68     public @interface ProfileType {
69         /**
70          * It is personal work profile.
71          */
72         int PERSONAL = 1;
73 
74         /**
75          * It is work profile
76          */
77         int WORK = 1 << 1;
78 
79         /**
80          * It is personal and work profile
81          */
82         int ALL = PERSONAL | WORK;
83     }
84 
85     /**
86      * Used in fragment argument and pass {@link ProfileType} to it
87      */
88     public static final String EXTRA_PROFILE = "profile";
89 
90     /**
91      * Used in fragment argument with Extra key {@link SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB}
92      */
93     public static final int PERSONAL_TAB = 0;
94 
95     /**
96      * Used in fragment argument with Extra key {@link SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB}
97      */
98     public static final int WORK_TAB = 1;
99     private static final int[] LABEL = {
100             R.string.category_personal, R.string.category_work
101     };
102 
103     private ViewGroup mContentView;
104 
105     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)106     public View onCreateView(LayoutInflater inflater, ViewGroup container,
107             Bundle savedInstanceState) {
108         mContentView = (ViewGroup) super.onCreateView(inflater, container, savedInstanceState);
109         final Activity activity = getActivity();
110         final int selectedTab = convertPosition(getTabId(activity, getArguments()));
111 
112         final View tabContainer = mContentView.findViewById(R.id.tab_container);
113         final ViewPager viewPager = tabContainer.findViewById(R.id.view_pager);
114         viewPager.setAdapter(new ProfileSelectFragment.ViewPagerAdapter(this));
115         final TabLayout tabs = tabContainer.findViewById(R.id.tabs);
116         tabs.setupWithViewPager(viewPager);
117         setupTabTextColor(tabs);
118         tabContainer.setVisibility(View.VISIBLE);
119         final TabLayout.Tab tab = tabs.getTabAt(selectedTab);
120         tab.select();
121 
122         final FrameLayout listContainer = mContentView.findViewById(android.R.id.list_container);
123         listContainer.setLayoutParams(new LinearLayout.LayoutParams(
124                 ViewGroup.LayoutParams.MATCH_PARENT,
125                 ViewGroup.LayoutParams.WRAP_CONTENT));
126 
127         final RecyclerView recyclerView = getListView();
128         recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
129         Utils.setActionBarShadowAnimation(activity, getSettingsLifecycle(), recyclerView);
130 
131         return mContentView;
132     }
133 
134     /**
135      * TabLayout uses ColorStateList of 2 states, selected state and empty state.
136      * It's expected to use textColorSecondary default state color as empty state tabTextColor.
137      *
138      * However, TabLayout uses textColorSecondary by a not expected state.
139      * This method sets tabTextColor with the color of expected textColorSecondary state.
140      */
setupTabTextColor(TabLayout tabLayout)141     private void setupTabTextColor(TabLayout tabLayout) {
142         final ColorStateList defaultColorStateList = tabLayout.getTabTextColors();
143         final ColorStateList resultColorStateList = new ColorStateList(
144                 new int[][]{
145                     new int[]{android.R.attr.state_selected},
146                     new int[]{}
147                 },
148                 new int[] {
149                     defaultColorStateList.getColorForState(new int[]{android.R.attr.state_selected},
150                             Utils.getColorAttrDefaultColor(getContext(),
151                             com.android.internal.R.attr.colorAccentPrimaryVariant)),
152                     Utils.getColorAttrDefaultColor(getContext(), android.R.attr.textColorSecondary)
153                 }
154         );
155         tabLayout.setTabTextColors(resultColorStateList);
156     }
157 
158     @Override
getMetricsCategory()159     public int getMetricsCategory() {
160         return METRICS_CATEGORY_UNKNOWN;
161     }
162 
163     /**
164      * Returns an array of {@link Fragment} to display in the
165      * {@link com.google.android.material.tabs.TabLayout}
166      */
getFragments()167     public abstract Fragment[] getFragments();
168 
169     @Override
getPreferenceScreenResId()170     protected int getPreferenceScreenResId() {
171         return R.xml.placeholder_preference_screen;
172     }
173 
174     @Override
getLogTag()175     protected String getLogTag() {
176         return TAG;
177     }
178 
179     @VisibleForTesting
getTabId(Activity activity, Bundle bundle)180     int getTabId(Activity activity, Bundle bundle) {
181         if (bundle != null) {
182             final int extraTab = bundle.getInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, -1);
183             if (extraTab != -1) {
184                 return extraTab;
185             }
186             final int userId = bundle.getInt(EXTRA_USER_ID, UserHandle.SYSTEM.getIdentifier());
187             final boolean isWorkProfile = UserManager.get(activity).isManagedProfile(userId);
188             if (isWorkProfile) {
189                 return WORK_TAB;
190             }
191         }
192         // Start intent from a specific user eg: adb shell --user 10
193         final int intentUser = activity.getIntent().getContentUserHint();
194         if (UserManager.get(activity).isManagedProfile(intentUser)) {
195             return WORK_TAB;
196         }
197 
198         return PERSONAL_TAB;
199     }
200 
201     static class ViewPagerAdapter extends FragmentStatePagerAdapter {
202 
203         private final Fragment[] mChildFragments;
204         private final Context mContext;
205 
ViewPagerAdapter(ProfileSelectFragment fragment)206         ViewPagerAdapter(ProfileSelectFragment fragment) {
207             super(fragment.getChildFragmentManager());
208             mContext = fragment.getContext();
209             mChildFragments = fragment.getFragments();
210         }
211 
212         @Override
getItem(int position)213         public Fragment getItem(int position) {
214             return mChildFragments[convertPosition(position)];
215         }
216 
217         @Override
getCount()218         public int getCount() {
219             return mChildFragments.length;
220         }
221 
222         @Override
getPageTitle(int position)223         public CharSequence getPageTitle(int position) {
224             return mContext.getString(LABEL[convertPosition(position)]);
225         }
226     }
227 
convertPosition(int index)228     private static int convertPosition(int index) {
229         if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
230                 == View.LAYOUT_DIRECTION_RTL) {
231             return LABEL.length - 1 - index;
232         }
233         return index;
234     }
235 }
236