Skip to content

Commit

Permalink
Automated g4 rollback of changelist 457744460
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 459744654
  • Loading branch information
drchen authored and hunterstich committed Jul 8, 2022
1 parent 2719859 commit 10ac255
Show file tree
Hide file tree
Showing 3 changed files with 293 additions and 0 deletions.
12 changes: 12 additions & 0 deletions lib/java/com/google/android/material/appbar/AppBarLayout.java
Expand Up @@ -677,6 +677,10 @@ public final int getTotalScrollRange() {
int range = 0;
for (int i = 0, z = getChildCount(); i < z; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
// Gone views should not be included in the scroll range calculation.
continue;
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int childHeight = child.getMeasuredHeight();
final int flags = lp.scrollFlags;
Expand Down Expand Up @@ -725,6 +729,10 @@ int getDownNestedPreScrollRange() {
int range = 0;
for (int i = getChildCount() - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
// Gone views should not be included in the scroll range calculation.
continue;
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int childHeight = child.getMeasuredHeight();
final int flags = lp.scrollFlags;
Expand Down Expand Up @@ -768,6 +776,10 @@ int getDownNestedScrollRange() {
int range = 0;
for (int i = 0, z = getChildCount(); i < z; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
// Gone views should not be included in the scroll range calculation.
continue;
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childHeight = child.getMeasuredHeight();
childHeight += lp.topMargin + lp.bottomMargin;
Expand Down
238 changes: 238 additions & 0 deletions lib/javatests/com/google/android/material/appbar/AppBarLayoutTest.java
@@ -0,0 +1,238 @@
/*
* Copyright (C) 2022 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.google.android.material.appbar;

import com.google.android.material.test.R;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.google.common.truth.Truth.assertThat;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import androidx.core.view.ViewCompat;
import com.google.android.material.appbar.AppBarLayout.LayoutParams;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;

@RunWith(RobolectricTestRunner.class)
public class AppBarLayoutTest {

private AppBarLayout appBarLayout;
private View firstScrollableChild;
private View secondScrollableChild;

@Before
public void setUp() {
AppCompatActivity activity = Robolectric.buildActivity(TestActivity.class).setup().get();
appBarLayout =
(AppBarLayout) activity.getLayoutInflater().inflate(R.layout.test_appbarlayout, null);
firstScrollableChild = appBarLayout.findViewById(R.id.firstScrollableChild);
secondScrollableChild = appBarLayout.findViewById(R.id.secondScrollableChild);

activity.setContentView(appBarLayout);

// Wait until the layout is measured.
getInstrumentation().waitForIdleSync();
}

@Test
public void testTotalScrollRange_whenFirstChildScrollableAndVisible_onlyCountFirstChild() {
assertThat(appBarLayout.getTotalScrollRange())
.isEqualTo(getChildScrollRange(firstScrollableChild));
}

@Test
public void testTotalScrollRange_whenFirstChildNotExitUntilCollapsed_countFirstTwoChildren() {
// Total scroll range will include all children until the first exit-until-collapsed child
setExitUntilCollapsed(firstScrollableChild, false);

assertThat(appBarLayout.getTotalScrollRange())
.isEqualTo(
getChildScrollRange(firstScrollableChild) + getChildScrollRange(secondScrollableChild));
}

@Test
public void testTotalScrollRange_whenFirstChildGone_onlyCountSecondChild() {
firstScrollableChild.setVisibility(View.GONE);

assertThat(appBarLayout.getTotalScrollRange())
.isEqualTo(getChildScrollRange(secondScrollableChild));
}

@Test
public void testTotalScrollRange_noVisibleScrollableChild_returnZero() {
firstScrollableChild.setVisibility(View.GONE);
secondScrollableChild.setVisibility(View.GONE);

assertThat(appBarLayout.getTotalScrollRange()).isEqualTo(0);
}

@Test
public void testTotalScrollRange_whenFirstChildNotScrollable_returnZero() {
appBarLayout.removeView(firstScrollableChild);
appBarLayout.removeView(secondScrollableChild);
appBarLayout.addView(firstScrollableChild);

assertThat(appBarLayout.getTotalScrollRange()).isEqualTo(0);
}

@Test
public void testDownNestedPreScrollRange_noEnterAlwaysChild_returnZero() {
assertThat(appBarLayout.getDownNestedPreScrollRange()).isEqualTo(0);
}

@Test
public void testDownNestedPreScrollRange_whenFirstChildEnterAlways_onlyCountFirstChild() {
setEnterAlways(firstScrollableChild, true);

assertThat(appBarLayout.getDownNestedPreScrollRange())
.isEqualTo(getChildDownNestedPreScrollRange(firstScrollableChild));
}

@Test
public void testDownNestedPreScrollRange_whenFirstChildEnterAlwaysButGone_returnZero() {
setEnterAlways(firstScrollableChild, true);
firstScrollableChild.setVisibility(View.GONE);

assertThat(appBarLayout.getDownNestedPreScrollRange()).isEqualTo(0);
}

@Test
public void testDownNestedPreScrollRange_whenFirstChildGone_onlyCountSecondChild() {
setEnterAlways(firstScrollableChild, true);
firstScrollableChild.setVisibility(View.GONE);
setEnterAlways(secondScrollableChild, true);

assertThat(appBarLayout.getDownNestedPreScrollRange())
.isEqualTo(getChildDownNestedPreScrollRange(secondScrollableChild));
}

@Test
public void
testDownNestedPreScrollRange_whenFirstChildEnterAlwaysCollapsed_onlyCountFirstChild() {
setEnterAlways(firstScrollableChild, true);
setEnterAlwaysCollapsed(firstScrollableChild, true);

assertThat(appBarLayout.getDownNestedPreScrollRange())
.isEqualTo(getChildDownNestedPreScrollRange(firstScrollableChild));
}

@Test
public void testDownNestedScrollRange_whenFirstChildScrollableAndVisible_onlyCountFirstChild() {
assertThat(appBarLayout.getDownNestedScrollRange())
.isEqualTo(getChildDownNestedScrollRange(firstScrollableChild));
}

@Test
public void testDownNestedRange_whenFirstChildNotExitUntilCollapsed_countFirstTwoChildren() {
// Down nested scroll range will include all children until the first exit-until-collapsed child
setExitUntilCollapsed(firstScrollableChild, false);

assertThat(appBarLayout.getDownNestedScrollRange())
.isEqualTo(
getChildDownNestedScrollRange(firstScrollableChild)
+ getChildDownNestedScrollRange(secondScrollableChild));
}

@Test
public void testDownNestedScrollRange_whenFirstChildGone_onlyCountSecondChild() {
firstScrollableChild.setVisibility(View.GONE);

assertThat(appBarLayout.getDownNestedScrollRange())
.isEqualTo(getChildDownNestedScrollRange(secondScrollableChild));
}

@Test
public void testDownNestedScrollRange_noVisibleScrollableChild_returnZero() {
firstScrollableChild.setVisibility(View.GONE);
secondScrollableChild.setVisibility(View.GONE);

assertThat(appBarLayout.getDownNestedScrollRange()).isEqualTo(0);
}

@Test
public void testDownNestedScrollRange_whenFirstChildNotScrollable_returnZero() {
appBarLayout.removeView(firstScrollableChild);
appBarLayout.removeView(secondScrollableChild);
appBarLayout.addView(firstScrollableChild);

assertThat(appBarLayout.getDownNestedScrollRange()).isEqualTo(0);
}

private static int getChildScrollRange(View child) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
return getChildFullHeight(child, lp)
- (isExitUntilCollapsed(lp) ? ViewCompat.getMinimumHeight(child) : 0);
}

private static int getChildDownNestedPreScrollRange(View child) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (isEnterAlwaysCollapsed(lp)) {
return ViewCompat.getMinimumHeight(child) + lp.topMargin + lp.bottomMargin;
}
return getChildScrollRange(child);
}

private static int getChildDownNestedScrollRange(View child) {
return getChildScrollRange(child);
}

private static int getChildFullHeight(View child, LayoutParams lp) {
return child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
}

private static void setExitUntilCollapsed(View child, boolean exitUntilCollapsed) {
enableFlag(child, LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED, exitUntilCollapsed);
}

private static void setEnterAlwaysCollapsed(View child, boolean enterAlwaysCollapsed) {
enableFlag(child, LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED, enterAlwaysCollapsed);
}

private static void setEnterAlways(View child, boolean enterAlways) {
enableFlag(child, LayoutParams.SCROLL_FLAG_ENTER_ALWAYS, enterAlways);
}

private static void enableFlag(View child, int flag, boolean enable) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (enable) {
lp.scrollFlags = lp.scrollFlags | flag;
} else {
lp.scrollFlags = lp.scrollFlags & ~flag;
}
}

private static boolean isExitUntilCollapsed(LayoutParams lp) {
return (lp.scrollFlags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) != 0;
}

private static boolean isEnterAlwaysCollapsed(LayoutParams lp) {
return (lp.scrollFlags & LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED) != 0;
}

private static class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setTheme(R.style.Theme_Material3_Light_NoActionBar);
}
}
}
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2022 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.
-->
<com.google.android.material.appbar.AppBarLayout
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="wrap_content">

<View
android:id="@+id/firstScrollableChild"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="15dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed" />

<View
android:id="@+id/secondScrollableChild"
android:layout_width="match_parent"
android:layout_height="100dp"
android:minHeight="50dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed" />

<View
android:id="@+id/fixedChild"
android:layout_width="match_parent"
android:layout_height="150dp" />

</com.google.android.material.appbar.AppBarLayout>

0 comments on commit 10ac255

Please sign in to comment.