7

我的活动有一些动画过渡。所以当一个活动开始时,它会出现一些淡入淡出的动画。这是代码:

Intent intent = new Intent(this, NextActivity.class);
startActivity(intent);
overridePendingTransition (android.R.anim.fade_in, android.R.anim.fade_out);

问题是,当“开发人员选项”中的“过渡动画比例”关闭时,这些动画将不会运行。所以我正在寻找一种以编程方式启用此功能的方法,以确保显示我的动画。有没有办法将“过渡动画比例”设置为“动画比例 1x”?

4

2 回答 2

12

经过几天的搜索,我找到了可以启用(或禁用)“过渡动画比例”的代码。

        Settings.Global.putInt(getContentResolver(), Global.TRANSITION_ANIMATION_SCALE, 1);

但是这段代码有一个大问题 如果你问什么问题?我会告诉这行代码需要这个权限:

<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>

授予系统 Apps。所以你的应用必须是系统应用。

这个问题是关于制作系统应用程序的:如何制作我的应用程序系统

更新

正如@TripeHound 所说,我们可以

显示一个对话框,告诉用户如果打开此选项,应用程序看起来会更好(如果他们真的想关闭,可以选择不再显示消息)

如何打开开发者选项设置?

这边走:

startActivityForResult(new Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), 0);
于 2014-11-24T13:29:49.187 回答
0

使用 WRITE_SECURE_SETTINGS 权限非常好,您可以通过 adb 或 root 授予它:

adb shell pm grant APP_PACKAGE_NAME android.permission.WRITE_SECURE_SETTINGS

甚至还有来自 Google 的示例,这里展示了如何使用快速设置切换来调整动画比例,尽管我们今天可以将它作为开发人员选项中的一个内置。

它最重要的功能是:

    static float getAnimatorScale(@NonNull ContentResolver contentResolver) {
        float scale = 1f;
        try {
            scale = Settings.Global.getFloat(contentResolver,
                    Settings.Global.ANIMATOR_DURATION_SCALE);
        } catch (Settings.SettingNotFoundException e) {
            Log.e(TAG, "Could not read Animator Duration Scale setting", e);
        }
        return scale;
    }

    static boolean setAnimatorScale(
            @NonNull Context context,
            @FloatRange(from = 0.0, to = 10.0) float scale) {
        try {
            Settings.Global.putFloat(
                    context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, scale);
            return true;
        } catch (SecurityException se) {
            String message = context.getString(R.string.permission_required_toast);
            Toast.makeText(context.getApplicationContext(), message, Toast.LENGTH_LONG).show();
            Log.d(TAG, message);
            return false;
        }
    }

如果你有root,你也可以试试这个,例如:

adb shell settings put global window_animation_scale 0
adb shell settings put global transition_animation_scale 0
adb shell settings put global animator_duration_scale 0

另一种选择是使用SET_ANIMATION_SCALE权限并通过 adb(或在根设备上)授予它,然后您可以使用动画设置进行播放,如此此处所写。但是,不建议这样做,因为它在框架上使用反射。

获得许可后启用和禁用动画的示例:

class SystemAnimations internal constructor(
        private val context: Context) {
    private var _currentScales: FloatArray? = null
    fun disableAll() {
        val permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION)
        if (permStatus == PackageManager.PERMISSION_GRANTED) {
            setSystemAnimationsScale(false)
        }
    }

    fun enableAll() {
        val permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION)
        if (permStatus == PackageManager.PERMISSION_GRANTED) {
            setSystemAnimationsScale(true)
        }
    }

    private fun setSystemAnimationsScale(enable: Boolean) {
        if (enable && _currentScales == null) return
        try {
            val windowManagerStubClazz = Class.forName("android.view.IWindowManager\$Stub")
            val asInterface = windowManagerStubClazz.getDeclaredMethod("asInterface", IBinder::class.java)
            val serviceManagerClazz = Class.forName("android.os.ServiceManager")
            val getService = serviceManagerClazz.getDeclaredMethod("getService", String::class.java)
            val windowManagerClazz = Class.forName("android.view.IWindowManager")
            val setAnimationScales = windowManagerClazz.getDeclaredMethod("setAnimationScales", FloatArray::class.java)
            val getAnimationScales = windowManagerClazz.getDeclaredMethod("getAnimationScales")
            val windowManagerBinder = getService.invoke(null, "window") as IBinder
            val windowManagerObj = asInterface.invoke(null, windowManagerBinder)
            if (!enable && _currentScales == null)
                _currentScales = getAnimationScales.invoke(windowManagerObj) as FloatArray
            //disable is 0.0f, and default is 1.0f
            val scales = FloatArray(_currentScales!!.size)
            for (i in _currentScales!!.indices)
                scales[i] = if (enable) _currentScales!![i] else 0f
            setAnimationScales.invoke(windowManagerObj, *arrayOf<Any>(scales))
            Log.d("AppLog", "changed animations scale")
        } catch (e: Exception) {
            Log.d("AppLog", "Could not change animation scale to $enable")
        }
    }

    companion object {
        private const val ANIMATION_PERMISSION = "android.permission.SET_ANIMATION_SCALE"
    }

}
于 2020-03-25T21:17:08.270 回答