Create a collapsing toolbar based activity

On Android S, each of subsetting pages will have a collapsing toolbar to
enlarge its title. However, there are many different pages from
differennt apps. So we extracted a base activity with collapsing toolbar
layout so it is easier to enbale a collapsing toolbar in their own
pages.

Bug: 179380824
Test: visual verified
Change-Id: Ic505d65320081589d1e1b5eb4bd2af7a06e60d39
This commit is contained in:
Mill Chen
2021-02-06 01:03:43 +08:00
parent 2441a6bb3a
commit 2ad0e3dcd8
9 changed files with 365 additions and 0 deletions

View File

@@ -66,6 +66,7 @@ java_defaults {
"SettingsLibBannerMessagePreference",
"SettingsLibFooterPreference",
"SettingsLibUsageProgressBarPreference",
"SettingsLibCollapsingToolbarBaseActivity",
],
}

View File

@@ -0,0 +1,14 @@
android_library {
name: "SettingsLibCollapsingToolbarBaseActivity",
srcs: ["src/**/*.java"],
resource_dirs: ["res"],
static_libs: [
"androidx.annotation_annotation",
"androidx.core_core",
"com.google.android.material_material",
],
sdk_version: "system_current",
min_sdk_version: "21",
}

View File

@@ -0,0 +1,23 @@
<?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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settingslib.collapsingtoolbar">
<uses-sdk android:minSdkVersion="21" />
</manifest>

View File

@@ -0,0 +1,60 @@
<?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.
-->
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/content_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionGroup="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="180dp"
android:theme="@style/Theme.CollapsingToolbar.Settings">
<com.android.settingslib.collapsingtoolbar.AdjustableToolbarLayout
android:id="@+id/collapsing_toolbar"
android:background="?android:attr/colorPrimary"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:maxLines="3"
app:contentScrim="?android:attr/colorPrimary"
app:collapsedTitleTextAppearance="@style/CollapsingToolbarTitle.Collapsed"
app:statusBarScrim="?android:attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:expandedTitleMarginStart="18dp"
app:expandedTitleMarginEnd="18dp"
app:toolbarId="@id/action_bar">
<Toolbar
android:id="@+id/action_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="?android:attr/actionBarTheme"
app:layout_collapseMode="pin"/>
</com.android.settingslib.collapsingtoolbar.AdjustableToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,23 @@
<?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.
-->
<resources>
<style name="Theme.CollapsingToolbar.Settings"
parent="@style/Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@*android:color/primary_dark_device_default_settings</item>
<item name="colorAccent">@*android:color/accent_device_default_dark</item>
</style>
</resources>

View File

@@ -0,0 +1,30 @@
<?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.
-->
<resources>
<style name="CollapsingToolbarTitle.Collapsed"
parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
</style>
<style name="CollapsingToolbarTitle"
parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
<item name="android:textSize">36sp</item>
</style>
<style name="CollapsingToolbarTitle.MoreThanTwoLines">
<item name="android:textSize">24sp</item>
</style>
</resources>

View File

@@ -0,0 +1,23 @@
<?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.
-->
<resources>
<style name="Theme.CollapsingToolbar.Settings"
parent="@style/Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
<item name="colorAccent">@*android:color/accent_device_default_light</item>
</style>
</resources>

View File

@@ -0,0 +1,92 @@
/*
* 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.settingslib.collapsingtoolbar;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* A customized version of CollapsingToolbarLayout that can apply different font size based on
* the line count of its title.
*/
public class AdjustableToolbarLayout extends CollapsingToolbarLayout {
private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
public AdjustableToolbarLayout(@NonNull Context context) {
this(context, null);
}
public AdjustableToolbarLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public AdjustableToolbarLayout(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
initCollapsingToolbar();
}
private void initCollapsingToolbar() {
this.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
v.removeOnLayoutChangeListener(this);
final int count = getLineCount();
if (count > TOOLBAR_MAX_LINE_NUMBER) {
setExpandedTitleTextAppearance(R.style.CollapsingToolbarTitle_MoreThanTwoLines);
} else {
setExpandedTitleTextAppearance(R.style.CollapsingToolbarTitle);
}
}
});
}
/**
* Returns a number of title line count for CollapsingToolbarLayout so that facilitates the
* determination to apply what kind of font size. Since the title of CollapsingToolbarLayout is
* drawn in a canvas and the text process is wrapped in a CollapsingTextHelper, the way we used
* here is to get the line count from the CollapsingTextHelper via Java Reflection.
*/
private int getLineCount() {
try {
final Field textHelperField = this.getClass().getDeclaredField("collapsingTextHelper");
textHelperField.setAccessible(true);
final Object textHelperObj = textHelperField.get(this);
final Field layoutField = textHelperObj.getClass().getDeclaredField("textLayout");
layoutField.setAccessible(true);
final Object layoutObj = layoutField.get(textHelperObj);
final Method method = layoutObj.getClass().getDeclaredMethod("getLineCount");
return (int) method.invoke(layoutObj);
} catch (Exception e) {
return 0;
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* 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.settingslib.collapsingtoolbar;
import android.app.ActionBar;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import com.google.android.material.appbar.CollapsingToolbarLayout;
/**
* A base Activity that has a collapsing toolbar layout is used for the activities intending to
* enable the collapsing toolbar function.
*/
public class CollapsingToolbarBaseActivity extends FragmentActivity {
private CollapsingToolbarLayout mCollapsingToolbarLayout;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.collapsing_toolbar_base_layout);
mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
final Toolbar toolbar = findViewById(R.id.action_bar);
setActionBar(toolbar);
// Enable title and home button by default
final ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayShowTitleEnabled(true);
}
}
@Override
public void setContentView(int layoutResID) {
final ViewGroup parent = findViewById(R.id.content_frame);
if (parent != null) {
parent.removeAllViews();
}
LayoutInflater.from(this).inflate(layoutResID, parent);
}
@Override
public void setContentView(View view) {
((ViewGroup) findViewById(R.id.content_frame)).addView(view);
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
}
@Override
public void setTitle(CharSequence title) {
if (mCollapsingToolbarLayout != null) {
mCollapsingToolbarLayout.setTitle(title);
}
super.setTitle(title);
}
@Override
public void setTitle(int titleId) {
if (mCollapsingToolbarLayout != null) {
mCollapsingToolbarLayout.setTitle(getText(titleId));
}
super.setTitle(titleId);
}
/**
* Returns an instance of collapsing toolbar.
*/
public CollapsingToolbarLayout getCollapsingToolbarLayout() {
return mCollapsingToolbarLayout;
}
}