Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android picture-in-picture scale view

Is there a way to use picture-in-picture feature on an activity that is not a video to show it scaled down ?

I have an activity with a giant progress bar and some text that I would like to display on PiP window while the user did some web browsing.

I already have

android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout"

set for the activity in the manifest.

and to start PiP

@Override
protected void onUserLeaveHint() {


    PictureInPictureParams params = new PictureInPictureParams.Builder()
            .build();
    enterPictureInPictureMode(params);

}

This is what my sample app looks like

enter image description here

I press home and it briefly animates to

enter image description here

and then quickly redraws to become

enter image description here

I am hoping to show PiP as it appears scaled down in picture #2 but after a quick animation it redraws to what it looks like in picture #3.

Is there anyway to achieve a scaled down view?

Please keep in mind this is not a going to be an app store app. It is a very targeted app on a dedicated tablet.

like image 488
Professor Chaos Avatar asked Feb 19 '19 21:02

Professor Chaos


People also ask

How do I fix my android Picture-in-picture?

Step 1: Launch YouTube and tap the profile picture icon. Step 2: Go to Settings > General. Step 3: Verify that Picture-in-picture is disabled. If it's disabled, turn it on.

What is PiP mode in Android?

PiP mode allows users to open multiple applications simultaneously leveraging Android's multi-window APIs. If a user is running an app and presses the home button, the app doesn't fully close and can continue running in PiP mode, hovering on the screen while the user interacts with other applications.


1 Answers

Here is another solution which uses fragments to show a scaled UI. Unlike my previous solution, this solution has the advantage to be able to show a UI which is optimized for the PIP mode. (E.g. some views can be hidden in the PIP mode.)

Following code uses onPictureInPictureModeChanged() to listen for a mode change and changes the UI at the next restart. (Because the toolbar is not needed in PIP mode, it is hidden before the PIP mode is entered.)

public class Activity extends AppCompatActivity {

    private static final String FRAGMENT_TAG_FULL = "fragment_full";
    private static final String FRAGMENT_TAG_PIP = "fragment_pip";

    private MyApplication mApplication;

    private Toolbar mToolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mApplication = (MyApplication) getApplicationContext();

        setContentView(R.layout.activity);

        mToolbar = findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);

        if (!mApplication.inPipMode) {
            showFullFragment();
        } else {
            showPipFragment();
        }
    }

    @Override
    protected void onUserLeaveHint() {
        mToolbar.setVisibility(View.GONE);
        PictureInPictureParams params = new PictureInPictureParams.Builder().build();
        enterPictureInPictureMode(params);
    }

    @Override
    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
        if (isInPictureInPictureMode) {
            mApplication.inPipMode = true;
        } else {
            mApplication.inPipMode = false;
        }
    }

    private void showFullFragment() {
        Fragment fragment = new FragmentFull();
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container_content, fragment, FRAGMENT_TAG_FULL)
                .commit();
        mToolbar.setVisibility(View.VISIBLE);
    }

    private void showPipFragment() {
        Fragment fragment = new FragmentPip();
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container_content, fragment, FRAGMENT_TAG_PIP)
                .commit();
        mToolbar.setVisibility(View.GONE);
    }

}

Because onUserLeaveHint() - which starts the PIP mode - is called after onSaveInstanceState() the current mode can't be stored in a field of the activity class. It must be stored somewhere else where it survives a configuration change. A field in the application class is used here.

public class MyApplication extends Application {

    public boolean inPipMode = false;

}

Fragment layout for full screen mode:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Hello World!"
        android:textSize="36sp" />

    <TextView
        android:id="@+id/text_detail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/text"
        android:layout_centerHorizontal="true"
        android:text="&#x1F642;"
        android:textSize="28sp" />

</RelativeLayout>

Fragment layout for PIP mode:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Hello World!"
        android:textSize="10sp"/>

</RelativeLayout>

Result:

result

like image 139
Matt Ke Avatar answered Sep 29 '22 12:09

Matt Ke