Add support for non-fullscreen preference fragments

Settings wants to use a preference fragment in only
a small region of their screen. Currently, the
PreferenceFragment interfaces with the CarUi toolbar,
which is global across the activity. Add a way to
disable this behavior so it doesn't respond to
the toolbar/base layout.

Fixes: 170755185
Test: atest CarUILibUnitTests
Change-Id: Ic40e04fe16f1d005b4a1326dd4b8e8f49766e153
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml b/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml
index 2482a5b..73041a4 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml
+++ b/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml
@@ -16,13 +16,16 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.car.ui.test">
-    <application android:debuggable="true" android:theme="@style/Theme.CarUi">
+    <application android:debuggable="true" android:theme="@style/Theme.CarUi.NoToolbar">
         <uses-library android:name="android.test.runner" />
         <activity android:name="com.android.car.ui.TestActivity" />
         <activity android:name="com.android.car.ui.recyclerview.CarUiRecyclerViewTestActivity" />
         <activity android:name="com.android.car.ui.FocusAreaTestActivity" />
         <activity android:name="com.android.car.ui.FocusParkingViewTestActivity" />
         <activity android:name="com.android.car.ui.preference.PreferenceTestActivity" />
+        <activity
+            android:name="com.android.car.ui.preference.NonFullscreenPreferenceFragmentTest$MyActivity"
+            android:theme="@style/Theme.CarUi.WithToolbar"/>
         <activity android:name="com.android.car.ui.utils.ViewUtilsTestActivity" />
         <activity
             android:name="com.android.car.ui.toolbar.ToolbarTestActivity"
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/PaddingMatcher.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/PaddingMatcher.java
new file mode 100644
index 0000000..5ab1a86
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/PaddingMatcher.java
@@ -0,0 +1,81 @@
+/*
+ * 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.car.ui.matchers;
+
+import android.view.View;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+
+public class PaddingMatcher extends TypeSafeMatcher<View> {
+
+    public enum Side {
+        TOP,
+        BOTTOM,
+        LEFT,
+        RIGHT,
+        START,
+        END
+    }
+
+    private Side mSide;
+    private int mMin;
+    private int mMax;
+
+    public PaddingMatcher(Side side, int min, int max) {
+        mSide = side;
+        mMin = min;
+        mMax = max;
+    }
+
+    @Override
+    protected boolean matchesSafely(View item) {
+        int padding = 0;
+        switch (mSide) {
+            case TOP:
+                padding = item.getPaddingTop();
+                break;
+            case BOTTOM:
+                padding = item.getPaddingBottom();
+                break;
+            case LEFT:
+                padding = item.getPaddingLeft();
+                break;
+            case RIGHT:
+                padding = item.getPaddingRight();
+                break;
+            case START:
+                padding = item.getPaddingStart();
+                break;
+            case END:
+                padding = item.getPaddingEnd();
+                break;
+        }
+
+        if (mMin >= 0 && padding < mMin) {
+            return false;
+        }
+
+        return mMax < 0 || padding <= mMax;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description
+            .appendText("with " + mSide.toString() + " padding between " + mMin + " and " + mMax);
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/ViewMatchers.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/ViewMatchers.java
index 74ce4fa..cdef653 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/ViewMatchers.java
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/matchers/ViewMatchers.java
@@ -18,6 +18,8 @@
 
 import android.view.View;
 
+import com.android.car.ui.matchers.PaddingMatcher.Side;
+
 import org.hamcrest.Matcher;
 
 public class ViewMatchers {
@@ -32,4 +34,12 @@
     public static Matcher<View> withIndex(Matcher<View> matcher, int index) {
         return new IndexMatcher(matcher, index);
     }
+
+    public static Matcher<View> withPadding(Side side, int exactly) {
+        return new PaddingMatcher(side, exactly, exactly);
+    }
+
+    public static Matcher<View> withPaddingAtLeast(Side side, int min) {
+        return new PaddingMatcher(side, min, -1);
+    }
 }
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/NonFullscreenPreferenceFragmentTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/NonFullscreenPreferenceFragmentTest.java
new file mode 100644
index 0000000..33aaa18
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/NonFullscreenPreferenceFragmentTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.car.ui.preference;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.Espresso.pressBack;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.car.ui.matchers.ViewMatchers.withPadding;
+import static com.android.car.ui.matchers.ViewMatchers.withPaddingAtLeast;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.preference.ListPreference;
+import androidx.preference.MultiSelectListPreference;
+import androidx.preference.PreferenceScreen;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.baselayout.InsetsChangedListener;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.matchers.PaddingMatcher.Side;
+import com.android.car.ui.toolbar.ToolbarController;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+public class NonFullscreenPreferenceFragmentTest {
+
+    private static final String EXTRA_FULLSCREEN = "fullscreen";
+    private static final String TOOLBAR_DEFAULT_TEXT = "Test!";
+    private static final String PREFERENCE_SCREEN_TITLE = "PreferenceScreen Title";
+    private static final String LIST_PREFERENCE_TITLE = "List Preference";
+    private static final String MULTI_SELECT_LIST_PREFERENCE_TITLE = "MultiSelect List Preference";
+    private static final String BACK_CONTENT_DESCRIPTION = "Back";
+    private static final String[] ITEMS = { "Item 1", "Item 2", "Item 3" };
+
+    @Rule
+    public ActivityScenarioRule<PreferenceTestActivity> mActivityRule =
+            new ActivityScenarioRule<>(PreferenceTestActivity.class);
+
+    @Test
+    public void test_fullscreen_changesTitle() {
+        try (ActivityScenario<MyActivity> scenario =
+                     ActivityScenario.launch(MyActivity.newIntent(true))) {
+
+            onView(withText(TOOLBAR_DEFAULT_TEXT)).check(doesNotExist());
+            onView(withText(PREFERENCE_SCREEN_TITLE)).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(
+                    matches(withPaddingAtLeast(Side.TOP, 1)));
+
+            onView(withText(MULTI_SELECT_LIST_PREFERENCE_TITLE)).perform(click());
+            onView(withText(MULTI_SELECT_LIST_PREFERENCE_TITLE)).check(matches(isDisplayed()));
+            onView(withText(ITEMS[0])).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(
+                    matches(withPaddingAtLeast(Side.TOP, 1)));
+            onView(withContentDescription(BACK_CONTENT_DESCRIPTION)).perform(click());
+
+            onView(withText(LIST_PREFERENCE_TITLE)).perform(click());
+            onView(withText(LIST_PREFERENCE_TITLE)).check(matches(isDisplayed()));
+            onView(withText(ITEMS[0])).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(
+                    matches(withPaddingAtLeast(Side.TOP, 1)));
+            onView(withContentDescription(BACK_CONTENT_DESCRIPTION)).perform(click());
+        }
+    }
+
+    @Test
+    public void test_nonFullscreen_doesntChangeTitle() {
+        try (ActivityScenario<MyActivity> scenario =
+                     ActivityScenario.launch(MyActivity.newIntent(false))) {
+
+            onView(withText(TOOLBAR_DEFAULT_TEXT)).check(matches(isDisplayed()));
+            onView(withText(PREFERENCE_SCREEN_TITLE)).check(doesNotExist());
+            onView(isAssignableFrom(RecyclerView.class)).check(matches(withPadding(Side.TOP, 0)));
+
+            onView(withText(MULTI_SELECT_LIST_PREFERENCE_TITLE)).perform(click());
+            onView(withText(MULTI_SELECT_LIST_PREFERENCE_TITLE)).check(doesNotExist());
+            onView(withText(TOOLBAR_DEFAULT_TEXT)).check(matches(isDisplayed()));
+            onView(withText(ITEMS[0])).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(matches(withPadding(Side.TOP, 0)));
+            onView(withContentDescription(BACK_CONTENT_DESCRIPTION)).check(doesNotExist());
+            pressBack();
+
+            onView(withText(LIST_PREFERENCE_TITLE)).perform(click());
+            onView(withText(LIST_PREFERENCE_TITLE)).check(doesNotExist());
+            onView(withText(TOOLBAR_DEFAULT_TEXT)).check(matches(isDisplayed()));
+            onView(withText(ITEMS[0])).check(matches(isDisplayed()));
+            onView(isAssignableFrom(RecyclerView.class)).check(matches(withPadding(Side.TOP, 0)));
+            onView(withContentDescription(BACK_CONTENT_DESCRIPTION)).check(doesNotExist());
+            pressBack();
+        }
+    }
+
+
+    public static class MyActivity extends AppCompatActivity implements InsetsChangedListener {
+
+        private boolean mIsFullScreen = false;
+
+        public static Intent newIntent(boolean isFullScreen) {
+            Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+            Intent intent = new Intent(context, MyActivity.class);
+            intent.putExtra(EXTRA_FULLSCREEN, isFullScreen);
+            return intent;
+        }
+
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            ToolbarController toolbar = CarUi.requireToolbar(this);
+            toolbar.setTitle(TOOLBAR_DEFAULT_TEXT);
+
+            mIsFullScreen = getIntent().getBooleanExtra(EXTRA_FULLSCREEN, true);
+            if (savedInstanceState == null) {
+                getSupportFragmentManager()
+                        .beginTransaction()
+                        .replace(android.R.id.content, new MyPreferenceFragment(mIsFullScreen))
+                        .commitNow();
+            }
+        }
+
+        @Override
+        public void onCarUiInsetsChanged(@NonNull Insets insets) {
+            if (!mIsFullScreen) {
+                requireViewById(android.R.id.content).setPadding(insets.getLeft(), insets.getTop(),
+                        insets.getRight(), insets.getBottom());
+            } else {
+                // No-op marker for the preference fragment to handle it
+            }
+        }
+    }
+
+    public static class MyPreferenceFragment extends PreferenceFragment {
+
+        private final boolean mIsFullScreen;
+
+        public MyPreferenceFragment(boolean isFullScreen) {
+            mIsFullScreen = isFullScreen;
+        }
+
+        @Override
+        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+            PreferenceScreen screen = getPreferenceManager()
+                    .createPreferenceScreen(requireContext());
+
+            ListPreference listPreference = new CarUiListPreference(getContext());
+            listPreference.setTitle(LIST_PREFERENCE_TITLE);
+            listPreference.setKey(LIST_PREFERENCE_TITLE);
+            listPreference.setEntries(ITEMS);
+            listPreference.setEntryValues(new CharSequence[]{"1", "2", "3"});
+
+            MultiSelectListPreference multiSelectListPreference =
+                    new CarUiMultiSelectListPreference(getContext());
+            multiSelectListPreference.setTitle(MULTI_SELECT_LIST_PREFERENCE_TITLE);
+            multiSelectListPreference.setKey(MULTI_SELECT_LIST_PREFERENCE_TITLE);
+            multiSelectListPreference.setEntries(ITEMS);
+            multiSelectListPreference.setEntryValues(new CharSequence[]{"1", "2", "3"});
+
+            screen.addPreference(listPreference);
+            screen.addPreference(multiSelectListPreference);
+
+            screen.setTitle(PREFERENCE_SCREEN_TITLE);
+            setPreferenceScreen(screen);
+        }
+
+        @Override
+        protected boolean isFullScreenFragment() {
+            return mIsFullScreen;
+        }
+    }
+}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/ListPreferenceFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/ListPreferenceFragment.java
index 5a34dcd..2f63fbf 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/ListPreferenceFragment.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/ListPreferenceFragment.java
@@ -51,20 +51,23 @@
  */
 public class ListPreferenceFragment extends Fragment implements InsetsChangedListener {
 
-    private ToolbarController mToolbar;
+    private static final String ARG_FULLSCREEN = "fullscreen";
+
     private ListPreference mPreference;
     private CarUiContentListItem mSelectedItem;
     private int mSelectedIndex = -1;
+    private boolean mFullScreen;
 
     /**
      * Returns a new instance of {@link ListPreferenceFragment} for the {@link ListPreference} with
      * the given {@code key}.
      */
     @NonNull
-    static ListPreferenceFragment newInstance(String key) {
+    static ListPreferenceFragment newInstance(String key, boolean fullScreen) {
         ListPreferenceFragment fragment = new ListPreferenceFragment();
         Bundle b = new Bundle(/* capacity= */ 1);
         b.putString(ARG_KEY, key);
+        b.putBoolean(ARG_FULLSCREEN, fullScreen);
         fragment.setArguments(b);
         return fragment;
     }
@@ -85,29 +88,34 @@
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         final CarUiRecyclerView carUiRecyclerView = CarUiUtils.requireViewByRefId(view, R.id.list);
-        mToolbar = CarUi.getToolbar(getActivity());
+        mFullScreen = requireArguments().getBoolean(ARG_FULLSCREEN, true);
+        ToolbarController toolbar = mFullScreen ? CarUi.getToolbar(getActivity()) : null;
 
         // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
-        if (mToolbar == null) {
-            Toolbar toolbarView = CarUiUtils.requireViewByRefId(view, R.id.toolbar);
-            mToolbar = toolbarView;
+        if (toolbar == null) {
+            Toolbar toolbarView = CarUiUtils.findViewByRefId(view, R.id.toolbar);
+            toolbar = toolbarView;
 
-            carUiRecyclerView.setPadding(0, toolbarView.getHeight(), 0, 0);
-            toolbarView.registerToolbarHeightChangeListener(newHeight -> {
-                if (carUiRecyclerView.getPaddingTop() == newHeight) {
-                    return;
-                }
+            if (toolbarView != null) {
+                carUiRecyclerView.setPadding(0, toolbarView.getHeight(), 0, 0);
+                toolbarView.registerToolbarHeightChangeListener(newHeight -> {
+                    if (carUiRecyclerView.getPaddingTop() == newHeight) {
+                        return;
+                    }
 
-                int oldHeight = carUiRecyclerView.getPaddingTop();
-                carUiRecyclerView.setPadding(0, newHeight, 0, 0);
-                carUiRecyclerView.scrollBy(0, oldHeight - newHeight);
-            });
+                    int oldHeight = carUiRecyclerView.getPaddingTop();
+                    carUiRecyclerView.setPadding(0, newHeight, 0, 0);
+                    carUiRecyclerView.scrollBy(0, oldHeight - newHeight);
+                });
+            }
         }
 
         carUiRecyclerView.setClipToPadding(false);
         mPreference = getListPreference();
-        mToolbar.setTitle(mPreference.getTitle());
-        mToolbar.setState(Toolbar.State.SUBPAGE);
+        if (toolbar != null) {
+            toolbar.setTitle(mPreference.getTitle());
+            toolbar.setState(Toolbar.State.SUBPAGE);
+        }
 
         CharSequence[] entries = mPreference.getEntries();
         CharSequence[] entryValues = mPreference.getEntryValues();
@@ -178,11 +186,7 @@
     }
 
     private ListPreference getListPreference() {
-        if (getArguments() == null) {
-            throw new IllegalStateException("Preference arguments cannot be null");
-        }
-
-        String key = getArguments().getString(ARG_KEY);
+        String key = requireArguments().getString(ARG_KEY);
         DialogPreference.TargetFragment fragment =
                 (DialogPreference.TargetFragment) getTargetFragment();
 
@@ -210,6 +214,9 @@
 
     @Override
     public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        if (!mFullScreen) {
+            return;
+        }
         View view = requireView();
         CarUiUtils.requireViewByRefId(view, R.id.list)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
index 44c5f43..b1b8a28 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/MultiSelectListPreferenceFragment.java
@@ -52,19 +52,23 @@
  */
 public class MultiSelectListPreferenceFragment extends Fragment implements InsetsChangedListener {
 
+    private static final String ARG_FULLSCREEN = "fullscreen";
+
     private CarUiMultiSelectListPreference mPreference;
     private Set<String> mNewValues;
     private ToolbarController mToolbar;
+    private boolean mFullScreen;
 
     /**
      * Returns a new instance of {@link MultiSelectListPreferenceFragment} for the {@link
      * CarUiMultiSelectListPreference} with the given {@code key}.
      */
     @NonNull
-    static MultiSelectListPreferenceFragment newInstance(String key) {
+    static MultiSelectListPreferenceFragment newInstance(String key, boolean fullScreen) {
         MultiSelectListPreferenceFragment fragment = new MultiSelectListPreferenceFragment();
         Bundle b = new Bundle(/* capacity= */ 1);
         b.putString(ARG_KEY, key);
+        b.putBoolean(ARG_FULLSCREEN, fullScreen);
         fragment.setArguments(b);
         return fragment;
     }
@@ -85,30 +89,35 @@
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         final CarUiRecyclerView recyclerView = CarUiUtils.requireViewByRefId(view, R.id.list);
-        mToolbar = CarUi.getToolbar(requireActivity());
+        mFullScreen = requireArguments().getBoolean(ARG_FULLSCREEN, true);
+        mToolbar = mFullScreen ? CarUi.getToolbar(requireActivity()) : null;
 
         // TODO(b/150230923) remove the code for the old toolbar height change when apps are ready
         if (mToolbar == null) {
-            Toolbar toolbarView = CarUiUtils.requireViewByRefId(view, R.id.toolbar);
+            Toolbar toolbarView = CarUiUtils.findViewByRefId(view, R.id.toolbar);
             mToolbar = toolbarView;
 
-            recyclerView.setPadding(0, toolbarView.getHeight(), 0, 0);
-            toolbarView.registerToolbarHeightChangeListener(newHeight -> {
-                if (recyclerView.getPaddingTop() == newHeight) {
-                    return;
-                }
+            if (toolbarView != null) {
+                recyclerView.setPadding(0, toolbarView.getHeight(), 0, 0);
+                toolbarView.registerToolbarHeightChangeListener(newHeight -> {
+                    if (recyclerView.getPaddingTop() == newHeight) {
+                        return;
+                    }
 
-                int oldHeight = recyclerView.getPaddingTop();
-                recyclerView.setPadding(0, newHeight, 0, 0);
-                recyclerView.scrollBy(0, oldHeight - newHeight);
-            });
+                    int oldHeight = recyclerView.getPaddingTop();
+                    recyclerView.setPadding(0, newHeight, 0, 0);
+                    recyclerView.scrollBy(0, oldHeight - newHeight);
+                });
+            }
         }
 
         mPreference = getPreference();
 
         recyclerView.setClipToPadding(false);
-        mToolbar.setTitle(mPreference.getTitle());
-        mToolbar.setState(Toolbar.State.SUBPAGE);
+        if (mToolbar != null) {
+            mToolbar.setTitle(mPreference.getTitle());
+            mToolbar.setState(Toolbar.State.SUBPAGE);
+        }
 
         mNewValues = new HashSet<>(mPreference.getValues());
         CharSequence[] entries = mPreference.getEntries();
@@ -205,6 +214,9 @@
 
     @Override
     public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        if (!mFullScreen) {
+            return;
+        }
         View view = requireView();
         CarUiUtils.requireViewByRefId(view, R.id.list)
                 .setPadding(0, insets.getTop(), 0, insets.getBottom());
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceFragment.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceFragment.java
index ed2c724..3f5b5cb 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceFragment.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/preference/PreferenceFragment.java
@@ -72,15 +72,29 @@
     private static final String DIALOG_FRAGMENT_TAG =
             "com.android.car.ui.PreferenceFragment.DIALOG";
 
+    /**
+     * This method can be overridden to indicate whether or not this fragment covers the
+     * whole screen. When it returns false, the preference fragment will not attempt to change
+     * the CarUi base layout toolbar (but will still have its own toolbar and change it when using
+     * non-baselayout toolbars), and will also not take into account CarUi insets.
+     *
+     * @return Whether to PreferenceFragment takes up the whole app's space. Defaults to true.
+     */
+    protected boolean isFullScreenFragment() {
+        return true;
+    }
+
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
-        ToolbarController baseLayoutToolbar = CarUi.getToolbar(getActivity());
-        if (baseLayoutToolbar != null) {
-            baseLayoutToolbar.setState(Toolbar.State.SUBPAGE);
-            if (getPreferenceScreen() != null) {
-                baseLayoutToolbar.setTitle(getPreferenceScreen().getTitle());
+        if (isFullScreenFragment()) {
+            ToolbarController baseLayoutToolbar = CarUi.getToolbar(getActivity());
+            if (baseLayoutToolbar != null) {
+                baseLayoutToolbar.setState(Toolbar.State.SUBPAGE);
+                if (getPreferenceScreen() != null) {
+                    baseLayoutToolbar.setTitle(getPreferenceScreen().getTitle());
+                }
             }
         }
 
@@ -123,6 +137,10 @@
 
     @Override
     public void onCarUiInsetsChanged(@NonNull Insets insets) {
+        if (!isFullScreenFragment()) {
+            return;
+        }
+
         View view = requireView();
         FocusArea focusArea = CarUiUtils.requireViewByRefId(view, R.id.car_ui_focus_area);
         focusArea.setHighlightPadding(0, insets.getTop(), 0, insets.getBottom());
@@ -160,9 +178,10 @@
         if (preference instanceof EditTextPreference) {
             f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
         } else if (preference instanceof ListPreference) {
-            f = ListPreferenceFragment.newInstance(preference.getKey());
+            f = ListPreferenceFragment.newInstance(preference.getKey(), isFullScreenFragment());
         } else if (preference instanceof MultiSelectListPreference) {
-            f = MultiSelectListPreferenceFragment.newInstance(preference.getKey());
+            f = MultiSelectListPreferenceFragment
+                    .newInstance(preference.getKey(), isFullScreenFragment());
         } else if (preference instanceof CarUiSeekBarDialogPreference) {
             f = SeekbarPreferenceDialogFragment.newInstance(preference.getKey());
         } else {
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/Toolbar.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/Toolbar.java
index cdced83..45e7dce 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/Toolbar.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/Toolbar.java
@@ -42,7 +42,11 @@
  * {@link android.app.Activity#setActionBar(android.widget.Toolbar)} with it)
  *
  * <p>The toolbar supports a navigation button, title, tabs, search, and {@link MenuItem MenuItems}
+ *
+ * @deprecated Instead of creating this class, use Theme.CarUi.WithToolbar, and get access to it
+ *             via {@link com.android.car.ui.core.CarUi#requireToolbar(android.app.Activity)}
  */
+@Deprecated
 public final class Toolbar extends FrameLayout implements ToolbarController {
 
     /** Callback that will be issued whenever the height of toolbar is changed. */