Fix a flicker problem on top app bar
The height of top app bar area is dependent on the line count of title. This mechanism is always triggered when entering either subsetting page or rotating the screen, regardless the state of collapsing toolbar. That is saying this mechanism caused a flicker problem or a title in wrong color. The mechanism will be updated to check the state of collapsing toolbar to make sure that it is only triggered if the collapsing toolbar is in expanded state. This changes also added null checker to app bar since there's no AppBarLayout existing in the older version of Android. Fix: 186419089 Fix: 187709056 Fix: 191746368 Test: visual verified 1) Navigate to a subsetting page with multiline title 2) Rotate the screen to landscape mode and collapse the title 3) Rotate the screen to portrait mode and see if the title is in collapsing state Change-Id: Ica868245e0b0a799f76b7f953c606c8e543375f6
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
android:background="?android:attr/colorPrimary"
|
||||
android:theme="@style/Theme.CollapsingToolbar.Settings">
|
||||
|
||||
<com.android.settingslib.collapsingtoolbar.AdjustableToolbarLayout
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@+id/collapsing_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/toolbar_one_line_height"
|
||||
@@ -59,7 +59,7 @@
|
||||
android:transitionName="shared_element_view"
|
||||
app:layout_collapseMode="pin"/>
|
||||
|
||||
</com.android.settingslib.collapsingtoolbar.AdjustableToolbarLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<FrameLayout
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* 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 android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
@SuppressWarnings("RestrictTo")
|
||||
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) {
|
||||
final ViewGroup.LayoutParams lp = getLayoutParams();
|
||||
lp.height = getResources()
|
||||
.getDimensionPixelSize(R.dimen.toolbar_three_lines_height);
|
||||
setScrimVisibleHeightTrigger(
|
||||
getResources().getDimensionPixelSize(
|
||||
R.dimen.scrim_visible_height_trigger_three_lines));
|
||||
setLayoutParams(lp);
|
||||
} else if (count == TOOLBAR_MAX_LINE_NUMBER) {
|
||||
final ViewGroup.LayoutParams lp = getLayoutParams();
|
||||
lp.height = getResources()
|
||||
.getDimensionPixelSize(R.dimen.toolbar_two_lines_height);
|
||||
setScrimVisibleHeightTrigger(
|
||||
getResources().getDimensionPixelSize(
|
||||
R.dimen.scrim_visible_height_trigger_two_lines));
|
||||
setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -35,10 +35,18 @@ import com.google.android.material.resources.TextAppearanceConfig;
|
||||
* 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 SettingsTransitionActivity {
|
||||
public class CollapsingToolbarBaseActivity extends SettingsTransitionActivity implements
|
||||
AppBarLayout.OnOffsetChangedListener {
|
||||
|
||||
private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
|
||||
private static final int FULLY_EXPANDED_OFFSET = 0;
|
||||
private static final String KEY_IS_TOOLBAR_COLLAPSED = "is_toolbar_collapsed";
|
||||
|
||||
@Nullable
|
||||
private CollapsingToolbarLayout mCollapsingToolbarLayout;
|
||||
@Nullable
|
||||
private AppBarLayout mAppBarLayout;
|
||||
private boolean mIsToolbarCollapsed;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -48,6 +56,12 @@ public class CollapsingToolbarBaseActivity extends SettingsTransitionActivity {
|
||||
super.setContentView(R.layout.collapsing_toolbar_base_layout);
|
||||
mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
|
||||
mAppBarLayout = findViewById(R.id.app_bar);
|
||||
mAppBarLayout.addOnOffsetChangedListener(this);
|
||||
if (savedInstanceState != null) {
|
||||
mIsToolbarCollapsed = savedInstanceState.getBoolean(KEY_IS_TOOLBAR_COLLAPSED);
|
||||
}
|
||||
|
||||
initCollapsingToolbar();
|
||||
disableCollapsingToolbarLayoutScrollingBehavior();
|
||||
|
||||
final Toolbar toolbar = findViewById(R.id.action_bar);
|
||||
@@ -107,14 +121,43 @@ public class CollapsingToolbarBaseActivity extends SettingsTransitionActivity {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOffsetChanged(AppBarLayout appBarLayout, int offset) {
|
||||
if (offset == FULLY_EXPANDED_OFFSET) {
|
||||
mIsToolbarCollapsed = false;
|
||||
} else {
|
||||
mIsToolbarCollapsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (isChangingConfigurations()) {
|
||||
outState.putBoolean(KEY_IS_TOOLBAR_COLLAPSED, mIsToolbarCollapsed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of collapsing toolbar.
|
||||
*/
|
||||
@Nullable
|
||||
public CollapsingToolbarLayout getCollapsingToolbarLayout() {
|
||||
return mCollapsingToolbarLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of app bar.
|
||||
*/
|
||||
@Nullable
|
||||
public AppBarLayout getAppBarLayout() {
|
||||
return mAppBarLayout;
|
||||
}
|
||||
|
||||
private void disableCollapsingToolbarLayoutScrollingBehavior() {
|
||||
if (mAppBarLayout == null) {
|
||||
return;
|
||||
}
|
||||
final CoordinatorLayout.LayoutParams params =
|
||||
(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
|
||||
final AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
|
||||
@@ -127,4 +170,39 @@ public class CollapsingToolbarBaseActivity extends SettingsTransitionActivity {
|
||||
});
|
||||
params.setBehavior(behavior);
|
||||
}
|
||||
|
||||
@SuppressWarnings("RestrictTo")
|
||||
private void initCollapsingToolbar() {
|
||||
if (mCollapsingToolbarLayout == null || mAppBarLayout == null) {
|
||||
return;
|
||||
}
|
||||
mCollapsingToolbarLayout.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);
|
||||
if (mIsToolbarCollapsed) {
|
||||
return;
|
||||
}
|
||||
final int count = mCollapsingToolbarLayout.getLineCount();
|
||||
if (count > TOOLBAR_MAX_LINE_NUMBER) {
|
||||
final ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
|
||||
lp.height = getResources()
|
||||
.getDimensionPixelSize(R.dimen.toolbar_three_lines_height);
|
||||
mCollapsingToolbarLayout.setScrimVisibleHeightTrigger(
|
||||
getResources().getDimensionPixelSize(
|
||||
R.dimen.scrim_visible_height_trigger_three_lines));
|
||||
mCollapsingToolbarLayout.setLayoutParams(lp);
|
||||
} else if (count == TOOLBAR_MAX_LINE_NUMBER) {
|
||||
final ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
|
||||
lp.height = getResources()
|
||||
.getDimensionPixelSize(R.dimen.toolbar_two_lines_height);
|
||||
mCollapsingToolbarLayout.setScrimVisibleHeightTrigger(
|
||||
getResources().getDimensionPixelSize(
|
||||
R.dimen.scrim_visible_height_trigger_two_lines));
|
||||
mCollapsingToolbarLayout.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,21 +25,31 @@ import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
|
||||
/**
|
||||
* A base fragment that has a collapsing toolbar layout for enabling the collapsing toolbar design.
|
||||
*/
|
||||
public abstract class CollapsingToolbarBaseFragment extends Fragment {
|
||||
public abstract class CollapsingToolbarBaseFragment extends Fragment implements
|
||||
AppBarLayout.OnOffsetChangedListener {
|
||||
|
||||
private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
|
||||
private static final int FULLY_EXPANDED_OFFSET = 0;
|
||||
private static final String KEY_IS_TOOLBAR_COLLAPSED = "is_toolbar_collapsed";
|
||||
|
||||
@Nullable
|
||||
private CollapsingToolbarLayout mCollapsingToolbarLayout;
|
||||
@Nullable
|
||||
private AppBarLayout mAppBarLayout;
|
||||
@NonNull
|
||||
private Toolbar mToolbar;
|
||||
@NonNull
|
||||
private FrameLayout mContentFrameLayout;
|
||||
private boolean mIsToolbarCollapsed;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -48,6 +58,13 @@ public abstract class CollapsingToolbarBaseFragment extends Fragment {
|
||||
final View view = inflater.inflate(R.layout.collapsing_toolbar_base_layout, container,
|
||||
false);
|
||||
mCollapsingToolbarLayout = view.findViewById(R.id.collapsing_toolbar);
|
||||
mAppBarLayout = view.findViewById(R.id.app_bar);
|
||||
mAppBarLayout.addOnOffsetChangedListener(this);
|
||||
if (savedInstanceState != null) {
|
||||
mIsToolbarCollapsed = savedInstanceState.getBoolean(KEY_IS_TOOLBAR_COLLAPSED);
|
||||
}
|
||||
initCollapsingToolbar();
|
||||
disableCollapsingToolbarLayoutScrollingBehavior();
|
||||
mToolbar = view.findViewById(R.id.action_bar);
|
||||
mContentFrameLayout = view.findViewById(R.id.content_frame);
|
||||
return view;
|
||||
@@ -60,6 +77,31 @@ public abstract class CollapsingToolbarBaseFragment extends Fragment {
|
||||
requireActivity().setActionBar(mToolbar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (getActivity().isChangingConfigurations()) {
|
||||
outState.putBoolean(KEY_IS_TOOLBAR_COLLAPSED, mIsToolbarCollapsed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOffsetChanged(AppBarLayout appBarLayout, int offset) {
|
||||
if (offset == FULLY_EXPANDED_OFFSET) {
|
||||
mIsToolbarCollapsed = false;
|
||||
} else {
|
||||
mIsToolbarCollapsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance of app bar.
|
||||
*/
|
||||
@Nullable
|
||||
public AppBarLayout getAppBarLayout() {
|
||||
return mAppBarLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the collapsing toolbar layout.
|
||||
*/
|
||||
@@ -75,4 +117,56 @@ public abstract class CollapsingToolbarBaseFragment extends Fragment {
|
||||
public FrameLayout getContentFrameLayout() {
|
||||
return mContentFrameLayout;
|
||||
}
|
||||
|
||||
private void disableCollapsingToolbarLayoutScrollingBehavior() {
|
||||
if (mAppBarLayout == null) {
|
||||
return;
|
||||
}
|
||||
final CoordinatorLayout.LayoutParams params =
|
||||
(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
|
||||
final AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
|
||||
behavior.setDragCallback(
|
||||
new AppBarLayout.Behavior.DragCallback() {
|
||||
@Override
|
||||
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
params.setBehavior(behavior);
|
||||
}
|
||||
|
||||
@SuppressWarnings("RestrictTo")
|
||||
private void initCollapsingToolbar() {
|
||||
if (mCollapsingToolbarLayout == null || mAppBarLayout == null) {
|
||||
return;
|
||||
}
|
||||
mCollapsingToolbarLayout.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);
|
||||
if (mIsToolbarCollapsed) {
|
||||
return;
|
||||
}
|
||||
final int count = mCollapsingToolbarLayout.getLineCount();
|
||||
if (count > TOOLBAR_MAX_LINE_NUMBER) {
|
||||
final ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
|
||||
lp.height = getResources()
|
||||
.getDimensionPixelSize(R.dimen.toolbar_three_lines_height);
|
||||
mCollapsingToolbarLayout.setScrimVisibleHeightTrigger(
|
||||
getResources().getDimensionPixelSize(
|
||||
R.dimen.scrim_visible_height_trigger_three_lines));
|
||||
mCollapsingToolbarLayout.setLayoutParams(lp);
|
||||
} else if (count == TOOLBAR_MAX_LINE_NUMBER) {
|
||||
final ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
|
||||
lp.height = getResources()
|
||||
.getDimensionPixelSize(R.dimen.toolbar_two_lines_height);
|
||||
mCollapsingToolbarLayout.setScrimVisibleHeightTrigger(
|
||||
getResources().getDimensionPixelSize(
|
||||
R.dimen.scrim_visible_height_trigger_two_lines));
|
||||
mCollapsingToolbarLayout.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user