Loading res/layout/work_tab_footer.xml→res/layout/work_mode_switch.xml +16 −29 Original line number Diff line number Diff line Loading @@ -13,39 +13,26 @@ See the License for the specific language governing permissions and limitations under the License. --> <com.android.launcher3.views.WorkFooterContainer <com.android.launcher3.allapps.WorkModeSwitch xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/work_toggle_container" android:focusable="true" android:orientation="horizontal" android:background="?attr/allAppsScrimColor" android:paddingBottom="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingLeft="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingRight="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingTop="@dimen/all_apps_work_profile_tab_footer_padding"> <TextView style="@style/PrimaryMediumText" android:id="@+id/work_mode_label" android:layout_width="0dp" android:layout_weight="1" android:id="@+id/work_mode_toggle" android:drawableStart="@drawable/ic_corp" android:drawablePadding="16dp" android:drawableTint="?attr/workProfileOverlayTextColor" android:textColor="?attr/workProfileOverlayTextColor" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:ellipsize="end" android:gravity="center_vertical" android:gravity="start" android:lines="1" android:minHeight="24dp" android:paddingEnd="12dp" android:showText="false" android:textSize="16sp" android:background="?attr/allAppsScrimColor" android:text="@string/work_profile_toggle_label" android:textSize="16sp"/> <com.android.launcher3.allapps.WorkModeSwitch android:id="@+id/work_mode_toggle" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </com.android.launcher3.views.WorkFooterContainer> No newline at end of file android:paddingBottom="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingLeft="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingRight="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingTop="@dimen/all_apps_work_profile_tab_footer_padding" /> src/com/android/launcher3/allapps/AllAppsContainerView.java +17 −20 Original line number Diff line number Diff line Loading @@ -62,7 +62,6 @@ import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.Themes; import com.android.launcher3.views.RecyclerViewFastScroller; import com.android.launcher3.views.SpringRelativeLayout; import com.android.launcher3.views.WorkFooterContainer; import java.util.ArrayList; Loading Loading @@ -91,7 +90,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo private AllAppsPagedView mViewPager; private FloatingHeaderView mHeader; private WorkFooterContainer mWorkFooterContainer; private WorkModeSwitch mWorkModeSwitch; private SpannableStringBuilder mSearchQueryBuilder = null; Loading Loading @@ -156,8 +155,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo return mMultiValueAlpha.getProperty(index); } public WorkFooterContainer getWorkFooterContainer() { return mWorkFooterContainer; public WorkModeSwitch getWorkModeSwitch() { return mWorkModeSwitch; } Loading Loading @@ -195,7 +194,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo } private void resetWorkProfile() { mWorkFooterContainer.refresh(); mWorkModeSwitch.refresh(); mAH[AdapterHolder.WORK].setupOverlay(); mAH[AdapterHolder.WORK].applyPadding(); } Loading Loading @@ -410,9 +409,9 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo } else { mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null); mAH[AdapterHolder.WORK].recyclerView = null; if (mWorkFooterContainer != null) { ((ViewGroup) mWorkFooterContainer.getParent()).removeView(mWorkFooterContainer); mWorkFooterContainer = null; if (mWorkModeSwitch != null) { ((ViewGroup) mWorkModeSwitch.getParent()).removeView(mWorkModeSwitch); mWorkModeSwitch = null; } } setupHeader(); Loading @@ -422,14 +421,11 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo } private void setupWorkToggle() { mWorkFooterContainer = (WorkFooterContainer) mLauncher.getLayoutInflater().inflate( R.layout.work_tab_footer, findViewById(R.id.work_toggle_container)); mWorkFooterContainer.setLayoutParams( new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); this.addView(mWorkFooterContainer); mWorkFooterContainer.setInsets(mInsets); mWorkFooterContainer.post(() -> mAH[AdapterHolder.WORK].applyPadding()); mWorkModeSwitch = (WorkModeSwitch) mLauncher.getLayoutInflater().inflate( R.layout.work_mode_switch, this, false); this.addView(mWorkModeSwitch); mWorkModeSwitch.setInsets(mInsets); mWorkModeSwitch.post(() -> mAH[AdapterHolder.WORK].applyPadding()); } private void replaceRVContainer(boolean showTabs) { Loading Loading @@ -469,8 +465,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo findViewById(R.id.tab_work) .setOnClickListener((View view) -> mViewPager.snapToPage(AdapterHolder.WORK)); } if (mWorkFooterContainer != null) { mWorkFooterContainer.setWorkTabVisible(pos == AdapterHolder.WORK); if (mWorkModeSwitch != null) { mWorkModeSwitch.setWorkTabVisible(pos == AdapterHolder.WORK); } } Loading Loading @@ -648,6 +644,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo if (!mIsWork || recyclerView == null) return; boolean workDisabled = UserCache.INSTANCE.get(mLauncher).isAnyProfileQuietModeEnabled(); if (mWorkDisabled == workDisabled) return; recyclerView.setContentDescription( workDisabled ? mLauncher.getString(R.string.work_apps_paused_title) : null); if (workDisabled) { appsList.updateItemFilter((info, cn) -> false); recyclerView.addAutoSizedOverlay( Loading @@ -662,8 +660,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo void applyPadding() { if (recyclerView != null) { int bottomOffset = mWorkFooterContainer != null && mIsWork ? mWorkFooterContainer.getHeight() : 0; mWorkModeSwitch != null && mIsWork ? mWorkModeSwitch.getHeight() : 0; recyclerView.setPadding(padding.left, padding.top, padding.right, padding.bottom + bottomOffset); } Loading src/com/android/launcher3/allapps/WorkModeSwitch.java +60 −3 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * 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. Loading @@ -15,7 +15,13 @@ */ package com.android.launcher3.allapps; import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.AsyncTask; import android.os.Process; import android.os.UserHandle; Loading @@ -24,28 +30,45 @@ import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.Switch; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.pm.UserCache; import java.lang.ref.WeakReference; public class WorkModeSwitch extends Switch { /** * Work profile toggle switch shown at the bottom of AllApps work tab */ public class WorkModeSwitch extends Switch implements Insettable { private Rect mInsets = new Rect(); protected ObjectAnimator mOpenCloseAnimator; public WorkModeSwitch(Context context) { super(context); init(); } public WorkModeSwitch(Context context, AttributeSet attrs) { super(context, attrs); init(); } public WorkModeSwitch(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mOpenCloseAnimator = ObjectAnimator.ofPropertyValuesHolder(this); } @Override public void setChecked(boolean checked) { // No-op, do not change the checked state until broadcast is received. } @Override Loading @@ -55,14 +78,23 @@ public class WorkModeSwitch extends Switch { private void setCheckedInternal(boolean checked) { super.setChecked(checked); setCompoundDrawablesWithIntrinsicBounds( checked ? R.drawable.ic_corp : R.drawable.ic_corp_off, 0, 0, 0); } public void refresh() { if (!shouldShowWorkSwitch()) return; UserCache userManager = UserCache.INSTANCE.get(getContext()); setCheckedInternal(!userManager.isAnyProfileQuietModeEnabled()); setEnabled(true); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); this.setVisibility(shouldShowWorkSwitch() ? VISIBLE : GONE); } @Override public boolean onTouchEvent(MotionEvent ev) { return ev.getActionMasked() == MotionEvent.ACTION_MOVE || super.onTouchEvent(ev); Loading @@ -72,6 +104,24 @@ public class WorkModeSwitch extends Switch { new SetQuietModeEnabledAsyncTask(enabled, new WeakReference<>(this)).execute(); } @Override public void setInsets(Rect insets) { int bottomInset = insets.bottom - mInsets.bottom; mInsets.set(insets); setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + bottomInset); } /** * Animates in/out work profile toggle panel based on the tab user is on */ public void setWorkTabVisible(boolean workTabVisible) { if (!shouldShowWorkSwitch()) return; mOpenCloseAnimator.setValues(PropertyValuesHolder.ofFloat(ALPHA, workTabVisible ? 1 : 0)); mOpenCloseAnimator.start(); } private static final class SetQuietModeEnabledAsyncTask extends AsyncTask<Void, Void, Boolean> { Loading Loading @@ -122,4 +172,11 @@ public class WorkModeSwitch extends Switch { } } } private boolean shouldShowWorkSwitch() { Launcher launcher = Launcher.getLauncher(getContext()); return Utilities.ATLEAST_P && (hasShortcutsPermission(launcher) || launcher.checkSelfPermission("android.permission.MODIFY_QUIET_MODE") == PackageManager.PERMISSION_GRANTED); } } src/com/android/launcher3/views/WorkFooterContainer.javadeleted 100644 → 0 +0 −133 Original line number Diff line number Diff line /* * 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. */ package com.android.launcher3.views; import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.allapps.WorkModeSwitch; import com.android.launcher3.pm.UserCache; /** * Container to show work footer in all-apps. */ public class WorkFooterContainer extends LinearLayout implements Insettable { private Rect mInsets = new Rect(); private WorkModeSwitch mWorkModeSwitch; private TextView mWorkModeLabel; protected final ObjectAnimator mOpenCloseAnimator; public WorkFooterContainer(Context context) { this(context, null, 0); } public WorkFooterContainer(Context context, AttributeSet attrs) { this(context, attrs, 0); } public WorkFooterContainer(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mOpenCloseAnimator = ObjectAnimator.ofPropertyValuesHolder(this); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); updateTranslation(); this.setVisibility(shouldShowWorkFooter() ? VISIBLE : GONE); } @Override protected void onFinishInflate() { super.onFinishInflate(); mWorkModeSwitch = findViewById(R.id.work_mode_toggle); mWorkModeLabel = findViewById(R.id.work_mode_label); } @Override public void offsetTopAndBottom(int offset) { super.offsetTopAndBottom(offset); updateTranslation(); } private void updateTranslation() { if (getParent() instanceof View) { View parent = (View) getParent(); int availableBot = parent.getHeight() - parent.getPaddingBottom(); setTranslationY(Math.max(0, availableBot - getBottom())); } } @Override public void setInsets(Rect insets) { int bottomInset = insets.bottom - mInsets.bottom; mInsets.set(insets); setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + bottomInset); } /** * Animates in/out work profile toggle panel based on the tab user is on */ public void setWorkTabVisible(boolean workTabVisible) { if (!shouldShowWorkFooter()) return; mOpenCloseAnimator.setValues(PropertyValuesHolder.ofFloat(ALPHA, workTabVisible ? 1 : 0)); mOpenCloseAnimator.start(); } /** * Refreshes views based on current work profile enabled status */ public void refresh() { if (!shouldShowWorkFooter()) return; boolean anyProfileQuietModeEnabled = UserCache.INSTANCE.get( getContext()).isAnyProfileQuietModeEnabled(); mWorkModeLabel.setCompoundDrawablesWithIntrinsicBounds( anyProfileQuietModeEnabled ? R.drawable.ic_corp_off : R.drawable.ic_corp, 0, 0, 0); mWorkModeSwitch.refresh(); } /** * Returns work mode switch */ public WorkModeSwitch getWorkModeSwitch() { return mWorkModeSwitch; } private boolean shouldShowWorkFooter() { Launcher launcher = Launcher.getLauncher(getContext()); return Utilities.ATLEAST_P && (hasShortcutsPermission(launcher) || launcher.checkSelfPermission("android.permission.MODIFY_QUIET_MODE") == PackageManager.PERMISSION_GRANTED); } } tests/src/com/android/launcher3/ui/WorkTabTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -31,9 +31,9 @@ import androidx.test.runner.AndroidJUnit4; import com.android.launcher3.R; import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsPagedView; import com.android.launcher3.allapps.WorkModeSwitch; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.views.WorkEduView; import com.android.launcher3.views.WorkFooterContainer; import org.junit.After; import org.junit.Before; Loading Loading @@ -87,7 +87,7 @@ public class WorkTabTest extends AbstractLauncherUiTest { executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS)); waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS); getOnceNotNull("Apps view did not bind", launcher -> launcher.getAppsView().getWorkFooterContainer(), 60000); launcher -> launcher.getAppsView().getWorkModeSwitch(), 60000); UserManager userManager = getFromLauncher(l -> l.getSystemService(UserManager.class)); assertEquals(2, userManager.getUserProfiles().size()); Loading @@ -102,10 +102,10 @@ public class WorkTabTest extends AbstractLauncherUiTest { assertTrue(userManager.isQuietModeEnabled(workProfile)); executeOnLauncher(launcher -> { WorkFooterContainer wf = launcher.getAppsView().getWorkFooterContainer(); WorkModeSwitch wf = launcher.getAppsView().getWorkModeSwitch(); ((AllAppsPagedView) launcher.getAppsView().getContentView()).snapToPageImmediately( AllAppsContainerView.AdapterHolder.WORK); wf.getWorkModeSwitch().toggle(); wf.toggle(); }); waitForLauncherCondition("Work toggle did not work", l -> l.getSystemService(UserManager.class).isQuietModeEnabled(workProfile)); Loading Loading
res/layout/work_tab_footer.xml→res/layout/work_mode_switch.xml +16 −29 Original line number Diff line number Diff line Loading @@ -13,39 +13,26 @@ See the License for the specific language governing permissions and limitations under the License. --> <com.android.launcher3.views.WorkFooterContainer <com.android.launcher3.allapps.WorkModeSwitch xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/work_toggle_container" android:focusable="true" android:orientation="horizontal" android:background="?attr/allAppsScrimColor" android:paddingBottom="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingLeft="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingRight="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingTop="@dimen/all_apps_work_profile_tab_footer_padding"> <TextView style="@style/PrimaryMediumText" android:id="@+id/work_mode_label" android:layout_width="0dp" android:layout_weight="1" android:id="@+id/work_mode_toggle" android:drawableStart="@drawable/ic_corp" android:drawablePadding="16dp" android:drawableTint="?attr/workProfileOverlayTextColor" android:textColor="?attr/workProfileOverlayTextColor" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:ellipsize="end" android:gravity="center_vertical" android:gravity="start" android:lines="1" android:minHeight="24dp" android:paddingEnd="12dp" android:showText="false" android:textSize="16sp" android:background="?attr/allAppsScrimColor" android:text="@string/work_profile_toggle_label" android:textSize="16sp"/> <com.android.launcher3.allapps.WorkModeSwitch android:id="@+id/work_mode_toggle" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </com.android.launcher3.views.WorkFooterContainer> No newline at end of file android:paddingBottom="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingLeft="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingRight="@dimen/all_apps_work_profile_tab_footer_padding" android:paddingTop="@dimen/all_apps_work_profile_tab_footer_padding" />
src/com/android/launcher3/allapps/AllAppsContainerView.java +17 −20 Original line number Diff line number Diff line Loading @@ -62,7 +62,6 @@ import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.Themes; import com.android.launcher3.views.RecyclerViewFastScroller; import com.android.launcher3.views.SpringRelativeLayout; import com.android.launcher3.views.WorkFooterContainer; import java.util.ArrayList; Loading Loading @@ -91,7 +90,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo private AllAppsPagedView mViewPager; private FloatingHeaderView mHeader; private WorkFooterContainer mWorkFooterContainer; private WorkModeSwitch mWorkModeSwitch; private SpannableStringBuilder mSearchQueryBuilder = null; Loading Loading @@ -156,8 +155,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo return mMultiValueAlpha.getProperty(index); } public WorkFooterContainer getWorkFooterContainer() { return mWorkFooterContainer; public WorkModeSwitch getWorkModeSwitch() { return mWorkModeSwitch; } Loading Loading @@ -195,7 +194,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo } private void resetWorkProfile() { mWorkFooterContainer.refresh(); mWorkModeSwitch.refresh(); mAH[AdapterHolder.WORK].setupOverlay(); mAH[AdapterHolder.WORK].applyPadding(); } Loading Loading @@ -410,9 +409,9 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo } else { mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null); mAH[AdapterHolder.WORK].recyclerView = null; if (mWorkFooterContainer != null) { ((ViewGroup) mWorkFooterContainer.getParent()).removeView(mWorkFooterContainer); mWorkFooterContainer = null; if (mWorkModeSwitch != null) { ((ViewGroup) mWorkModeSwitch.getParent()).removeView(mWorkModeSwitch); mWorkModeSwitch = null; } } setupHeader(); Loading @@ -422,14 +421,11 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo } private void setupWorkToggle() { mWorkFooterContainer = (WorkFooterContainer) mLauncher.getLayoutInflater().inflate( R.layout.work_tab_footer, findViewById(R.id.work_toggle_container)); mWorkFooterContainer.setLayoutParams( new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); this.addView(mWorkFooterContainer); mWorkFooterContainer.setInsets(mInsets); mWorkFooterContainer.post(() -> mAH[AdapterHolder.WORK].applyPadding()); mWorkModeSwitch = (WorkModeSwitch) mLauncher.getLayoutInflater().inflate( R.layout.work_mode_switch, this, false); this.addView(mWorkModeSwitch); mWorkModeSwitch.setInsets(mInsets); mWorkModeSwitch.post(() -> mAH[AdapterHolder.WORK].applyPadding()); } private void replaceRVContainer(boolean showTabs) { Loading Loading @@ -469,8 +465,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo findViewById(R.id.tab_work) .setOnClickListener((View view) -> mViewPager.snapToPage(AdapterHolder.WORK)); } if (mWorkFooterContainer != null) { mWorkFooterContainer.setWorkTabVisible(pos == AdapterHolder.WORK); if (mWorkModeSwitch != null) { mWorkModeSwitch.setWorkTabVisible(pos == AdapterHolder.WORK); } } Loading Loading @@ -648,6 +644,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo if (!mIsWork || recyclerView == null) return; boolean workDisabled = UserCache.INSTANCE.get(mLauncher).isAnyProfileQuietModeEnabled(); if (mWorkDisabled == workDisabled) return; recyclerView.setContentDescription( workDisabled ? mLauncher.getString(R.string.work_apps_paused_title) : null); if (workDisabled) { appsList.updateItemFilter((info, cn) -> false); recyclerView.addAutoSizedOverlay( Loading @@ -662,8 +660,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo void applyPadding() { if (recyclerView != null) { int bottomOffset = mWorkFooterContainer != null && mIsWork ? mWorkFooterContainer.getHeight() : 0; mWorkModeSwitch != null && mIsWork ? mWorkModeSwitch.getHeight() : 0; recyclerView.setPadding(padding.left, padding.top, padding.right, padding.bottom + bottomOffset); } Loading
src/com/android/launcher3/allapps/WorkModeSwitch.java +60 −3 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * 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. Loading @@ -15,7 +15,13 @@ */ package com.android.launcher3.allapps; import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.AsyncTask; import android.os.Process; import android.os.UserHandle; Loading @@ -24,28 +30,45 @@ import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.Switch; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.pm.UserCache; import java.lang.ref.WeakReference; public class WorkModeSwitch extends Switch { /** * Work profile toggle switch shown at the bottom of AllApps work tab */ public class WorkModeSwitch extends Switch implements Insettable { private Rect mInsets = new Rect(); protected ObjectAnimator mOpenCloseAnimator; public WorkModeSwitch(Context context) { super(context); init(); } public WorkModeSwitch(Context context, AttributeSet attrs) { super(context, attrs); init(); } public WorkModeSwitch(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mOpenCloseAnimator = ObjectAnimator.ofPropertyValuesHolder(this); } @Override public void setChecked(boolean checked) { // No-op, do not change the checked state until broadcast is received. } @Override Loading @@ -55,14 +78,23 @@ public class WorkModeSwitch extends Switch { private void setCheckedInternal(boolean checked) { super.setChecked(checked); setCompoundDrawablesWithIntrinsicBounds( checked ? R.drawable.ic_corp : R.drawable.ic_corp_off, 0, 0, 0); } public void refresh() { if (!shouldShowWorkSwitch()) return; UserCache userManager = UserCache.INSTANCE.get(getContext()); setCheckedInternal(!userManager.isAnyProfileQuietModeEnabled()); setEnabled(true); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); this.setVisibility(shouldShowWorkSwitch() ? VISIBLE : GONE); } @Override public boolean onTouchEvent(MotionEvent ev) { return ev.getActionMasked() == MotionEvent.ACTION_MOVE || super.onTouchEvent(ev); Loading @@ -72,6 +104,24 @@ public class WorkModeSwitch extends Switch { new SetQuietModeEnabledAsyncTask(enabled, new WeakReference<>(this)).execute(); } @Override public void setInsets(Rect insets) { int bottomInset = insets.bottom - mInsets.bottom; mInsets.set(insets); setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + bottomInset); } /** * Animates in/out work profile toggle panel based on the tab user is on */ public void setWorkTabVisible(boolean workTabVisible) { if (!shouldShowWorkSwitch()) return; mOpenCloseAnimator.setValues(PropertyValuesHolder.ofFloat(ALPHA, workTabVisible ? 1 : 0)); mOpenCloseAnimator.start(); } private static final class SetQuietModeEnabledAsyncTask extends AsyncTask<Void, Void, Boolean> { Loading Loading @@ -122,4 +172,11 @@ public class WorkModeSwitch extends Switch { } } } private boolean shouldShowWorkSwitch() { Launcher launcher = Launcher.getLauncher(getContext()); return Utilities.ATLEAST_P && (hasShortcutsPermission(launcher) || launcher.checkSelfPermission("android.permission.MODIFY_QUIET_MODE") == PackageManager.PERMISSION_GRANTED); } }
src/com/android/launcher3/views/WorkFooterContainer.javadeleted 100644 → 0 +0 −133 Original line number Diff line number Diff line /* * 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. */ package com.android.launcher3.views; import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.allapps.WorkModeSwitch; import com.android.launcher3.pm.UserCache; /** * Container to show work footer in all-apps. */ public class WorkFooterContainer extends LinearLayout implements Insettable { private Rect mInsets = new Rect(); private WorkModeSwitch mWorkModeSwitch; private TextView mWorkModeLabel; protected final ObjectAnimator mOpenCloseAnimator; public WorkFooterContainer(Context context) { this(context, null, 0); } public WorkFooterContainer(Context context, AttributeSet attrs) { this(context, attrs, 0); } public WorkFooterContainer(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mOpenCloseAnimator = ObjectAnimator.ofPropertyValuesHolder(this); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); updateTranslation(); this.setVisibility(shouldShowWorkFooter() ? VISIBLE : GONE); } @Override protected void onFinishInflate() { super.onFinishInflate(); mWorkModeSwitch = findViewById(R.id.work_mode_toggle); mWorkModeLabel = findViewById(R.id.work_mode_label); } @Override public void offsetTopAndBottom(int offset) { super.offsetTopAndBottom(offset); updateTranslation(); } private void updateTranslation() { if (getParent() instanceof View) { View parent = (View) getParent(); int availableBot = parent.getHeight() - parent.getPaddingBottom(); setTranslationY(Math.max(0, availableBot - getBottom())); } } @Override public void setInsets(Rect insets) { int bottomInset = insets.bottom - mInsets.bottom; mInsets.set(insets); setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + bottomInset); } /** * Animates in/out work profile toggle panel based on the tab user is on */ public void setWorkTabVisible(boolean workTabVisible) { if (!shouldShowWorkFooter()) return; mOpenCloseAnimator.setValues(PropertyValuesHolder.ofFloat(ALPHA, workTabVisible ? 1 : 0)); mOpenCloseAnimator.start(); } /** * Refreshes views based on current work profile enabled status */ public void refresh() { if (!shouldShowWorkFooter()) return; boolean anyProfileQuietModeEnabled = UserCache.INSTANCE.get( getContext()).isAnyProfileQuietModeEnabled(); mWorkModeLabel.setCompoundDrawablesWithIntrinsicBounds( anyProfileQuietModeEnabled ? R.drawable.ic_corp_off : R.drawable.ic_corp, 0, 0, 0); mWorkModeSwitch.refresh(); } /** * Returns work mode switch */ public WorkModeSwitch getWorkModeSwitch() { return mWorkModeSwitch; } private boolean shouldShowWorkFooter() { Launcher launcher = Launcher.getLauncher(getContext()); return Utilities.ATLEAST_P && (hasShortcutsPermission(launcher) || launcher.checkSelfPermission("android.permission.MODIFY_QUIET_MODE") == PackageManager.PERMISSION_GRANTED); } }
tests/src/com/android/launcher3/ui/WorkTabTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -31,9 +31,9 @@ import androidx.test.runner.AndroidJUnit4; import com.android.launcher3.R; import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsPagedView; import com.android.launcher3.allapps.WorkModeSwitch; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.views.WorkEduView; import com.android.launcher3.views.WorkFooterContainer; import org.junit.After; import org.junit.Before; Loading Loading @@ -87,7 +87,7 @@ public class WorkTabTest extends AbstractLauncherUiTest { executeOnLauncher(launcher -> launcher.getStateManager().goToState(ALL_APPS)); waitForState("Launcher internal state didn't switch to All Apps", () -> ALL_APPS); getOnceNotNull("Apps view did not bind", launcher -> launcher.getAppsView().getWorkFooterContainer(), 60000); launcher -> launcher.getAppsView().getWorkModeSwitch(), 60000); UserManager userManager = getFromLauncher(l -> l.getSystemService(UserManager.class)); assertEquals(2, userManager.getUserProfiles().size()); Loading @@ -102,10 +102,10 @@ public class WorkTabTest extends AbstractLauncherUiTest { assertTrue(userManager.isQuietModeEnabled(workProfile)); executeOnLauncher(launcher -> { WorkFooterContainer wf = launcher.getAppsView().getWorkFooterContainer(); WorkModeSwitch wf = launcher.getAppsView().getWorkModeSwitch(); ((AllAppsPagedView) launcher.getAppsView().getContentView()).snapToPageImmediately( AllAppsContainerView.AdapterHolder.WORK); wf.getWorkModeSwitch().toggle(); wf.toggle(); }); waitForLauncherCondition("Work toggle did not work", l -> l.getSystemService(UserManager.class).isQuietModeEnabled(workProfile)); Loading