Launch channel settings as half sheet
If opening app has requested only a subset of fields Test: manual - launch from an app, filtered and unfiltered, for normal channels and conversations Bug: 177246841 Change-Id: Ifd70478101d1ea1340d2ecc55033fab55e65ca92 Change-Id: I5194b959c82b2cfa7990c84285aaf69464cff3a8
This commit is contained in:
@@ -2803,8 +2803,13 @@
|
||||
</activity>
|
||||
|
||||
<!-- Show channel-level notification settings (channel passed in as extras) -->
|
||||
<activity android:name="Settings$ChannelNotificationSettingsActivity"
|
||||
<activity android:name=".notification.app.ChannelPanelActivity"
|
||||
android:label="@string/notification_channel_title"
|
||||
android:theme="@style/Theme.Panel"
|
||||
android:launchMode="singleInstance"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:exported="true">
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="android.settings.CHANNEL_NOTIFICATION_SETTINGS" />
|
||||
|
66
res/layout/notification_channel_panel.xml
Normal file
66
res/layout/notification_channel_panel.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main_content"
|
||||
android:layout_height="@dimen/output_switcher_slice_max_height"
|
||||
android:background="@drawable/settings_panel_background"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@android:id/list_container"
|
||||
android:layout_height="0px"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="match_parent"/>
|
||||
|
||||
<View
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/footer_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/horizontal_divider_height"
|
||||
android:background="?android:attr/dividerHorizontal"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/footer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/see_more"
|
||||
style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/see_more"/>
|
||||
|
||||
<Space
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/done"
|
||||
style="@android:style/Widget.DeviceDefault.Button.Borderless.Colored"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:text="@string/done"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@@ -62,10 +62,6 @@
|
||||
android:key="block_desc"
|
||||
settings:allowDividerAbove="false"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="channel_advanced"
|
||||
android:order="50"
|
||||
settings:initialExpandedChildrenCount="0">
|
||||
|
||||
<!-- peeking -->
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
@@ -107,6 +103,5 @@
|
||||
android:icon="@drawable/ic_volume_ringer_vibrate"
|
||||
android:title="@string/notification_vibrate_title"
|
||||
settings:useAdditionalSummary="true" />
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
@@ -68,12 +68,16 @@ public class ChannelNotificationSettings extends NotificationSettings {
|
||||
|
||||
if (mChannel != null && !TextUtils.isEmpty(mChannel.getConversationId())
|
||||
&& !mChannel.isDemoted()) {
|
||||
startActivity(new SubSettingLauncher(mContext)
|
||||
Intent intent = new SubSettingLauncher(mContext)
|
||||
.setDestination(ConversationNotificationSettings.class.getName())
|
||||
.setArguments(getArguments())
|
||||
.setExtras(getIntent() != null ? getIntent().getExtras(): null)
|
||||
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_TOPIC_NOTIFICATION)
|
||||
.toIntent());
|
||||
.toIntent();
|
||||
if (mPreferenceFilter != null) {
|
||||
intent.setClass(mContext, ChannelPanelActivity.class);
|
||||
}
|
||||
startActivity(intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
@@ -84,6 +88,7 @@ public class ChannelNotificationSettings extends NotificationSettings {
|
||||
controller.displayPreference(getPreferenceScreen());
|
||||
}
|
||||
updatePreferenceStates();
|
||||
animatePanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.settings.notification.app;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.HideNonSystemOverlayMixin;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
|
||||
/**
|
||||
* Dialog Activity to host channel settings
|
||||
*/
|
||||
public class ChannelPanelActivity extends FragmentActivity {
|
||||
|
||||
private static final String TAG = "ChannelPanelActivity";
|
||||
|
||||
final Bundle mBundle = new Bundle();
|
||||
NotificationSettings mPanelFragment;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (!getIntent().hasExtra(Settings.EXTRA_CHANNEL_FILTER_LIST)) {
|
||||
launchFullSettings();
|
||||
}
|
||||
|
||||
getApplicationContext().getTheme().rebase();
|
||||
createOrUpdatePanel();
|
||||
getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
createOrUpdatePanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
private void launchFullSettings() {
|
||||
Bundle extras = getIntent().getExtras();
|
||||
extras.remove(Settings.EXTRA_CHANNEL_FILTER_LIST);
|
||||
startActivity(new SubSettingLauncher(this)
|
||||
.setDestination(ChannelNotificationSettings.class.getName())
|
||||
.setExtras(extras)
|
||||
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_TOPIC_NOTIFICATION)
|
||||
.toIntent());
|
||||
finish();
|
||||
}
|
||||
|
||||
private void createOrUpdatePanel() {
|
||||
final Intent callingIntent = getIntent();
|
||||
if (callingIntent == null) {
|
||||
Log.e(TAG, "Null intent, closing Panel Activity");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
final FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
setContentView(R.layout.notification_channel_panel);
|
||||
|
||||
// Move the window to the bottom of screen, and make it take up the entire screen width.
|
||||
final Window window = getWindow();
|
||||
window.setGravity(Gravity.BOTTOM);
|
||||
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
findViewById(R.id.done).setOnClickListener(v -> finish());
|
||||
findViewById(R.id.see_more).setOnClickListener(v -> launchFullSettings());
|
||||
|
||||
mPanelFragment = callingIntent.hasExtra(Settings.EXTRA_CONVERSATION_ID)
|
||||
? new ConversationNotificationSettings()
|
||||
: new ChannelNotificationSettings();
|
||||
mPanelFragment.setArguments(new Bundle(mBundle));
|
||||
fragmentManager.beginTransaction().replace(
|
||||
android.R.id.list_container, mPanelFragment).commit();
|
||||
}
|
||||
}
|
@@ -93,6 +93,7 @@ public class ConversationHeaderPreferenceController extends NotificationPreferen
|
||||
.done(activity, mContext);
|
||||
|
||||
pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE);
|
||||
pref.findViewById(R.id.entity_header).setBackground(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -49,10 +49,11 @@ public class ConversationNotificationSettings extends NotificationSettings {
|
||||
|
||||
for (NotificationPreferenceController controller : mControllers) {
|
||||
controller.onResume(mAppRow, mChannel, mChannelGroup, mConversationDrawable,
|
||||
mConversationInfo, mSuspendedAppsAdmin, null);
|
||||
mConversationInfo, mSuspendedAppsAdmin, mPreferenceFilter);
|
||||
controller.displayPreference(getPreferenceScreen());
|
||||
}
|
||||
updatePreferenceStates();
|
||||
animatePanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -92,6 +92,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController
|
||||
.setRecyclerView(mFragment.getListView(), mFragment.getSettingsLifecycle())
|
||||
.done(activity, mContext);
|
||||
pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE);
|
||||
pref.findViewById(R.id.entity_header).setBackground(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,9 @@ package com.android.settings.notification.app;
|
||||
|
||||
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
@@ -39,8 +42,13 @@ import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -85,6 +93,20 @@ abstract public class NotificationSettings extends DashboardFragment {
|
||||
protected Intent mIntent;
|
||||
protected Bundle mArgs;
|
||||
|
||||
private ViewGroup mLayoutView;
|
||||
private static final int DURATION_ANIMATE_PANEL_EXPAND_MS = 250;
|
||||
|
||||
private final ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener =
|
||||
new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
animateIn();
|
||||
if (mLayoutView != null) {
|
||||
mLayoutView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
@@ -187,6 +209,50 @@ abstract public class NotificationSettings extends DashboardFragment {
|
||||
collectConfigActivities();
|
||||
}
|
||||
|
||||
protected void animatePanel() {
|
||||
if (mPreferenceFilter != null) {
|
||||
mLayoutView = getActivity().findViewById(R.id.main_content);
|
||||
mLayoutView.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate a Panel onto the screen.
|
||||
* <p>
|
||||
* Takes the entire panel and animates in from behind the navigation bar.
|
||||
* <p>
|
||||
* Relies on the Panel being having a fixed height to begin the animation.
|
||||
*/
|
||||
private void animateIn() {
|
||||
final AnimatorSet animatorSet = buildAnimatorSet(mLayoutView,
|
||||
mLayoutView.getHeight() /* startY */, 0.0f /* endY */,
|
||||
0.0f /* startAlpha */, 1.0f /* endAlpha */,
|
||||
DURATION_ANIMATE_PANEL_EXPAND_MS);
|
||||
final ValueAnimator animator = new ValueAnimator();
|
||||
animator.setFloatValues(0.0f, 1.0f);
|
||||
animatorSet.play(animator);
|
||||
animatorSet.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an {@link AnimatorSet} to animate the Panel, {@param parentView} in or out of the
|
||||
* screen, based on the positional parameters {@param startY}, {@param endY}, the parameters
|
||||
* for alpha changes {@param startAlpha}, {@param endAlpha}, and the {@param duration} in
|
||||
* milliseconds.
|
||||
*/
|
||||
@NonNull
|
||||
private static AnimatorSet buildAnimatorSet(@NonNull View targetView,
|
||||
float startY, float endY,
|
||||
float startAlpha, float endAlpha, int duration) {
|
||||
final AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.setDuration(duration);
|
||||
animatorSet.setInterpolator(new DecelerateInterpolator());
|
||||
animatorSet.playTogether(
|
||||
ObjectAnimator.ofFloat(targetView, View.TRANSLATION_Y, startY, endY),
|
||||
ObjectAnimator.ofFloat(targetView, View.ALPHA, startAlpha, endAlpha));
|
||||
return animatorSet;
|
||||
}
|
||||
|
||||
private void loadPreferencesFilter() {
|
||||
Intent intent = getActivity().getIntent();
|
||||
mPreferenceFilter = intent != null
|
||||
|
Reference in New Issue
Block a user