Multi-tasking with Partial Custom Tabs

By default, Custom Tabs launch as a full-window activity. Starting in Chrome 107, you can use partial Custom Tabs to specify a different launch height in portrait mode such that users can multitask by interacting with your app while viewing web content. Users can expand the Custom Tab to full-screen by dragging the toolbar handle up and restore the initial launch height by dragging the handle down.

Screenshot of a bottom sheet Partial Tab
Partial Custom Tab in a bottom sheet.

For large screens or devices in landscape mode, starting with Chrome 120, you can specify, a maximum launch width to show a partial Custom Tab in a side sheet. By setting a break point, you can decide when to launch a partial Custom Tab in a bottom or a side sheet.

Screenshot of a side sheet Partial Tab
Partial Custom Tab in a side sheet.

Prerequisite

To be able to use partial Custom Tabs you needs to:

Combine both approaches if you want a fast startup in case the service connection has not been established yet.

Configuring the bottom sheet

To turn a Custom Tab into a partial Custom Tab, define the initial launch height in pixels by calling the CustomTabBuilder class’s setInitialActivityHeightPx() method. By default, the partial Custom Tab is resizable, but you can pass ACTIVITY\_HEIGHT\_FIXED to disable this behavior:

new CustomTabsBuilder().setInitialActivityHeightPx(
    400,
    ACTIVITY_HEIGHT_FIXED
);

Configuring the side sheet

To configure the side sheet behavior, define the initial launch width in pixels by calling the CustomTabBuilder class’s setInitialActivityWidthPx() method.

By default, the partial Custom Tab is resizable, but you can pass ACTIVITY\_HEIGHT\_FIXED to disable this behavior:

  CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder(session)
        .setInitialActivityHeightPx(400)
        .setInitialActivityWidthPx(400);
        .setActivitySideSheetBreakpointDp(800);

The Custom Tab will behave as a side sheet if the screen's width is bigger than the breakpoint value set by setActivitySideSheetBreakpointDp(). If the screen's width is higher than x, the Custom Tab will behave as a side sheet, otherwise it will behave as a bottom sheet. If no breakpoint is specified, set the browser implementation should set as default value 840dp. If x is set to <600dp the browser implementation should default it to 600dp.

Launch a partial Custom Tab with an existing session

CustomTabsSession customTabsSession;

// ...

CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder(customTabsSession)
   .setInitialActivityHeightPx(500)
    .setInitialActivityWidthPx(400);
    .setActivitySideSheetBreakpointDp(800);
   .setCloseButtonPosition(CustomTabsIntent.CLOSE_BUTTON_POSITION_END)
   // ...
   .build();

customTabsIntent.launchUrl(context, Uri.parse(url))

Launch a partial Custom Tab via startActivityForResult

private ActivityResultLauncher<String> mCustomTabLauncher = registerForActivityResult(new ActivityResultContract<String, Integer>() {
    @Override
    public Integer parseResult(int statusCode, @Nullable Intent intent) {
        return statusCode;
    }

    @NonNull
    @Override
    public Intent createIntent(@NonNull Context context, String url) {
        CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(customTabsSession)
                .setInitialActivityHeightPx(500)
                .setInitialActivityWidthPx(400);
                .setActivitySideSheetBreakpointDp(800);
                .setCloseButtonPosition(CustomTabsIntent.CLOSE_BUTTON_POSITION_END)
                .setToolbarCornerRadiusDp(10);
        Intent customTabsIntent = builder.build().intent;
        customTabsIntent.setData(Uri.parse(url));
        return customTabsIntent;
    }
}, new ActivityResultCallback<Integer>() {
    @Override
    public void onActivityResult(Integer statusCode) {
       // ...
    }
});

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    Button selectButton = findViewById(R.id.select_button);
    selectButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            mCustomTabLauncher.launch(customTabsIntent.intent);
        }
    });
}

Next up: learn how to measure user engagement in your Custom Tabs.