用过 Andriod 版官方 Twitter 的用户可能会发现在打击链接后,打开的是一个不同寻常的界面:
Twitter Web
在使用 Telegram 时也会见到类似的界面:
Telgram Web
今天就来讲一下如何实现上面的几个效果。

在 Android 4.4 和 Chrome 45 以上的版本,可以使用 「Chrome Custom Tabs」 特性来实现以上的效果,将 Chrome Tab 作为应用的一部分来使用,并能非常好的展示网页内容,另外 Chrome 还提供了多个定制选项。

首先,需要引入 customtabs 包。打开 build.gradle ,添加依赖:

1
2
3
4
dependencies {
...
compile 'com.android.support:customtabs:23.4.0'
}

添加依赖后,可以进行 UI 定制、网页加载优化等操作。

使用 Chrome Custom Tab 打开网页

1
2
3
4
5
6
7
8
// Use a CustomTabsIntent.Builder to configure CustomTabsIntent.
// Once ready, call CustomTabsIntent.Builder.build() to create a CustomTabsIntent
// and launch the desired Url with CustomTabsIntent.launchUrl()

String url = ¨http://www.zuoyanyouwu.com/¨;
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(this, Uri.parse(url));

自定义地址栏颜色

为了和应用保持统一,Chrome 提供了自定义地址栏颜色的接口:

1
2
3
4
// Changes the background color for the omnibox. colorInt is an int
// that specifies a Color.

builder.setToolbarColor(colorInt);

自定义 Action Button

可以在 Chrome Tab 中自定义 Action Button, 如「分享」操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Adds an Action Button to the Toolbar.
// 'icon' is a Bitmap to be used as the image source for the
// action button.

// 'description' is a String be used as an accessible description for the button.

// 'pendingIntent is a PendingIntent to launch when the action button
// or menu item was tapped. Chrome will be calling PendingIntent#send() on
// taps after adding the url as data. The client app can call
// Intent#getDataString() to get the url.

// 'tint' is a boolean that defines if the Action Button should be tinted.

builder.setActionButton(icon, description, pendingIntent, tint);

自定义 menu

Chrome Tabs 也提供了自定义 menu 的功能,默认情况下, Chrome Tabs 提供了横向的三个图标:「前进」、「网页信息」、「刷新」,以及下面的「在网页中查找」、「在 Chrome 中打开」等五个操作,开发者可以在三个图标下方添加最多五个菜单:

1
builder.addMenuItem(menuItemTitle, menuItemPendingIntent);

自定义打开和关闭动画

为了使应用的动画保持统一,Chrome Tabs 同样提供了自定义动画的接口:

1
2
builder.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left);
builder.setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right);

加载优化

默认情况下,可以直接使用 CustomTabsIntent#launchUrl 方法直接打开网页,但是可能会因为冷启动的原因浪费一些启动时间,所以 Chrome 提供了后台热启动 Chrome,需要加载网页时即可直接打开网页,提升用户体验。
Chrome 热启动的流程:

  • 使用 CustomTabsClient#bindCustomTabsService 连接至 Chrome Service
  • 与 Service 建立后,调用 CustomTabsClient#warmup 在后台启动 Chrome
  • 调用 CustomTabsClient#newSession 新建一个 session,之后的请求都会在这个 session 中进行,可以在 CustomTabsClient#newSession 方法中传递 CustomTabsCallback 参数,以便获取页面的加载回调
  • 调用 CustomTabsSession#mayLaunchUrl 告知 Chrome 将要加载的网页
  • 将 session 作为参数传给 CustomTabsIntent.Builder

自定义 Action Button Icon

开发者可以根据设计,自定义 Action Button 的图标,如分享等:

1
2
3
4
5
6
7
8
9
10
11
12
String shareLabel = getString(R.string.label_action_share);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
android.R.drawable.ic_menu_share);

//Create a PendingIntent to your BroadCastReceiver implementation
Intent actionIntent = new Intent(
this.getApplicationContext(), ShareBroadcastReceiver.class);
PendingIntent pendingIntent =
PendingIntent.getBroadcast(getApplicationContext(), 0, actionIntent, 0);

//Set the pendingIntent as the action to be performed when the button is clicked.
intentBuilder.setActionButton(icon, shareLabel, pendingIntent);

自定义关闭按钮

1
2
3
4
//Setting a custom back button
CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();
intentBuilder.setCloseButtonIcon(BitmapFactory.decodeResource(
getResources(), R.drawable.ic_arrow_back));

通过以上方式,就可以实现 Twitter 和 Telegram 上的效果。

参考:Chrome Custom Tabs