Modify Settings homepage layout

- Add BottomNavigationView which has two tabs
- Remove BottomSheet in layout files

Change-Id: I493290fa9dee0566c73c5c9d7fbba10b71b4e2b4
Fixes: 113266753
Test: visual
This commit is contained in:
Raff Tsai
2018-08-28 22:02:29 +08:00
parent 7f050853c1
commit 43a7b18f21
14 changed files with 295 additions and 320 deletions

View File

@@ -29,22 +29,6 @@
column="9"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" app:barPredictionColor=&quot;@color/material_empty_color_light&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/layout/battery_history_chart.xml"
line="38"
column="9"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2425,7 +2409,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rXC/strings.xml"
line="2559"
line="2524"
column="168"/>
</issue>
@@ -2441,7 +2425,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rAU/strings.xml"
line="2560"
line="2525"
column="64"/>
</issue>
@@ -2457,7 +2441,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rCA/strings.xml"
line="2560"
line="2525"
column="64"/>
</issue>
@@ -2473,7 +2457,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rGB/strings.xml"
line="2560"
line="2525"
column="64"/>
</issue>
@@ -2489,7 +2473,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-en-rIN/strings.xml"
line="2560"
line="2525"
column="64"/>
</issue>
@@ -2505,7 +2489,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/strings.xml"
line="5898"
line="5865"
column="36"/>
</issue>
@@ -2701,6 +2685,22 @@
column="49"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item name=&quot;android:navigationBarDividerColor&quot;>#1f000000&lt;/item>"
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="175"
column="56"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_checked="true"
android:color="?android:attr/colorAccent" />
<item
android:state_checked="false"
android:color="?android:attr/textColorPrimary" />
</selector>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:attr/colorAccent"
android:pathData="M4,13L4,13c0.55,0 1,-0.45 1,-1v0c0,-0.55 -0.45,-1 -1,-1h0c-0.55,0 -1,0.45 -1,1v0C3,12.55 3.45,13 4,13zM4,17L4,17c0.55,0 1,-0.45 1,-1v0c0,-0.55 -0.45,-1 -1,-1h0c-0.55,0 -1,0.45 -1,1v0C3,16.55 3.45,17 4,17zM4,9L4,9c0.55,0 1,-0.45 1,-1v0c0,-0.55 -0.45,-1 -1,-1h0C3.45,7 3,7.45 3,8v0C3,8.55 3.45,9 4,9zM7,13h14v-2H7V13zM7,17h14v-2H7V17zM7,7v2h14V7H7z"/>
</vector>

View File

@@ -0,0 +1,26 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M3,12L3,3h9,9v9,9L12,21 3,21ZM19,12L19,5L12,5 5,5v7,7h7,7zM7,16c0,-0.55 0.45,-1 1,-1 0.55,0 1,0.45 1,1 0,0.55 -0.45,1 -1,1 -0.55,0 -1,-0.45 -1,-1zM11,16c0,-0.55 1.35,-1 3,-1 1.65,0 3,0.45 3,1 0,0.55 -1.35,1 -3,1 -1.65,0 -3,-0.45 -3,-1zM7,12c0,-0.55 0.45,-1 1,-1 0.55,0 1,0.45 1,1 0,0.55 -0.45,1 -1,1 -0.55,0 -1,-0.45 -1,-1zM11,12c0,-0.55 1.35,-1 3,-1 1.65,0 3,0.45 3,1 0,0.55 -1.35,1 -3,1 -1.65,0 -3,-0.45 -3,-1zM7,8C7,7.45 7.45,7 8,7 8.55,7 9,7.45 9,8 9,8.55 8.55,9 8,9 7.45,9 7,8.55 7,8ZM11,8c0,-0.55 1.35,-1 3,-1 1.65,0 3,0.45 3,1 0,0.55 -1.35,1 -3,1 -1.65,0 -3,-0.45 -3,-1z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,28 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M13.85,22.24h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.52c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.89 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73C7.91,5.2 8.17,5.05 8.43,4.91L8.7,3.01c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.7 14.59,22.24 13.85,22.24zM13.32,20.72c0,0.01 0,0.01 0,0.02V20.72zM10.68,20.69v0.02C10.69,20.72 10.69,20.7 10.68,20.69zM10.62,20.24h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96L15.6,7.28c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.69 8.84,6.94 8.38,7.3L7.93,7.62L5.55,6.67L4.16,9.06l2.03,1.58L6.12,11.2c-0.03,0.26 -0.06,0.53 -0.06,0.79s0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.24zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.7l0.01,0.02C5.78,17.72 5.77,17.7 5.77,17.7zM3.93,9.47L3.93,9.47L3.93,9.47zM18.22,6.26c0,0.01 0.01,0.02 0.01,0.02L18.22,6.26zM5.79,6.24L5.78,6.26C5.78,6.26 5.79,6.26 5.79,6.24zM13.31,3.27c0,0.01 0,0.01 0,0.02V3.27zM10.69,3.25v0.02C10.69,3.26 10.69,3.26 10.69,3.25z"/>
<path
android:fillColor="#FF000000"
android:pathData="M13.56,10.44l-1.56,-3.44l-1.56,3.44l-3.44,1.56l3.44,1.56l1.56,3.44l1.56,-3.44l3.44,-1.56z"/>
</vector>

View File

@@ -15,62 +15,8 @@
limitations under the License.
-->
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:minHeight="@dimen/homepage_bottomsheet_height"
app:layout_behavior="@string/bottom_sheet_behavior"
app:behavior_peekHeight="@dimen/homepage_bottomsheet_height">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/bottom_area"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/search_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_search_floating_24dp"
app:backgroundTint="@android:color/white"
app:layout_anchor="@id/bar"/>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bar"
android:layout_width="match_parent"
android:layout_height="@dimen/homepage_bottombar_height"
android:layout_alignParentTop="true"
android:layout_marginTop="@dimen/homepage_bottombar_top_margin"
android:clickable="true"
app:fabAttached="true"
app:fabAlignmentMode="end"
app:fabCradleDiameter="@dimen/homepage_bottombar_fab_cradle"
app:navigationIcon="@drawable/ic_list_24dp"
style="@style/Widget.MaterialComponents.BottomAppBar"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<include layout="@layout/search_bar"
android:visibility="invisible"/>
<FrameLayout
android:id="@+id/bottom_sheet_fragment"
android:layout_below="@id/bottom_area"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -15,8 +15,38 @@
limitations under the License.
-->
<FrameLayout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:background="?android:attr/windowBackground"
android:layout_alignParentBottom="true"
app:itemIconTint="@color/bottom_navigation_colors"
app:itemTextColor="@color/bottom_navigation_colors"
app:menu="@menu/home_bottom_navigation" />
<FrameLayout
android:id="@id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
android:layout_above="@+id/bottom_nav" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/search_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_search_24dp"
android:layout_margin="24dp"
android:layout_above="@id/bottom_nav"
android:layout_alignParentRight="true"
app:backgroundTint="?android:attr/colorAccent"
app:tint="@android:color/white" />
</RelativeLayout>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/homepage_personal_settings"
android:icon="@drawable/ic_settings_personal"
android:title="@string/homepage_personal_settings" />
<item
android:id="@+id/homepage_all_settings"
android:icon="@drawable/ic_settings_all"
android:title="@string/homepage_all_settings" />
</menu>

View File

@@ -10078,4 +10078,10 @@
<!-- UI debug setting: Enable High Refresh Rate virtual panel [CHAR LIMIT=50] -->
<string name="high_frequency_display_device_summary">Enable Virtual High Frequency Panel</string>
<!-- Homepage bottom menu. Title for display all Settings [CHAR LIMIT=30] -->
<string name="homepage_all_settings">All Settings</string>
<!-- Homepage bottom menu. Title for display personalized Settings [CHAR LIMIT=30] -->
<string name="homepage_personal_settings">Your Settings</string>
</resources>

View File

@@ -167,6 +167,7 @@
<style name="Theme.Settings.Home" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Color names copied from frameworks/base/core/res/res/values/themes_device_defaults.xml -->
<!-- TODO (b/113964702) : fix theme color -->
<item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
<item name="colorPrimaryDark">@*android:color/primary_dark_device_default_settings_light</item>
<item name="colorAccent">@*android:color/accent_device_default_light</item>

View File

@@ -22,15 +22,24 @@ import android.os.Bundle;
import android.util.FeatureFlagUtils;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.android.settings.core.FeatureFlags;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.homepage.HomepageFragment;
import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.homepage.PersonalSettingsFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.SearchFeatureProvider;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class SettingsHomepageActivity extends SettingsBaseActivity {
private static final String ALL_SETTINGS_TAG = "all_settings";
private static final String PERSONAL_SETTINGS_TAG = "personal_settings";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -42,24 +51,52 @@ public class SettingsHomepageActivity extends SettingsBaseActivity {
finish();
return;
}
setContentView(R.layout.settings_homepage_container);
if (savedInstanceState == null) {
switchToFragment(this, R.id.main_content, HomepageFragment.class.getName());
final FloatingActionButton searchButton = findViewById(R.id.search_fab);
FeatureFactory.getFactory(this).getSearchFeatureProvider()
.initSearchToolbar(this, searchButton);
final BottomNavigationView navigation = (BottomNavigationView) findViewById(
R.id.bottom_nav);
navigation.setOnNavigationItemSelectedListener(item -> {
switch (item.getItemId()) {
case R.id.homepage_personal_settings:
switchFragment(PersonalSettingsFragment.class.getName(), PERSONAL_SETTINGS_TAG,
ALL_SETTINGS_TAG);
return true;
case R.id.homepage_all_settings:
switchFragment(DashboardSummary.class.getName(), ALL_SETTINGS_TAG,
PERSONAL_SETTINGS_TAG);
return true;
}
return false;
});
}
public static boolean isDynamicHomepageEnabled(Context context) {
return FeatureFlagUtils.isEnabled(context, FeatureFlags.DYNAMIC_HOMEPAGE);
}
/**
* Switch to a specific Fragment
*/
public static void switchToFragment(FragmentActivity activity, int id, String fragmentName) {
final Fragment f = Fragment.instantiate(activity, fragmentName, null /* args */);
private void switchFragment(String fragmentName, String showFragmentTag,
String hideFragmentTag) {
final FragmentManager fragmentManager = getSupportFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FragmentManager manager = activity.getSupportFragmentManager();
manager.beginTransaction().replace(id, f).commitAllowingStateLoss();
manager.executePendingTransactions();
final Fragment hideFragment = fragmentManager.findFragmentByTag(hideFragmentTag);
if (hideFragment != null) {
fragmentTransaction.hide(hideFragment);
}
Fragment showFragment = fragmentManager.findFragmentByTag(showFragmentTag);
if (showFragment == null) {
showFragment = Fragment.instantiate(this, fragmentName, null /* args */);
fragmentTransaction.add(R.id.main_content, showFragment, showFragmentTag);
} else {
fragmentTransaction.show(showFragment);
}
fragmentTransaction.commit();
}
}

View File

@@ -1,196 +0,0 @@
/*
* Copyright (C) 2018 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.homepage;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsHomepageActivity;
import com.android.settings.Utils;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.SearchFeatureProvider;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class HomepageFragment extends InstrumentedFragment {
private static final String TAG = "HomepageFragment";
private static final String SAVE_BOTTOMBAR_STATE = "bottombar_state";
private static final String SAVE_BOTTOM_FRAGMENT_LOADED = "bottom_fragment_loaded";
private RecyclerView mCardsContainer;
private HomepageAdapter mHomepageAdapter;
private LinearLayoutManager mLayoutManager;
private FloatingActionButton mSearchButton;
private BottomSheetBehavior mBottomSheetBehavior;
private View mBottomBar;
private View mSearchBar;
private boolean mBottomFragmentLoaded;
private HomepageManager mHomepageManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHomepageManager = new HomepageManager(getContext(), getSettingsLifecycle());
mHomepageManager.startCardContentLoading();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.settings_homepage,
container, false);
mCardsContainer = (RecyclerView) rootView.findViewById(R.id.card_container);
//TODO(b/111822407): May have to swap to GridLayoutManager
mLayoutManager = new LinearLayoutManager(getActivity());
mCardsContainer.setLayoutManager(mLayoutManager);
mHomepageAdapter = new HomepageAdapter(getContext(), mHomepageManager);
mCardsContainer.setAdapter(mHomepageAdapter);
mHomepageManager.setListener(mHomepageAdapter);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setupBottomBar();
setupSearchBar();
if (savedInstanceState != null) {
final int bottombarState = savedInstanceState.getInt(SAVE_BOTTOMBAR_STATE);
mBottomFragmentLoaded = savedInstanceState.getBoolean(SAVE_BOTTOM_FRAGMENT_LOADED);
mBottomSheetBehavior.setState(bottombarState);
setBarState(bottombarState);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mBottomSheetBehavior != null) {
outState.putInt(SAVE_BOTTOMBAR_STATE, mBottomSheetBehavior.getState());
outState.putBoolean(SAVE_BOTTOM_FRAGMENT_LOADED, mBottomFragmentLoaded);
}
}
@Override
public int getMetricsCategory() {
return MetricsEvent.SETTINGS_HOMEPAGE;
}
private void setupBottomBar() {
final Activity activity = getActivity();
mSearchButton = activity.findViewById(R.id.search_fab);
mSearchButton.setOnClickListener(v -> {
final Intent intent = SearchFeatureProvider.SEARCH_UI_INTENT;
intent.setPackage(FeatureFactory.getFactory(activity)
.getSearchFeatureProvider().getSettingsIntelligencePkgName());
startActivityForResult(intent, 0 /* requestCode */);
});
mBottomSheetBehavior = BottomSheetBehavior.from(activity.findViewById(R.id.bottom_sheet));
mSearchBar = activity.findViewById(R.id.search_bar_container);
mBottomBar = activity.findViewById(R.id.bar);
mBottomBar.setOnClickListener(v -> {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
});
final int screenWidthpx = getResources().getDisplayMetrics().widthPixels;
final Toolbar searchActionBar = activity.findViewById(R.id.search_action_bar);
searchActionBar.setNavigationIcon(R.drawable.ic_search_floating_24dp);
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (!mBottomFragmentLoaded) {
// TODO(b/110405144): Switch to {@link TopLevelSettings} when it's ready.
SettingsHomepageActivity.switchToFragment(getActivity(),
R.id.bottom_sheet_fragment, DashboardSummary.class.getName());
mBottomFragmentLoaded = true;
}
setBarState(newState);
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
mBottomBar.setAlpha(1 - slideOffset);
mSearchButton.setAlpha(1 - slideOffset);
mSearchBar.setAlpha(slideOffset);
mSearchBar.setPadding((int) (screenWidthpx * (1 - slideOffset)), 0, 0, 0);
}
});
}
private void setBarState(int bottomSheetState) {
if (bottomSheetState == BottomSheetBehavior.STATE_EXPANDED) {
mBottomBar.setVisibility(View.INVISIBLE);
mSearchBar.setVisibility(View.VISIBLE);
mSearchButton.setVisibility(View.GONE);
} else if (bottomSheetState == BottomSheetBehavior.STATE_COLLAPSED) {
mBottomBar.setVisibility(View.VISIBLE);
mSearchBar.setVisibility(View.INVISIBLE);
mSearchButton.setVisibility(View.VISIBLE);
} else if (bottomSheetState == BottomSheetBehavior.STATE_SETTLING) {
mBottomBar.setVisibility(View.VISIBLE);
mSearchBar.setVisibility(View.VISIBLE);
mSearchButton.setVisibility(View.VISIBLE);
}
}
//TODO(110767984), copied from settingsActivity. We have to merge them
private void setupSearchBar() {
final Activity activity = getActivity();
final Toolbar toolbar = activity.findViewById(R.id.search_action_bar);
FeatureFactory.getFactory(activity).getSearchFeatureProvider()
.initSearchToolbar(activity, toolbar);
activity.setActionBar(toolbar);
// Please forgive me for what I am about to do.
//
// Need to make the navigation icon non-clickable so that the entire card is clickable
// and goes to the search UI. Also set the background to null so there's no ripple.
final View navView = toolbar.getNavigationView();
navView.setClickable(false);
navView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
navView.setBackground(null);
final ActionBar actionBar = activity.getActionBar();
if (actionBar != null) {
boolean deviceProvisioned = Utils.isDeviceProvisioned(activity);
actionBar.setDisplayHomeAsUpEnabled(deviceProvisioned);
actionBar.setHomeButtonEnabled(deviceProvisioned);
actionBar.setDisplayShowTitleEnabled(false);
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2018 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.homepage;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
public class PersonalSettingsFragment extends InstrumentedFragment {
private static final String TAG = "PersonalSettingsFragment";
private RecyclerView mCardsContainer;
//TODO(b/113966426): rename
private HomepageAdapter mHomepageAdapter;
private LinearLayoutManager mLayoutManager;
//TODO(b/113966426): rename
private HomepageManager mHomepageManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHomepageManager = new HomepageManager(getContext(), getSettingsLifecycle());
mHomepageManager.startCardContentLoading();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.settings_homepage,
container, false);
mCardsContainer = (RecyclerView) rootView.findViewById(R.id.card_container);
//TODO(b/111822407): May have to swap to GridLayoutManager
mLayoutManager = new LinearLayoutManager(getActivity());
mCardsContainer.setLayoutManager(mLayoutManager);
mHomepageAdapter = new HomepageAdapter(getContext(), mHomepageManager);
mCardsContainer.setAdapter(mHomepageAdapter);
mHomepageManager.setListener(mHomepageAdapter);
return rootView;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.SETTINGS_HOMEPAGE;
}
}

View File

@@ -21,7 +21,7 @@ import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.widget.Toolbar;
import android.view.View;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.search.SearchIndexableResources;
@@ -55,11 +55,11 @@ public interface SearchFeatureProvider {
/**
* Initializes the search toolbar.
*/
default void initSearchToolbar(Activity activity, Toolbar toolbar) {
if (activity == null || toolbar == null) {
default void initSearchToolbar(Activity activity, View view) {
if (activity == null || view == null) {
return;
}
toolbar.setOnClickListener(tb -> {
view.setOnClickListener(tb -> {
final Intent intent = SEARCH_UI_INTENT;
intent.setPackage(getSettingsIntelligencePkgName());