diff options
-rw-r--r-- | tests/WindowInsetsTests/AndroidManifest.xml | 24 | ||||
-rw-r--r-- | tests/WindowInsetsTests/res/layout/chat_activity.xml (renamed from tests/WindowInsetsTests/res/layout/window_inset_activity.xml) | 0 | ||||
-rw-r--r-- | tests/WindowInsetsTests/res/layout/controller_activity.xml | 106 | ||||
-rw-r--r-- | tests/WindowInsetsTests/res/layout/main_activity.xml | 37 | ||||
-rw-r--r-- | tests/WindowInsetsTests/res/values/strings.xml | 11 | ||||
-rw-r--r-- | tests/WindowInsetsTests/res/values/styles.xml | 8 | ||||
-rw-r--r-- | tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ChatActivity.java (renamed from tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java) | 9 | ||||
-rw-r--r-- | tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java | 202 | ||||
-rw-r--r-- | tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java | 36 |
9 files changed, 416 insertions, 17 deletions
diff --git a/tests/WindowInsetsTests/AndroidManifest.xml b/tests/WindowInsetsTests/AndroidManifest.xml index 597805451b95..61dd9d4cd021 100644 --- a/tests/WindowInsetsTests/AndroidManifest.xml +++ b/tests/WindowInsetsTests/AndroidManifest.xml @@ -16,18 +16,24 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.google.android.test.windowinsetstests"> - - <application android:label="@string/activity_title"> - <activity android:name=".WindowInsetsActivity" - android:theme="@style/appTheme" - android:windowSoftInputMode="adjustResize" - android:exported="true"> + package="com.google.android.test.windowinsetstests"> + <application android:label="@string/application_title"> + <activity android:name=".WindowInsetsTestsMainActivity" + android:exported="true"> <intent-filter> - <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.LAUNCHER"/> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + + <activity android:name=".ChatActivity" + android:label="@string/chat_activity_title" + android:theme="@style/chat" + android:windowSoftInputMode="adjustResize" /> + + <activity android:name=".ControllerActivity" + android:label="@string/controller_activity_title" + android:theme="@style/controller" /> </application> </manifest> diff --git a/tests/WindowInsetsTests/res/layout/window_inset_activity.xml b/tests/WindowInsetsTests/res/layout/chat_activity.xml index 1b51c4f83fe0..1b51c4f83fe0 100644 --- a/tests/WindowInsetsTests/res/layout/window_inset_activity.xml +++ b/tests/WindowInsetsTests/res/layout/chat_activity.xml diff --git a/tests/WindowInsetsTests/res/layout/controller_activity.xml b/tests/WindowInsetsTests/res/layout/controller_activity.xml new file mode 100644 index 000000000000..d51a4ddd43e8 --- /dev/null +++ b/tests/WindowInsetsTests/res/layout/controller_activity.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 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. +--> + + +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <Spinner + android:id="@+id/spinnerBehavior" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:layout_marginBottom="20dp" /> + + <ToggleButton + android:id="@+id/toggleButtonStatus" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:checked="true" + android:text="Status Bars Toggle Button" + android:textOff="Status Bars Invisible" + android:textOn="Status Bars Visible" /> + + <SeekBar + android:id="@+id/seekBarStatus" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:layout_marginBottom="20dp" + android:max="10000" + android:progress="10000" /> + + <ToggleButton + android:id="@+id/toggleButtonNavigation" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:checked="true" + android:text="Navigation Bars Toggle Button" + android:textOff="Navigation Bars Invisible" + android:textOn="Navigation Bars Visible" /> + + <SeekBar + android:id="@+id/seekBarNavigation" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:layout_marginBottom="20dp" + android:max="10000" + android:progress="10000" /> + + <ToggleButton + android:id="@+id/toggleButtonIme" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:checked="true" + android:text="IME Toggle Button" + android:textOff="IME Invisible" + android:textOn="IME Visible" /> + + <SeekBar + android:id="@+id/seekBarIme" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:layout_marginBottom="20dp" + android:max="10000" + android:progress="0" /> + + <TextView + android:id="@+id/textViewControllableInsets" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="5dp" /> + + <EditText + android:id="@+id/editText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ems="10" + android:hint="For testing IME..." + android:inputType="text" + android:text="" /> + + </LinearLayout> + +</ScrollView>
\ No newline at end of file diff --git a/tests/WindowInsetsTests/res/layout/main_activity.xml b/tests/WindowInsetsTests/res/layout/main_activity.xml new file mode 100644 index 000000000000..621ed89204d1 --- /dev/null +++ b/tests/WindowInsetsTests/res/layout/main_activity.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <Button + android:id="@+id/chat_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/chat_activity_title" + android:textAllCaps="false"/> + + <Button + android:id="@+id/controller_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/controller_activity_title" + android:textAllCaps="false"/> + +</LinearLayout> diff --git a/tests/WindowInsetsTests/res/values/strings.xml b/tests/WindowInsetsTests/res/values/strings.xml index 2b8e5f3da362..1a236c6f751d 100644 --- a/tests/WindowInsetsTests/res/values/strings.xml +++ b/tests/WindowInsetsTests/res/values/strings.xml @@ -16,5 +16,14 @@ --> <resources> - <string name="activity_title">New Insets Chat</string> + <string name="application_title">Window Insets Tests</string> + <string name="chat_activity_title">New Insets Chat</string> + <string name="controller_activity_title">Window Insets Controller</string> + + <!-- The item positions should match the flag values respectively. --> + <string-array name="behaviors"> + <item>BEHAVIOR_SHOW_BARS_BY_TOUCH</item> + <item>BEHAVIOR_SHOW_BARS_BY_SWIPE</item> + <item>BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE</item> + </string-array> </resources> diff --git a/tests/WindowInsetsTests/res/values/styles.xml b/tests/WindowInsetsTests/res/values/styles.xml index 220671fb8e71..a84ffbed600d 100644 --- a/tests/WindowInsetsTests/res/values/styles.xml +++ b/tests/WindowInsetsTests/res/values/styles.xml @@ -17,7 +17,7 @@ <resources> - <style name="appTheme" parent="@style/Theme.MaterialComponents.Light"> + <style name="chat" parent="@style/Theme.MaterialComponents.Light"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> @@ -63,5 +63,11 @@ <dimen name="bubble_padding">8dp</dimen> <dimen name="bubble_padding_side">16dp</dimen> + <style name="controller" parent="android:Theme.Material"> + <item name="android:colorPrimaryDark">#111111</item> + <item name="android:navigationBarColor">#111111</item> + <item name="android:colorPrimary">#222222</item> + <item name="android:colorAccent">#33ccff</item> + </style> </resources>
\ No newline at end of file diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ChatActivity.java index 498cb7c1c710..ba12acb2c877 100644 --- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java +++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ChatActivity.java @@ -30,7 +30,6 @@ import android.content.Context; import android.graphics.Insets; import android.os.Bundle; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -39,8 +38,6 @@ import android.view.WindowInsetsAnimation; import android.view.WindowInsetsAnimation.Callback; import android.view.WindowInsetsAnimationControlListener; import android.view.WindowInsetsAnimationController; -import android.view.WindowInsetsController; -import android.view.WindowInsetsController.OnControllableInsetsChangedListener; import android.view.animation.LinearInterpolator; import android.widget.LinearLayout; @@ -49,7 +46,7 @@ import java.util.List; import androidx.appcompat.app.AppCompatActivity; -public class WindowInsetsActivity extends AppCompatActivity { +public class ChatActivity extends AppCompatActivity { private View mRoot; @@ -58,7 +55,7 @@ public class WindowInsetsActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.window_inset_activity); + setContentView(R.layout.chat_activity); setSupportActionBar(findViewById(R.id.toolbar)); @@ -71,7 +68,7 @@ public class WindowInsetsActivity extends AppCompatActivity { mRoot.setOnTouchListener(new View.OnTouchListener() { private final ViewConfiguration mViewConfiguration = - ViewConfiguration.get(WindowInsetsActivity.this); + ViewConfiguration.get(ChatActivity.this); WindowInsetsAnimationController mAnimationController; WindowInsetsAnimationControlListener mCurrentRequest; boolean mRequestedController = false; diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java new file mode 100644 index 000000000000..beb4049cb230 --- /dev/null +++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/ControllerActivity.java @@ -0,0 +1,202 @@ +/* + * 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.google.android.test.windowinsetstests; + +import android.app.Activity; +import android.graphics.Insets; +import android.os.Bundle; +import android.view.View; +import android.view.WindowInsets; +import android.view.WindowInsets.Type; +import android.view.WindowInsetsAnimationControlListener; +import android.view.WindowInsetsAnimationController; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.CompoundButton; +import android.widget.SeekBar; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.ToggleButton; + +public class ControllerActivity extends Activity implements View.OnApplyWindowInsetsListener { + + private ToggleButton mToggleStatus; + private SeekBar mSeekStatus; + private ToggleButton mToggleNavigation; + private SeekBar mSeekNavigation; + private ToggleButton mToggleIme; + private SeekBar mSeekIme; + private TextView mTextControllableInsets; + private boolean[] mNotFromUser = {false}; + private WindowInsets mLastInsets; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.controller_activity); + final Spinner spinnerBehavior = findViewById(R.id.spinnerBehavior); + ArrayAdapter<CharSequence> adapterBehavior = ArrayAdapter.createFromResource(this, + R.array.behaviors, android.R.layout.simple_spinner_item); + adapterBehavior.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinnerBehavior.setAdapter(adapterBehavior); + spinnerBehavior.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + parent.getWindowInsetsController().setSystemBarsBehavior(position); + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { } + }); + mToggleStatus = findViewById(R.id.toggleButtonStatus); + mToggleStatus.setTag(mNotFromUser); + mToggleStatus.setOnCheckedChangeListener(new ToggleListener(Type.statusBars())); + mSeekStatus = findViewById(R.id.seekBarStatus); + mSeekStatus.setOnSeekBarChangeListener(new SeekBarListener(Type.statusBars())); + mToggleNavigation = findViewById(R.id.toggleButtonNavigation); + mToggleNavigation.setTag(mNotFromUser); + mToggleNavigation.setOnCheckedChangeListener(new ToggleListener(Type.navigationBars())); + mSeekNavigation = findViewById(R.id.seekBarNavigation); + mSeekNavigation.setOnSeekBarChangeListener(new SeekBarListener(Type.navigationBars())); + mToggleIme = findViewById(R.id.toggleButtonIme); + mToggleIme.setTag(mNotFromUser); + mToggleIme.setOnCheckedChangeListener(new ToggleListener(Type.ime())); + mSeekIme = findViewById(R.id.seekBarIme); + mSeekIme.setOnSeekBarChangeListener(new SeekBarListener(Type.ime())); + mTextControllableInsets = findViewById(R.id.textViewControllableInsets); + final View contentView = findViewById(R.id.content); + contentView.setOnApplyWindowInsetsListener(this); + contentView.getWindowInsetsController().addOnControllableInsetsChangedListener( + (c, types) -> mTextControllableInsets.setText("ControllableInsetsTypes=" + types)); + } + + @Override + public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { + mNotFromUser[0] = true; + updateWidgets(insets, Type.statusBars(), mToggleStatus, mSeekStatus); + updateWidgets(insets, Type.navigationBars(), mToggleNavigation, mSeekNavigation); + updateWidgets(insets, Type.ime(), mToggleIme, mSeekIme); + mLastInsets = insets; + mNotFromUser[0] = false; + + // Prevent triggering system gestures while controlling seek bars. + final Insets gestureInsets = insets.getInsets(Type.systemGestures()); + v.setPadding(gestureInsets.left, 0, gestureInsets.right, 0); + + return v.onApplyWindowInsets(insets); + } + + private void updateWidgets(WindowInsets insets, int types, ToggleButton toggle, SeekBar seek) { + final boolean isVisible = insets.isVisible(types); + final boolean wasVisible = mLastInsets != null ? mLastInsets.isVisible(types) : !isVisible; + if (isVisible != wasVisible) { + toggle.setChecked(isVisible); + if (!seek.isPressed()) { + seek.setProgress(isVisible ? seek.getMax() : seek.getMin(), true /* animate*/); + } + } + + } + + private static class ToggleListener implements CompoundButton.OnCheckedChangeListener { + + private final @Type.InsetsType int mTypes; + + ToggleListener(int types) { + mTypes = types; + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (((boolean[]) buttonView.getTag())[0]) { + // not from user + return; + } + if (isChecked) { + buttonView.getWindowInsetsController().show(mTypes); + } else { + buttonView.getWindowInsetsController().hide(mTypes); + } + } + } + + private static class SeekBarListener implements SeekBar.OnSeekBarChangeListener { + + private final @Type.InsetsType int mTypes; + + private WindowInsetsAnimationController mController; + + SeekBarListener(int types) { + mTypes = types; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (mController != null && fromUser) { + final int min = seekBar.getMin(); + final float fraction = (progress - min) / (float) (seekBar.getMax() - min); + final Insets shownInsets = mController.getShownStateInsets(); + final Insets hiddenInsets = mController.getHiddenStateInsets(); + final Insets currentInsets = Insets.of( + (int) (0.5f + fraction * (shownInsets.left - hiddenInsets.left)), + (int) (0.5f + fraction * (shownInsets.top - hiddenInsets.top)), + (int) (0.5f + fraction * (shownInsets.right - hiddenInsets.right)), + (int) (0.5f + fraction * (shownInsets.bottom - hiddenInsets.bottom))); + mController.setInsetsAndAlpha(currentInsets, 1f /* alpha */, fraction); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + if (mController != null) { + return; + } + seekBar.getWindowInsetsController().controlWindowInsetsAnimation(mTypes, + -1 /* durationMs */, null /* interpolator */, null /* cancellationSignal */, + new WindowInsetsAnimationControlListener() { + @Override + public void onReady(WindowInsetsAnimationController controller, int types) { + mController = controller; + if (!seekBar.isPressed()) { + onStopTrackingTouch(seekBar); + } + } + + @Override + public void onFinished(WindowInsetsAnimationController controller) { + mController = null; + } + + @Override + public void onCancelled(WindowInsetsAnimationController controller) { + mController = null; + } + }); + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + final int min = seekBar.getMin(); + final int max = seekBar.getMax(); + final boolean shown = (seekBar.getProgress() - min) * 2 > max - min; + seekBar.setProgress(shown ? max : min); + if (mController != null) { + mController.finish(shown); + } + } + } +} diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java new file mode 100644 index 000000000000..8b77a78ff51e --- /dev/null +++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsTestsMainActivity.java @@ -0,0 +1,36 @@ +/* + * 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.google.android.test.windowinsetstests; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class WindowInsetsTestsMainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main_activity); + + findViewById(R.id.chat_button).setOnClickListener( + v -> startActivity(new Intent(this, ChatActivity.class))); + + findViewById(R.id.controller_button).setOnClickListener( + v -> startActivity(new Intent(this, ControllerActivity.class))); + } +} |