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:
Samuel Fufa 2021-06-14 19:34:04 +00:00 committed by Automerger Merge Worker
commit b2d6d73377
16 changed files with 433 additions and 132 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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"

View File

@ -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" />

View File

@ -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>

View File

@ -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>

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -57,7 +57,7 @@ public class DefaultSearchAdapterProvider extends SearchAdapterProvider {
}
@Override
public boolean isSearchView(int viewType) {
public boolean isViewSupported(int viewType) {
return false;
}

View File

@ -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