Skip to content

Just one line of code to achieve the Circular Reveal Theme Switch Animation in Telegram

License

Notifications You must be signed in to change notification settings

YenalyLiew/CircularRevealSwitch

Repository files navigation

中文 | English

CircularRevealSwitch

环形揭示切换


只需至少一句代码实现 Telegram 环形揭示切换主题动画



使用

在 settings.gradle.kts 中添加 jitpack 仓库

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven {
            url = uri("https://jitpack.io")
            // groovy:
            // url 'https://jitpack.io'
        }
    }
}

在你的模块下的 build.gradle.kts 中添加依赖

dependencies {
    implementation("com.github.YenalyLiew:CircularRevealSwitch:0.4.6")
}

使用效果

日间到夜间 夜间到日间 切换至黄色主题 切换至红色主题

使用要求

Android API 至少为 24 (Android 7.0)

Android 7.0 以上才支持 DecorView 复用,而本库依赖复用 DecorView。

优势

  • 无需自行嵌套、添加新 View
  • 有一定拓展性,方法均为 protected open
  • 实现最简单的日夜间切换动画只需要一行代码

基础使用方法

日夜间切换

Kotlin

view.setDayNightModeSwitcher(
    duration = 400L,
    interpolator = FastOutSlowInInterpolator(),
    animToDayMode = SwitchAnimation.SHRINK, // 前往日间模式的动画
    animToNightMode = SwitchAnimation.EXPAND, // 前往夜间模式的动画
    onNightModeAnimStart = { TODO("切换夜间模式动画开始回调") },
    onNightModeAnimEnd = { TODO("切换夜间模式动画结束回调") },
    onDayModeAnimStart = { TODO("切换日间模式动画开始回调") },
    onDayModeAnimEnd = { TODO("切换日间模式动画结束回调") },
    onClick = { TODO("点击事件") },
)

Java

DayNightModeCRSwitch builder = new DayNightModeCRSwitch.Builder(view)
        .duration(400L)
        .interpolator(new FastOutSlowInInterpolator())
        .animToDayMode(SwitchAnimation.SHRINK) // 前往日间模式的动画
        .animToNightMode(SwitchAnimation.EXPAND) // 前往夜间模式的动画
        .onNightModeAnimStart(() -> {
            // TODO: 切换夜间模式动画开始回调
        })
        .onNightModeAnimEnd(() -> {
            // TODO: 切换夜间模式动画结束回调
        })
        .onDayModeAnimStart(() -> {
            // TODO: 切换日间模式动画开始回调 
        })
        .onDayModeAnimEnd(() -> {
            // TODO: 切换日间模式动画结束回调
        })
        .onClickListener((view) -> {
            // TODO: 点击事件
        })
        .build();
builder.setSwitcher();

主题切换

⚠ 你需要在 super.onCreate(savedInstanceState) 之前调用 setTheme 方法,加载你切换的主题。如果你只想要个动画,可以选择直接调用 ThemeCRSwitch.setTheme(int)

ThemeCRSwitch.setTheme(int) 只是自慰方法,不推荐使用。如果需要保存主题状态,请自行使用 SharedPreferences 或其他库进行储存与加载

🌰 举例:

override fun onCreate(savedInstanceState: Bundle?) {
    when (sharedPrefs().getString("theme", "default")) {
        "red" -> setTheme(R.style.Theme_CircularRevealSwitch_Red)
        "green" -> setTheme(R.style.Theme_CircularRevealSwitch_Green)
        "blue" -> setTheme(R.style.Theme_CircularRevealSwitch_Blue)
        "yellow" -> setTheme(R.style.Theme_CircularRevealSwitch_Yellow)
        else -> setTheme(R.style.Theme_CircularRevealSwitch)
    }
    super.onCreate(savedInstanceState)
    // view.setThemeSwitcher...
}

Kotlin

view.setThemeSwitcher(
    toTheme = R.style.new_theme, // 前往的新主题
    duration = 400L,
    interpolator = FastOutSlowInInterpolator(),
    animToTheme = SwitchAnimation.EXPAND, // 前往新主题的动画
    onAnimStart = { TODO("切换动画开始回调") },
    onAnimEnd = { TODO("切换动画结束回调") },
    onClick = { TODO("点击事件") },
)

Java

ThemeCRSwitch builder = new ThemeCRSwitch.Builder(view, R.style.new_theme)
        .duration(400L)
        .interpolator(new FastOutSlowInInterpolator())
        .animToTheme(SwitchAnimation.EXPAND) // 前往新主题的动画
        .onAnimStart(() -> {
            // TODO: 切换主题动画开始回调
        })
        .onAnimEnd(() -> {
            // TODO: 切换主题动画结束回调
        })
        .onClickListener((view) -> {
            // TODO: 点击事件
        })
        .build();
builder.setSwitcher();

⚠ 使用注意

  • 本库强依赖 ActivityCompat#recreate 方法,如果你的 Activity 在重建后 View 改变,可能会影响观感
  • 不要onAnimStartonAnimEnd 相关回调中调用与当前 Activity 相关的组件,因为回调到这里时,旧 Activity 已经销毁,你对组件的任何操作基本都会失效,但你可以在这里执行一些 application 级操作。如果你需要在旧 Activity 未销毁之前执行其他任务,可以在 onClick 中执行
  • 建议至少是 ComponentActivity
  • 建议 API 大于等于 28(Android 9.0),因为操作依赖于 Handler#post,而 ActivityCompat#recreate 中 API 低于 28 会 Handler 套 Handler 再 recreate,放入主消息队列的顺序可能会不一样,动画可能失效,但其实一般不会失效v0.3 已解决)
  • setSwitcher() 方法会覆盖原本的 onTouch()onClick() 方法,如果需要点击事件,可以从构造器里调用,或者继承 CircularRevealSwitch 类重写相应的方法
  • 本库只提供切换主题效果,不提供切换后主题的保存。如果你需要保存主题,希望下次启动软件或者打开新 Activity 时能应用到新主题,请自行储存并设置

更新

v0.4.6

  1. 使用 PixelCopyCompat,可使在 API 小于 26 时使用先进的 PixelCopy。虽然使用了反射调用,但整体速度还是比 View#getDrawingCache() 快不少

    图上部分为 PixelCopy 在 API 24 时的表现(平均耗时 40ms 左右),图下部分为 View#getDrawingCache() 的表现(平均耗时 60-70ms 左右)

  2. takeScreenshot() 方法实现由 View#getDrawingCache() 修改为 View#drawToBitmap(),速度快一倍以上(平均耗时 30ms 左右)

v0.4.5

  1. 修复多 Activity 下,日间夜间切换动画无法正常播放的问题

v0.4

  1. 在 API 26 以上使用 PixelCopy 进行屏幕截图,能保留阴影等效果

    删除 screenshot() 方法,替换为 takeScreenshotCompat()

  2. 修复 isViewClickable 逻辑不起作用的问题

v0.3

  1. 修复 #1:部分手机不能立即 attach view 从而导致无法启动动画的问题
  2. 修复 API 小于 28 时动画不能显示的问题

About

Just one line of code to achieve the Circular Reveal Theme Switch Animation in Telegram

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages