如何以编程方式在“开发人员选项”中启用“过渡动画比例”?

时间:2014-11-19 07:23:55

标签: android animation transitions pending-transition

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

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

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

2 个答案:

答案 0 :(得分:8)

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

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

但此代码存在严重问题 如果你问这个问题是什么?我会告诉这行代码需要此权限:

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

仅授予系统应用。因此,您的应用必须是系统应用。

这个问题是关于制作系统应用程序:How to make my application system

<强>更新

并且正如@TripeHound所说,我们可以

  

显示一个对话框,告诉用户该应用看起来会更好   如果他们打开此选项(带有不显示消息的选项)   再次,如果他们真的想要它)

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

这样:

startActivityForResult(new Intent(android.provider.Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), 0);

答案 1 :(得分:0)

使用WRITE_SECURE_SETTINGS权限是完全可以的,您可以通过adb或root授予它:

adb shell pm grant APP_PACKAGE_NAME android.permission.WRITE_SECURE_SETTINGS

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

它最重要的功能是:

    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(或在有根设备上)授予它,然后您就可以按照herehere编写的动画设置进行播放。但是,不建议使用它,因为它会在框架上使用反射。

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

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"
    }

}