Merge "Introduce inline education for work profile" into sc-dev am: b8b822a74b
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/14962825 Change-Id: I144ebf38fab282417389a51f0b95d47001482d79
This commit is contained in:
commit
b2d6d73377
|
@ -24,7 +24,7 @@
|
|||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="@dimen/work_fab_radius" />
|
||||
<solid android:color="?android:attr/colorAccent" />
|
||||
<solid android:color="@color/all_apps_tab_bg" />
|
||||
<padding android:left="@dimen/work_fab_radius" android:right="@dimen/work_fab_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2021 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="?androidprv:attr/colorSurface" />
|
||||
<corners android:radius="@dimen/work_edu_card_margin" />
|
||||
<padding
|
||||
android:left="@dimen/work_fab_radius"
|
||||
android:right="@dimen/work_fab_radius" />
|
||||
</shape>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2021 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="@dimen/work_edu_card_margin" />
|
||||
<stroke android:width="1dp" android:color="?androidprv:attr/colorAccentPrimaryVariant" />
|
||||
<padding
|
||||
android:left="@dimen/work_fab_radius"
|
||||
android:right="@dimen/work_fab_radius" />
|
||||
</shape>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<com.android.launcher3.allapps.WorkEduCard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/work_edu_card_margin"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/work_card"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
style="@style/PrimaryHeadline"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:id="@+id/work_apps_paused_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/work_profile_edu_work_apps"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/action_btn"
|
||||
android:textColor="?attr/workProfileOverlayTextColor"
|
||||
android:text="@string/work_profile_edu_accept"
|
||||
android:textAlignment="center"
|
||||
android:background="@drawable/work_card_btn"
|
||||
android:textSize="14sp" />
|
||||
</com.android.launcher3.allapps.WorkEduCard>
|
|
@ -1,5 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2017 The Android Open Source Project
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -13,8 +12,7 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.launcher3.allapps.WorkModeSwitch
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.android.launcher3.allapps.WorkModeSwitch xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/work_mode_toggle"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
|
@ -22,8 +20,8 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:drawableTint="@android:color/white"
|
||||
android:textColor="@android:color/white"
|
||||
android:drawableTint="@color/all_apps_tab_text"
|
||||
android:textColor="@color/all_apps_tab_text"
|
||||
android:background="@drawable/work_apps_toggle_background"
|
||||
android:drawablePadding="16dp"
|
||||
android:drawableStart="@drawable/ic_corp_off"
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.launcher3.allapps.WorkModeSwitch xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/PrimaryHeadline"
|
||||
android:id="@+id/work_mode_toggle"
|
||||
android:drawableStart="@drawable/ic_corp"
|
||||
android:drawablePadding="16dp"
|
||||
android:drawableTint="?attr/workProfileOverlayTextColor"
|
||||
android:textColor="?attr/workProfileOverlayTextColor"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:ellipsize="end"
|
||||
android:elevation="10dp"
|
||||
android:gravity="start"
|
||||
android:lines="1"
|
||||
android:showText="false"
|
||||
android:textSize="@dimen/work_profile_footer_text_size"
|
||||
android:background="?attr/allAppsScrimColor"
|
||||
android:text="@string/work_profile_toggle_label"
|
||||
android:paddingBottom="@dimen/work_profile_footer_padding"
|
||||
android:paddingLeft="@dimen/work_profile_footer_padding"
|
||||
android:paddingRight="@dimen/work_profile_footer_padding"
|
||||
android:paddingTop="@dimen/work_profile_footer_padding" />
|
|
@ -122,8 +122,10 @@
|
|||
<dimen name="work_fab_margin">18dp</dimen>
|
||||
<dimen name="work_profile_footer_padding">20dp</dimen>
|
||||
<dimen name="work_profile_footer_text_size">16sp</dimen>
|
||||
<dimen name="work_edu_card_margin">16dp</dimen>
|
||||
|
||||
<!-- Widget tray -->
|
||||
|
||||
<!-- Widget tray -->
|
||||
<dimen name="widget_cell_vertical_padding">8dp</dimen>
|
||||
<dimen name="widget_cell_horizontal_padding">16dp</dimen>
|
||||
<dimen name="widget_cell_font_size">14sp</dimen>
|
||||
|
|
|
@ -389,7 +389,7 @@
|
|||
<!-- This string is in the work profile tab when a user has All Apps open on their phone. This is a label for a toggle to turn the work profile on and off. "Work profile" means a separate profile on a user's phone that's specifically for their work apps and managed by their company. "Work" is used as an adjective.-->
|
||||
<string name="work_profile_toggle_label">Work profile</string>
|
||||
<!--- User onboarding title for work profile apps -->
|
||||
<string name="work_profile_edu_work_apps">Work apps are badged andare visible to your IT admin</string>
|
||||
<string name="work_profile_edu_work_apps">Work apps are badged and visible to your IT admin</string>
|
||||
<!-- Action label to finish work profile edu-->
|
||||
<string name="work_profile_edu_accept">Got it</string>
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ import androidx.annotation.StringRes;
|
|||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.core.os.BuildCompat;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
|
@ -127,6 +126,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
|||
private Rect mInsets = new Rect();
|
||||
|
||||
private SearchAdapterProvider mSearchAdapterProvider;
|
||||
private WorkAdapterProvider mWorkAdapterProvider;
|
||||
private final int mScrimColor;
|
||||
private final int mHeaderProtectionColor;
|
||||
private final float mHeaderThreshold;
|
||||
|
@ -159,6 +159,11 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
|||
Selection.setSelection(mSearchQueryBuilder, 0);
|
||||
|
||||
mAH = new AdapterHolder[2];
|
||||
mWorkAdapterProvider = new WorkAdapterProvider(mLauncher, () -> {
|
||||
if (mAH[AdapterHolder.WORK] != null) {
|
||||
mAH[AdapterHolder.WORK].appsList.updateAdapterItems();
|
||||
}
|
||||
});
|
||||
mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */);
|
||||
mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */);
|
||||
|
||||
|
@ -228,8 +233,9 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
|||
}
|
||||
|
||||
private void resetWorkProfile() {
|
||||
mWorkModeSwitch.updateCurrentState(!mAllAppsStore.hasModelFlag(FLAG_QUIET_MODE_ENABLED));
|
||||
mAH[AdapterHolder.WORK].setupOverlay();
|
||||
boolean isEnabled = !mAllAppsStore.hasModelFlag(FLAG_QUIET_MODE_ENABLED);
|
||||
mWorkModeSwitch.updateCurrentState(isEnabled);
|
||||
mWorkAdapterProvider.updateCurrentState(isEnabled);
|
||||
mAH[AdapterHolder.WORK].applyPadding();
|
||||
}
|
||||
|
||||
|
@ -392,7 +398,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
|||
mAH[i].padding.bottom = insets.bottom;
|
||||
mAH[i].padding.left = mAH[i].padding.right = leftRightPadding;
|
||||
mAH[i].applyPadding();
|
||||
mAH[i].setupOverlay();
|
||||
}
|
||||
|
||||
ViewGroup.MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
|
||||
|
@ -539,6 +544,9 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
|||
&& mAllAppsStore.hasModelFlag(
|
||||
FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION));
|
||||
}
|
||||
if (mSearchUiManager != null && mSearchUiManager.getEditText() != null) {
|
||||
mSearchUiManager.getEditText().hideKeyboard();
|
||||
}
|
||||
}
|
||||
|
||||
// Used by tests only
|
||||
|
@ -719,9 +727,15 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
|||
|
||||
AdapterHolder(boolean isWork) {
|
||||
mIsWork = isWork;
|
||||
appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore, isWork);
|
||||
appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore,
|
||||
isWork ? mWorkAdapterProvider : null);
|
||||
|
||||
BaseAdapterProvider[] adapterProviders =
|
||||
isWork ? new BaseAdapterProvider[]{mSearchAdapterProvider, mWorkAdapterProvider}
|
||||
: new BaseAdapterProvider[]{mSearchAdapterProvider};
|
||||
|
||||
adapter = new AllAppsGridAdapter(mLauncher, getLayoutInflater(), appsList,
|
||||
mSearchAdapterProvider);
|
||||
adapterProviders);
|
||||
appsList.setAdapter(adapter);
|
||||
layoutManager = adapter.getLayoutManager();
|
||||
}
|
||||
|
@ -743,38 +757,11 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
|||
adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
|
||||
applyVerticalFadingEdgeEnabled(verticalFadingEdge);
|
||||
applyPadding();
|
||||
setupOverlay();
|
||||
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
|
||||
recyclerView.addItemDecoration(mSearchAdapterProvider.getDecorator());
|
||||
}
|
||||
}
|
||||
|
||||
void setupOverlay() {
|
||||
if (!mIsWork || recyclerView == null) return;
|
||||
boolean workDisabled = mAllAppsStore.hasModelFlag(FLAG_QUIET_MODE_ENABLED);
|
||||
if (mWorkDisabled == workDisabled) return;
|
||||
recyclerView.setContentDescription(workDisabled ? mLauncher.getString(
|
||||
R.string.work_apps_paused_content_description) : null);
|
||||
View overlayView = getOverlayView();
|
||||
recyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
if (workDisabled) {
|
||||
overlayView.setAlpha(0);
|
||||
recyclerView.addAutoSizedOverlay(overlayView);
|
||||
overlayView.animate().alpha(1).withEndAction(
|
||||
() -> {
|
||||
appsList.updateItemFilter((info, cn) -> false);
|
||||
recyclerView.setItemAnimator(null);
|
||||
}).start();
|
||||
} else if (mInfoMatcher != null) {
|
||||
appsList.updateItemFilter(mInfoMatcher);
|
||||
overlayView.animate().alpha(0).withEndAction(() -> {
|
||||
recyclerView.setItemAnimator(null);
|
||||
recyclerView.clearAutoSizedOverlays();
|
||||
}).start();
|
||||
}
|
||||
mWorkDisabled = workDisabled;
|
||||
}
|
||||
|
||||
void applyPadding() {
|
||||
if (recyclerView != null) {
|
||||
Resources res = getResources();
|
||||
|
|
|
@ -41,10 +41,10 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -72,7 +72,8 @@ public class AllAppsGridAdapter extends
|
|||
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
|
||||
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
|
||||
|
||||
private final SearchAdapterProvider mSearchAdapterProvider;
|
||||
|
||||
private final BaseAdapterProvider[] mAdapterProviders;
|
||||
|
||||
/**
|
||||
* ViewHolder for each icon.
|
||||
|
@ -242,9 +243,12 @@ public class AllAppsGridAdapter extends
|
|||
int totalSpans = mGridLayoutMgr.getSpanCount();
|
||||
if (isIconViewType(viewType)) {
|
||||
return totalSpans / mAppsPerRow;
|
||||
} else if (mSearchAdapterProvider.isSearchView(viewType)) {
|
||||
return totalSpans / mSearchAdapterProvider.getItemsPerRow(viewType, mAppsPerRow);
|
||||
} else {
|
||||
BaseAdapterProvider adapterProvider = getAdapterProvider(viewType);
|
||||
if (adapterProvider != null) {
|
||||
return totalSpans / adapterProvider.getItemsPerRow(viewType, mAppsPerRow);
|
||||
}
|
||||
|
||||
// Section breaks span the full width
|
||||
return totalSpans;
|
||||
}
|
||||
|
@ -270,7 +274,7 @@ public class AllAppsGridAdapter extends
|
|||
private Intent mMarketSearchIntent;
|
||||
|
||||
public AllAppsGridAdapter(BaseDraggingActivity launcher, LayoutInflater inflater,
|
||||
AlphabeticalAppsList apps, SearchAdapterProvider searchAdapterProvider) {
|
||||
AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
|
||||
Resources res = launcher.getResources();
|
||||
mLauncher = launcher;
|
||||
mApps = apps;
|
||||
|
@ -282,16 +286,18 @@ public class AllAppsGridAdapter extends
|
|||
|
||||
mOnIconClickListener = launcher.getItemOnClickListener();
|
||||
|
||||
mSearchAdapterProvider = searchAdapterProvider;
|
||||
mAdapterProviders = adapterProviders;
|
||||
setAppsPerRow(mLauncher.getDeviceProfile().numShownAllAppsColumns);
|
||||
}
|
||||
|
||||
public void setAppsPerRow(int appsPerRow) {
|
||||
mAppsPerRow = appsPerRow;
|
||||
int totalSpans = mAppsPerRow;
|
||||
for (int itemPerRow : mSearchAdapterProvider.getSupportedItemsPerRowArray()) {
|
||||
if (totalSpans % itemPerRow != 0) {
|
||||
totalSpans *= itemPerRow;
|
||||
for (BaseAdapterProvider adapterProvider : mAdapterProviders) {
|
||||
for (int itemPerRow : adapterProvider.getSupportedItemsPerRowArray()) {
|
||||
if (totalSpans % itemPerRow != 0) {
|
||||
totalSpans *= itemPerRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
mGridLayoutMgr.setSpanCount(totalSpans);
|
||||
|
@ -363,9 +369,9 @@ public class AllAppsGridAdapter extends
|
|||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
R.layout.all_apps_divider, parent, false));
|
||||
default:
|
||||
if (mSearchAdapterProvider.isSearchView(viewType)) {
|
||||
return mSearchAdapterProvider.onCreateViewHolder(mLayoutInflater, parent,
|
||||
viewType);
|
||||
BaseAdapterProvider adapterProvider = getAdapterProvider(viewType);
|
||||
if (adapterProvider != null) {
|
||||
return adapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
|
||||
}
|
||||
throw new RuntimeException("Unexpected view type");
|
||||
}
|
||||
|
@ -399,7 +405,10 @@ public class AllAppsGridAdapter extends
|
|||
// nothing to do
|
||||
break;
|
||||
default:
|
||||
mSearchAdapterProvider.onBindView(holder, position);
|
||||
BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType());
|
||||
if (adapterProvider != null) {
|
||||
adapterProvider.onBindView(holder, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,4 +433,11 @@ public class AllAppsGridAdapter extends
|
|||
AdapterItem item = mApps.getAdapterItems().get(position);
|
||||
return item.viewType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BaseAdapterProvider getAdapterProvider(int viewType) {
|
||||
return Arrays.stream(mAdapterProviders).filter(
|
||||
adapterProvider -> adapterProvider.isViewSupported(viewType)).findFirst().orElse(
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
|
|||
private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS = 1;
|
||||
|
||||
private final int mFastScrollDistributionMode = FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS;
|
||||
private final WorkAdapterProvider mWorkAdapterProvider;
|
||||
|
||||
/**
|
||||
* Info about a fast scroller section, depending if sections are merged, the fast scroller
|
||||
|
@ -75,8 +76,6 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
|
|||
private final ArrayList<AdapterItem> mAdapterItems = new ArrayList<>();
|
||||
// The set of sections that we allow fast-scrolling to (includes non-merged sections)
|
||||
private final List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
|
||||
// Is it the work profile app list.
|
||||
private final boolean mIsWork;
|
||||
|
||||
// The of ordered component names as a result of a search query
|
||||
private ArrayList<AdapterItem> mSearchResults;
|
||||
|
@ -86,11 +85,12 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
|
|||
private int mNumAppRowsInAdapter;
|
||||
private ItemInfoMatcher mItemFilter;
|
||||
|
||||
public AlphabeticalAppsList(Context context, AllAppsStore appsStore, boolean isWork) {
|
||||
public AlphabeticalAppsList(Context context, AllAppsStore appsStore,
|
||||
WorkAdapterProvider adapterProvider) {
|
||||
mAllAppsStore = appsStore;
|
||||
mLauncher = BaseDraggingActivity.fromContext(context);
|
||||
mAppNameComparator = new AppInfoComparator(context);
|
||||
mIsWork = isWork;
|
||||
mWorkAdapterProvider = adapterProvider;
|
||||
mNumAppsPerRow = mLauncher.getDeviceProfile().inv.numColumns;
|
||||
mAllAppsStore.addUpdateListener(this);
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
|
|||
* Updates the set of filtered apps with the current filter. At this point, we expect
|
||||
* mCachedSectionNames to have been calculated for the set of all apps in mApps.
|
||||
*/
|
||||
private void updateAdapterItems() {
|
||||
public void updateAdapterItems() {
|
||||
refillAdapterItems();
|
||||
refreshRecyclerView();
|
||||
}
|
||||
|
@ -292,6 +292,12 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
|
|||
|
||||
if (!hasFilter()) {
|
||||
mAccessibilityResultsCount = mApps.size();
|
||||
if (mWorkAdapterProvider != null) {
|
||||
position += mWorkAdapterProvider.addWorkItems(mAdapterItems);
|
||||
if (!mWorkAdapterProvider.shouldShowWorkApps()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (AppInfo info : mApps) {
|
||||
String sectionName = info.sectionName;
|
||||
|
||||
|
@ -303,7 +309,8 @@ public class AlphabeticalAppsList implements AllAppsStore.OnUpdateListener {
|
|||
}
|
||||
|
||||
// Create an app item
|
||||
AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, appIndex++);
|
||||
AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info,
|
||||
appIndex++);
|
||||
if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
|
||||
lastFastScrollerSectionInfo.fastScrollToItem = appItem;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.allapps;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* A UI expansion wrapper providing for providing dynamic recyclerview items
|
||||
*/
|
||||
public abstract class BaseAdapterProvider {
|
||||
|
||||
/**
|
||||
* Returns whether or not viewType can be handled by searchProvider
|
||||
*/
|
||||
public abstract boolean isViewSupported(int viewType);
|
||||
|
||||
/**
|
||||
* Called from RecyclerView.Adapter#onBindViewHolder
|
||||
*/
|
||||
public abstract void onBindView(AllAppsGridAdapter.ViewHolder holder, int position);
|
||||
|
||||
/**
|
||||
* Called from RecyclerView.Adapter#onCreateViewHolder
|
||||
*/
|
||||
public abstract AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
|
||||
ViewGroup parent, int viewType);
|
||||
|
||||
/**
|
||||
* Returns supported item per row combinations supported
|
||||
*/
|
||||
public int[] getSupportedItemsPerRowArray() {
|
||||
return new int[]{};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many cells a view should span
|
||||
*/
|
||||
public int getItemsPerRow(int viewType, int appsPerRow) {
|
||||
return appsPerRow;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.allapps;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A UI expansion wrapper providing for providing work profile specific views
|
||||
*/
|
||||
public class WorkAdapterProvider extends BaseAdapterProvider {
|
||||
|
||||
public static final String KEY_WORK_EDU_STEP = "showed_work_profile_edu";
|
||||
|
||||
private static final int VIEW_TYPE_WORK_EDU_CARD = 1 << 20;
|
||||
private static final int VIEW_TYPE_WORK_DISABLED_CARD = 1 << 21;
|
||||
private final Runnable mRefreshCB;
|
||||
private final BaseDraggingActivity mLauncher;
|
||||
private boolean mEnabled;
|
||||
|
||||
WorkAdapterProvider(BaseDraggingActivity launcher, Runnable refreshCallback) {
|
||||
mLauncher = launcher;
|
||||
mRefreshCB = refreshCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindView(AllAppsGridAdapter.ViewHolder holder, int position) {
|
||||
if (holder.itemView instanceof WorkEduCard) {
|
||||
((WorkEduCard) holder.itemView).setPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
|
||||
ViewGroup parent, int viewType) {
|
||||
int viewId = viewType == VIEW_TYPE_WORK_DISABLED_CARD ? R.layout.work_apps_paused
|
||||
: R.layout.work_apps_edu;
|
||||
return new AllAppsGridAdapter.ViewHolder(layoutInflater.inflate(viewId, parent, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns whether or not work apps should be visible in work tab.
|
||||
*/
|
||||
public boolean shouldShowWorkApps() {
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds work profile specific adapter items to adapterItems and returns number of items added
|
||||
*/
|
||||
public int addWorkItems(ArrayList<AllAppsGridAdapter.AdapterItem> adapterItems) {
|
||||
if (!mEnabled) {
|
||||
//add disabled card here.
|
||||
AllAppsGridAdapter.AdapterItem disabledCard = new AllAppsGridAdapter.AdapterItem();
|
||||
disabledCard.viewType = VIEW_TYPE_WORK_DISABLED_CARD;
|
||||
adapterItems.add(disabledCard);
|
||||
} else if (!isEduSeen()) {
|
||||
AllAppsGridAdapter.AdapterItem eduCard = new AllAppsGridAdapter.AdapterItem();
|
||||
eduCard.viewType = VIEW_TYPE_WORK_EDU_CARD;
|
||||
adapterItems.add(eduCard);
|
||||
}
|
||||
|
||||
return adapterItems.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current state of work profile
|
||||
*/
|
||||
public void updateCurrentState(boolean isEnabled) {
|
||||
mEnabled = isEnabled;
|
||||
mRefreshCB.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewSupported(int viewType) {
|
||||
return viewType == VIEW_TYPE_WORK_DISABLED_CARD || viewType == VIEW_TYPE_WORK_EDU_CARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsPerRow(int viewType, int appsPerRow) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
private boolean isEduSeen() {
|
||||
return Utilities.getPrefs(mLauncher).getInt(KEY_WORK_EDU_STEP, 0) != 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.allapps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
|
||||
/**
|
||||
* Work profile toggle switch shown at the bottom of AllApps work tab
|
||||
*/
|
||||
public class WorkEduCard extends LinearLayout implements View.OnClickListener,
|
||||
Animation.AnimationListener {
|
||||
|
||||
private final Launcher mLauncher;
|
||||
Animation mDismissAnim;
|
||||
private int mPosition = -1;
|
||||
|
||||
public WorkEduCard(Context context) {
|
||||
this(context, null, 0);
|
||||
}
|
||||
|
||||
public WorkEduCard(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public WorkEduCard(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mLauncher = Launcher.getLauncher(getContext());
|
||||
mDismissAnim = AnimationUtils.loadAnimation(context, android.R.anim.fade_out);
|
||||
mDismissAnim.setDuration(500);
|
||||
mDismissAnim.setAnimationListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
findViewById(R.id.action_btn).setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
startAnimation(mDismissAnim);
|
||||
mLauncher.getSharedPrefs().edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP, 1).apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
removeCard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
private void removeCard() {
|
||||
if (mPosition == -1) {
|
||||
if (getParent() != null) ((ViewGroup) getParent()).removeView(WorkEduCard.this);
|
||||
} else {
|
||||
AllAppsRecyclerView rv = mLauncher.getAppsView()
|
||||
.mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView;
|
||||
rv.getApps().getAdapterItems().remove(mPosition);
|
||||
rv.getAdapter().notifyItemRemoved(mPosition);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
mPosition = position;
|
||||
}
|
||||
|
||||
}
|
|
@ -57,7 +57,7 @@ public class DefaultSearchAdapterProvider extends SearchAdapterProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isSearchView(int viewType) {
|
||||
public boolean isViewSupported(int viewType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,20 +17,18 @@
|
|||
package com.android.launcher3.allapps.search;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsGridAdapter;
|
||||
import com.android.launcher3.allapps.BaseAdapterProvider;
|
||||
|
||||
/**
|
||||
* A UI expansion wrapper providing for search results
|
||||
*/
|
||||
public abstract class SearchAdapterProvider {
|
||||
public abstract class SearchAdapterProvider extends BaseAdapterProvider {
|
||||
|
||||
protected final BaseDraggingActivity mLauncher;
|
||||
|
||||
|
@ -38,42 +36,12 @@ public abstract class SearchAdapterProvider {
|
|||
mLauncher = launcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from RecyclerView.Adapter#onBindViewHolder
|
||||
*/
|
||||
public abstract void onBindView(AllAppsGridAdapter.ViewHolder holder, int position);
|
||||
|
||||
/**
|
||||
* Called from LiveSearchManager to notify slice status updates.
|
||||
*/
|
||||
public void onSliceStatusUpdate(Uri sliceUri) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not viewType can be handled by searchProvider
|
||||
*/
|
||||
public abstract boolean isSearchView(int viewType);
|
||||
|
||||
/**
|
||||
* Called from RecyclerView.Adapter#onCreateViewHolder
|
||||
*/
|
||||
public abstract AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
|
||||
ViewGroup parent, int viewType);
|
||||
|
||||
/**
|
||||
* Returns supported item per row combinations supported
|
||||
*/
|
||||
public int[] getSupportedItemsPerRowArray() {
|
||||
return new int[]{};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many cells a view should span
|
||||
*/
|
||||
public int getItemsPerRow(int viewType, int appsPerRow) {
|
||||
return appsPerRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles selection event on search adapter item. Returns false if provider can not handle
|
||||
* event
|
||||
|
|
Loading…
Reference in New Issue