Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a31ca7ca authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Add test app for new Inset API's

Bug: 118118435
Change-Id: I53f09522a7859f15364dd2b71fa495256a830235
parent 75d45584
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
// 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.

android_test {
    name: "WindowInsetsTests",
    srcs: ["src/**/*.java"],
    resource_dirs: ["res"],
    certificate: "platform",
    platform_apis: true,
}
+32 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (018C) 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
  -->

<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="@android:style/Theme.Material"
            android:windowSoftInputMode="adjustResize">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
+33 −0
Original line number Diff line number Diff line
<?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
  -->

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:id="@+id/root">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:text="Hello insets" />

</LinearLayout>
+20 −0
Original line number Diff line number Diff line
<?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
  -->

<resources>
    <string name="activity_title">Window Insets Tests</string>
</resources>
+159 −0
Original line number Diff line number Diff line
/*
 * 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.google.android.test.windowinsetstests;

import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.graphics.Insets;
import android.os.Bundle;
import android.util.Property;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowInsets.Type;
import android.view.WindowInsetsAnimationCallback;
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowInsetsAnimationController;

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

public class WindowInsetsActivity extends Activity {

    private View mRoot;
    private View mButton;

    private static class InsetsProperty extends Property<WindowInsetsAnimationController, Insets> {

        private final View mViewToAnimate;
        private final Insets mShowingInsets;

        public InsetsProperty(View viewToAnimate, Insets showingInsets) {
            super(Insets.class, "Insets");
            mViewToAnimate = viewToAnimate;
            mShowingInsets = showingInsets;
        }

        @Override
        public Insets get(WindowInsetsAnimationController object) {
            return object.getCurrentInsets();
        }

        @Override
        public void set(WindowInsetsAnimationController object, Insets value) {
            object.setInsetsAndAlpha(value, 1.0f, 0.5f);
            if (mShowingInsets.bottom != 0) {
                mViewToAnimate.setTranslationY(mShowingInsets.bottom - value.bottom);
            } else if (mShowingInsets.right != 0) {
                mViewToAnimate.setTranslationX(mShowingInsets.right - value.right);
            } else if (mShowingInsets.left != 0) {
                mViewToAnimate.setTranslationX(value.left - mShowingInsets.left);
            }
        }
    };

    float showY;
    float hideY;
    InsetsAnimation imeAnim;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.window_inset_activity);
        mRoot = findViewById(R.id.root);
        mButton = findViewById(R.id.button);
        mButton.setOnClickListener(v -> {
            if (!v.getRootWindowInsets().isVisible(Type.ime())) {
                v.getWindowInsetsController().show(Type.ime());
            } else {
                v.getWindowInsetsController().hide(Type.ime());
            }
        });
        mRoot.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            if (imeAnim == null) {
                return;
            }
            if (mRoot.getRootWindowInsets().isVisible(Type.ime())) {
                showY = mButton.getTop();
            } else {
                hideY = mButton.getTop();
            }
        });
        mRoot.setWindowInsetsAnimationCallback(new WindowInsetsAnimationCallback() {

            @Override
            public void onPrepare(InsetsAnimation animation) {
                if ((animation.getTypeMask() & Type.ime()) != 0) {
                    imeAnim = animation;
                }
                if (mRoot.getRootWindowInsets().isVisible(Type.ime())) {
                    showY = mButton.getTop();
                } else {
                    hideY = mButton.getTop();
                }
            }

            @Override
            public WindowInsets onProgress(WindowInsets insets) {
                mButton.setY(hideY + (showY - hideY) * imeAnim.getInterpolatedFraction());
                return insets;
            }

            @Override
            public AnimationBounds onStart(InsetsAnimation animation,
                    AnimationBounds bounds) {
                return bounds;
            }

            @Override
            public void onFinish(InsetsAnimation animation) {
                imeAnim = null;
            }
        });
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();

        TypeEvaluator<Insets> evaluator = (fraction, startValue, endValue) -> Insets.of(
                (int)(startValue.left + fraction * (endValue.left - startValue.left)),
                (int)(startValue.top + fraction * (endValue.top - startValue.top)),
                (int)(startValue.right + fraction * (endValue.right - startValue.right)),
                (int)(startValue.bottom + fraction * (endValue.bottom - startValue.bottom)));

        WindowInsetsAnimationControlListener listener = new WindowInsetsAnimationControlListener() {
            @Override
            public void onReady(WindowInsetsAnimationController controller, int types) {
                ObjectAnimator animator = ObjectAnimator.ofObject(controller,
                        new InsetsProperty(findViewById(R.id.button),
                                controller.getShownStateInsets()),
                        evaluator, controller.getShownStateInsets(),
                        controller.getHiddenStateInsets());
                animator.setRepeatCount(ValueAnimator.INFINITE);
                animator.setRepeatMode(ValueAnimator.REVERSE);
                animator.start();
            }

            @Override
            public void onCancelled() {

            }
        };
    }
}