Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c65d2c3e authored by Jian-Yang Liu's avatar Jian-Yang Liu Committed by Android (Google) Code Review
Browse files

Merge "Updated OverlayPanelViewController to allow for showing overlay panel...

Merge "Updated OverlayPanelViewController to allow for showing overlay panel from the bottom navigation bar." into rvc-dev
parents 8a36b147 2d922fb6
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -72,11 +72,21 @@

    <!-- Car System UI's OverlayViewsMediator-->
    <string-array name="config_carSystemUIOverlayViewsMediators" translatable="false">
        <item>com.android.systemui.car.notification.NotificationPanelViewMediator</item>
        <item>@string/config_notificationPanelViewMediator</item>
        <item>com.android.systemui.car.keyguard.CarKeyguardViewMediator</item>
        <item>com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator</item>
    </string-array>

    <!--
        Car SystemUI's notification mediator. Replace with other notification mediators to have
        the notification panel show from another system bar. The system bar should be enabled to
        use the mediator with that system bar.
        Example: config_enableBottomNavigationBar=true
                 config_notificationPanelViewMediator=
                    com.android.systemui.car.notification.BottomNotificationPanelViewMediator -->
    <string name="config_notificationPanelViewMediator" translatable="false">
        com.android.systemui.car.notification.TopNotificationPanelViewMediator</string>

    <!-- List of package names that are allowed sources of app installation. -->
    <string-array name="config_allowedAppInstallSources" translatable="false">
        <item>com.android.vending</item>
+59 −0
Original line number Diff line number Diff line
/*
 * 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.systemui.car.notification;

import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.car.window.OverlayPanelViewController;
import com.android.systemui.statusbar.policy.ConfigurationController;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Implementation of NotificationPanelViewMediator that sets the notification panel to be opened
 * from the top navigation bar.
 */
@Singleton
public class BottomNotificationPanelViewMediator extends NotificationPanelViewMediator {

    @Inject
    public BottomNotificationPanelViewMediator(
            CarNavigationBarController carNavigationBarController,
            NotificationPanelViewController notificationPanelViewController,

            PowerManagerHelper powerManagerHelper,

            CarDeviceProvisionedController carDeviceProvisionedController,
            ConfigurationController configurationController
    ) {
        super(carNavigationBarController,
                notificationPanelViewController,
                powerManagerHelper,
                carDeviceProvisionedController,
                configurationController);
        notificationPanelViewController.setOverlayDirection(
                OverlayPanelViewController.OVERLAY_FROM_BOTTOM_BAR);
    }

    @Override
    public void registerListeners() {
        super.registerListeners();
        getCarNavigationBarController().registerBottomBarTouchListener(
                getNotificationPanelViewController().getDragOpenTouchListener());
    }
}
+41 −28
Original line number Diff line number Diff line
@@ -83,9 +83,9 @@ public class NotificationPanelViewController extends OverlayPanelViewController
    private NotificationViewController mNotificationViewController;

    private boolean mIsTracking;
    private boolean mNotificationListAtBottom;
    private boolean mNotificationListAtEnd;
    private float mFirstTouchDownOnGlassPane;
    private boolean mNotificationListAtBottomAtTimeOfTouch;
    private boolean mNotificationListAtEndAtTimeOfTouch;
    private boolean mIsSwipingVerticallyToClose;
    private boolean mIsNotificationCardSwiping;

@@ -233,11 +233,11 @@ public class NotificationPanelViewController extends OverlayPanelViewController
        // This allows us to initialize gesture listeners and detect when to close the notifications
        glassPane.setOnTouchListener((v, event) -> {
            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
                mNotificationListAtBottomAtTimeOfTouch = false;
                mNotificationListAtEndAtTimeOfTouch = false;
            }
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                mFirstTouchDownOnGlassPane = event.getRawX();
                mNotificationListAtBottomAtTimeOfTouch = mNotificationListAtBottom;
                mNotificationListAtEndAtTimeOfTouch = mNotificationListAtEnd;
                // Reset the tracker when there is a touch down on the glass pane.
                mIsTracking = false;
                // Pass the down event to gesture detector so that it knows where the touch event
@@ -251,34 +251,34 @@ public class NotificationPanelViewController extends OverlayPanelViewController
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                // Check if we can scroll vertically downwards.
                if (!mNotificationList.canScrollVertically(/* direction= */ 1)) {
                    mNotificationListAtBottom = true;
                // Check if we can scroll vertically in the animation direction.
                if (!mNotificationList.canScrollVertically(mAnimateDirection)) {
                    mNotificationListAtEnd = true;
                    return;
                }
                mNotificationListAtBottom = false;
                mNotificationListAtEnd = false;
                mIsSwipingVerticallyToClose = false;
                mNotificationListAtBottomAtTimeOfTouch = false;
                mNotificationListAtEndAtTimeOfTouch = false;
            }
        });

        mNotificationList.setOnTouchListener((v, event) -> {
            mIsNotificationCardSwiping = Math.abs(mFirstTouchDownOnGlassPane - event.getRawX())
                    > SWIPE_MAX_OFF_PATH;
            if (mNotificationListAtBottomAtTimeOfTouch && mNotificationListAtBottom) {
            if (mNotificationListAtEndAtTimeOfTouch && mNotificationListAtEnd) {
                // We need to save the state here as if notification card is swiping we will
                // change the mNotificationListAtBottomAtTimeOfTouch. This is to protect
                // change the mNotificationListAtEndAtTimeOfTouch. This is to protect
                // closing the notification shade while the notification card is being swiped.
                mIsSwipingVerticallyToClose = true;
            }

            // If the card is swiping we should not allow the notification shade to close.
            // Hence setting mNotificationListAtBottomAtTimeOfTouch to false will stop that
            // Hence setting mNotificationListAtEndAtTimeOfTouch to false will stop that
            // for us. We are also checking for mIsTracking because while swiping the
            // notification shade to close if the user goes a bit horizontal while swiping
            // upwards then also this should close.
            if (mIsNotificationCardSwiping && !mIsTracking) {
                mNotificationListAtBottomAtTimeOfTouch = false;
                mNotificationListAtEndAtTimeOfTouch = false;
            }

            boolean handled = closeGestureDetector.onTouchEvent(event);
@@ -290,7 +290,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController
            }
            if (!handled && event.getActionMasked() == MotionEvent.ACTION_UP
                    && mIsSwipingVerticallyToClose) {
                if (getSettleClosePercentage() < getPercentageFromBottom() && isTracking) {
                if (getSettleClosePercentage() < getPercentageFromEndingEdge() && isTracking) {
                    animatePanel(DEFAULT_FLING_VELOCITY, false);
                } else if (clippedHeight != getLayout().getHeight() && isTracking) {
                    // this can be caused when user is at the end of the list and trying to
@@ -299,11 +299,11 @@ public class NotificationPanelViewController extends OverlayPanelViewController
                }
            }

            // Updating the mNotificationListAtBottomAtTimeOfTouch state has to be done after
            // Updating the mNotificationListAtEndAtTimeOfTouch state has to be done after
            // the event has been passed to the closeGestureDetector above, such that the
            // closeGestureDetector sees the up event before the state has changed.
            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
                mNotificationListAtBottomAtTimeOfTouch = false;
                mNotificationListAtEndAtTimeOfTouch = false;
            }
            return handled || isTracking;
        });
@@ -377,25 +377,31 @@ public class NotificationPanelViewController extends OverlayPanelViewController
    }

    @Override
    protected void onScroll(int height) {
    protected void onScroll(int y) {
        if (mHandleBar != null) {
            ViewGroup.MarginLayoutParams lp =
                    (ViewGroup.MarginLayoutParams) mHandleBar.getLayoutParams();
            mHandleBar.setTranslationY(height - mHandleBar.getHeight() - lp.bottomMargin);
            // Adjust handlebar to new pointer position, and a little more depending on the
            // animate direction so the bar can be seen fully.
            if (mAnimateDirection > 0) {
                mHandleBar.setTranslationY(y - mHandleBar.getHeight() - lp.bottomMargin);
            } else {
                mHandleBar.setTranslationY(y + mHandleBar.getHeight() + lp.topMargin);
            }
        }

        if (mNotificationView.getHeight() > 0) {
            Drawable background = mNotificationView.getBackground().mutate();
            background.setAlpha((int) (getBackgroundAlpha(height) * 255));
            background.setAlpha((int) (getBackgroundAlpha(y) * 255));
            mNotificationView.setBackground(background);
        }
    }

    @Override
    protected boolean shouldAllowClosingScroll() {
        // Unless the notification list is at the bottom, the panel shouldn't be allowed to
        // Unless the notification list is at the end, the panel shouldn't be allowed to
        // collapse on scroll.
        return mNotificationListAtBottomAtTimeOfTouch;
        return mNotificationListAtEndAtTimeOfTouch;
    }

    /**
@@ -403,9 +409,11 @@ public class NotificationPanelViewController extends OverlayPanelViewController
     * shade is visible to the user. When the notification shade is completely open then
     * alpha value will be 1.
     */
    private float getBackgroundAlpha(int height) {
        return mInitialBackgroundAlpha
                + ((float) height / mNotificationView.getHeight() * mBackgroundAlphaDiff);
    private float getBackgroundAlpha(int y) {
        float fractionCovered =
                ((float) (mAnimateDirection > 0 ? y : mNotificationView.getHeight() - y))
                        / mNotificationView.getHeight();
        return mInitialBackgroundAlpha + fractionCovered * mBackgroundAlphaDiff;
    }

    /** Sets the unseen count listener. */
@@ -431,13 +439,18 @@ public class NotificationPanelViewController extends OverlayPanelViewController
        @Override
        public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX,
                float distanceY) {
            calculatePercentageFromBottom(event2.getRawY());
            // To prevent the jump in the clip bounds while closing the notification shade using
            calculatePercentageFromEndingEdge(event2.getRawY());
            // To prevent the jump in the clip bounds while closing the notification panel using
            // the handle bar we should calculate the height using the diff of event1 and event2.
            // This will help the notification shade to clip smoothly as the event2 value changes
            // as event1 value will be fixed.
            int clipHeight = getLayout().getHeight() - (int) (event1.getRawY() - event2.getRawY());
            setViewClipBounds(clipHeight);
            float diff = mAnimateDirection * (event1.getRawY() - event2.getRawY());
            float y = mAnimateDirection > 0
                    ? getLayout().getHeight() - diff
                    : diff;
            // Ensure the position is within the overlay panel.
            y = Math.max(0, Math.min(y, getLayout().getHeight()));
            setViewClipBounds((int) y);
            return true;
        }
    }
+13 −7
Original line number Diff line number Diff line
@@ -19,17 +19,15 @@ package com.android.systemui.car.notification;
import android.car.hardware.power.CarPowerManager;
import android.content.res.Configuration;

import androidx.annotation.CallSuper;

import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.car.window.OverlayViewMediator;
import com.android.systemui.statusbar.policy.ConfigurationController;

import javax.inject.Inject;
import javax.inject.Singleton;

/** The view mediator which attaches the view controller to other elements of the system ui. */
@Singleton
public class NotificationPanelViewMediator implements OverlayViewMediator,
public abstract class NotificationPanelViewMediator implements OverlayViewMediator,
        ConfigurationController.ConfigurationListener {

    private final CarNavigationBarController mCarNavigationBarController;
@@ -38,7 +36,6 @@ public class NotificationPanelViewMediator implements OverlayViewMediator,
    private final CarDeviceProvisionedController mCarDeviceProvisionedController;
    private final ConfigurationController mConfigurationController;

    @Inject
    public NotificationPanelViewMediator(
            CarNavigationBarController carNavigationBarController,
            NotificationPanelViewController notificationPanelViewController,
@@ -56,9 +53,10 @@ public class NotificationPanelViewMediator implements OverlayViewMediator,
    }

    @Override
    @CallSuper
    public void registerListeners() {
        mCarNavigationBarController.registerTopBarTouchListener(
                mNotificationPanelViewController.getDragOpenTouchListener());
                mNotificationPanelViewController.getDragCloseTouchListener());
        mCarNavigationBarController.registerBottomBarTouchListener(
                mNotificationPanelViewController.getDragCloseTouchListener());
        mCarNavigationBarController.registerLeftBarTouchListener(
@@ -128,4 +126,12 @@ public class NotificationPanelViewMediator implements OverlayViewMediator,
        mNotificationPanelViewController.reinflate();
        registerListeners();
    }

    protected final CarNavigationBarController getCarNavigationBarController() {
        return mCarNavigationBarController;
    }

    protected final NotificationPanelViewController getNotificationPanelViewController() {
        return mNotificationPanelViewController;
    }
}
+59 −0
Original line number Diff line number Diff line
/*
 * 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.systemui.car.notification;

import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.car.window.OverlayPanelViewController;
import com.android.systemui.statusbar.policy.ConfigurationController;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Implementation of NotificationPanelViewMediator that sets the notification panel to be opened
 * from the top navigation bar.
 */
@Singleton
public class TopNotificationPanelViewMediator extends NotificationPanelViewMediator {

    @Inject
    public TopNotificationPanelViewMediator(
            CarNavigationBarController carNavigationBarController,
            NotificationPanelViewController notificationPanelViewController,

            PowerManagerHelper powerManagerHelper,

            CarDeviceProvisionedController carDeviceProvisionedController,
            ConfigurationController configurationController
    ) {
        super(carNavigationBarController,
                notificationPanelViewController,
                powerManagerHelper,
                carDeviceProvisionedController,
                configurationController);
        notificationPanelViewController.setOverlayDirection(
                OverlayPanelViewController.OVERLAY_FROM_TOP_BAR);
    }

    @Override
    public void registerListeners() {
        super.registerListeners();
        getCarNavigationBarController().registerBottomBarTouchListener(
                getNotificationPanelViewController().getDragOpenTouchListener());
    }
}
Loading