多窗口

在android7.0中原生提供了多窗口模式和画中画模式,多窗口模式将屏幕分为上下或左右两块区域分别显示两个应用,画中画模式主要应用在android TV中,类似于windows中的多窗口。

分屏

实现分屏功能只需要在AndroidManifest.xml中为application或特定的activity添加以下属性即可


android:resizeableActivity="true"

画中画

和分屏实现方式相同,只是需要设备支持,目前只是在android TV中有此功能,手机并没有开启该功能,需要进行特殊设置。实现方法也是在AndroidManifest.xml中为application或特定的activity添加以下属性

android:supportsPictureInPicture="true"

demo:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".TestPIPActivity"
            android:supportsPictureInPicture="true"

            ></activity>
        <activity android:name=".MainActivity"
            android:resizeableActivity="true"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
import android.annotation.TargetApi;
import android.app.PictureInPictureParams;
import android.content.res.Configuration;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.Rational;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
// 画中画 test
public class TestPIPActivity extends AppCompatActivity {
    private static final String TAG = "TestPIPActivity";
    private PictureInPictureParams.Builder mPictureInPictureParamsBuilder;

    @TargetApi(Build.VERSION_CODES.O)
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FrameLayout content = new FrameLayout(this);
        setContentView(content,new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        if(Build.VERSION.SDK_INT == Build.VERSION_CODES.O){
            mPictureInPictureParamsBuilder = new PictureInPictureParams.Builder();

            final TextView textView = new TextView(this);
            textView.setText("test PIP");
            textView.setTextSize(20);
            FrameLayout.LayoutParams fl = new FrameLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            fl.gravity = Gravity.CENTER ;
            textView.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {//主要操作
                    Rational aspectRatio = new Rational(10,10);
                    mPictureInPictureParamsBuilder.setAspectRatio(aspectRatio).build();
                    enterPictureInPictureMode(mPictureInPictureParamsBuilder.build());
                }
            });
            content.addView(textView,fl);

        }else{
            TextView descTv = new TextView(this);
            descTv.setText("当前版本不支持...");
            descTv.setTextSize(20);
            FrameLayout.LayoutParams Tvfl = new FrameLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            Tvfl.gravity = Gravity.CENTER ;
            content.addView(descTv,Tvfl);
        }

    }



    @Override
    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
        super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
        Log.d(TAG,String.valueOf(isInPictureInPictureMode));
    }

}

shortcut

android7.1中加入的shortcut类似于iOS的3D touch,只是将iPhone上的重按替换成了长按,长按后会弹出菜单,提供快捷操作,shortcut分为静态配置和动态配置。

静态配置

静态配置一般用于固定的选项,需要在资源文件重定义。在res下建立xml目录并新建shortcuts.xml文件,这里面定义shortcut的显示内容和跳转intent,代码如下

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    <shortcut
        android:shortcutId="static_1"
        android:enabled="true"
        android:icon="@mipmap/ic_launcher"
        android:shortcutShortLabel="@string/static_shortcut_short_name_1"
        android:shortcutLongLabel="@string/static_shortcut_long_name_1" >
        <intent
            android:action="android.intent.action.VIEW"
            android:targetPackage="com.example.myapplication"
            android:targetClass="com.example.myapplication.TestPIPActivity" />
        <categories android:name="android.shortcut.conversation" />
    </shortcut>
</shortcuts>
  • id: shortcut的id,必须惟一,否则后面的会覆盖前面的
  • longLabel: 显示在弹出菜单中的label
  • shortLabel: 通过拖拽显示在桌面上的label
  • icon: 一个选项对应的icon
  • intent: 跳转intent,必须设置,否则会抛出java.lang.NullPointerException: Shortcut Intent must be provided的异常
之后还要在AndroidManifest中的activity中添加meta-data标签,代码如下
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".TestPIPActivity"
            android:supportsPictureInPicture="true"

            ></activity>
        <activity android:name=".MainActivity"
            android:resizeableActivity="true"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data
                android:name="android.app.shortcuts"
                android:resource="@xml/shortcuts"/>
        </activity>
    </application>

</manifest>

这样就可以通过资源文件的配置生成shortcut。需要注意的是,shortcut的数量并不能无限增加,当数量超过4时就会抛出如下异常

动态生成

动态生成shortcut由ShortcutInfo构成,ShortcutInfo有几个主要属性与静态配置相同,下面就通过ShortcutManager动态的生成两个shortcut

    private void initShortcut() {
        ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);

        ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(this, "1")
                .setShortLabel("dynamic short 1")
                .setLongLabel("dynamic long 1")
                .setDisabledMessage("disable")
                .setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher))
                .setIntent(new Intent(Intent.ACTION_VIEW, Uri.EMPTY, this, MainActivity.class))
                .build();

        ShortcutInfo shortcutInfo1 = new ShortcutInfo.Builder(this, "2")
                .setShortLabel("dynamic short 1")
                .setLongLabel("dynamic long 2")
                .setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher))
                .setIntent(new Intent(Intent.ACTION_VIEW, Uri.EMPTY, this, SecondActivity.class))
                .build();

        List<ShortcutInfo> shortcutInfoList = new ArrayList<>();
        shortcutInfoList.add(shortcutInfo);
        shortcutInfoList.add(shortcutInfo1);

        shortcutManager.addDynamicShortcuts(shortcutInfoList);
    }
通过以上两种方法就可以在android7.1中加入快捷菜单,可以让用户在不进入应用时直接进入某个页面,实现类似iPhone中3D touch的效果。使用时也需要注意,添加数量的上限,将重要的快捷入口添加进来!
12-29 22:32