中文 | English
只需至少一句代码实现 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
- 实现最简单的日夜间切换动画只需要一行代码
view.setDayNightModeSwitcher(
duration = 400L,
interpolator = FastOutSlowInInterpolator(),
animToDayMode = SwitchAnimation.SHRINK, // 前往日间模式的动画
animToNightMode = SwitchAnimation.EXPAND, // 前往夜间模式的动画
onNightModeAnimStart = { TODO("切换夜间模式动画开始回调") },
onNightModeAnimEnd = { TODO("切换夜间模式动画结束回调") },
onDayModeAnimStart = { TODO("切换日间模式动画开始回调") },
onDayModeAnimEnd = { TODO("切换日间模式动画结束回调") },
onClick = { TODO("点击事件") },
)
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... }
view.setThemeSwitcher(
toTheme = R.style.new_theme, // 前往的新主题
duration = 400L,
interpolator = FastOutSlowInInterpolator(),
animToTheme = SwitchAnimation.EXPAND, // 前往新主题的动画
onAnimStart = { TODO("切换动画开始回调") },
onAnimEnd = { TODO("切换动画结束回调") },
onClick = { TODO("点击事件") },
)
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 改变,可能会影响观感 - 不要在
onAnimStart
和onAnimEnd
相关回调中调用与当前 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 时能应用到新主题,请自行储存并设置
-
使用 PixelCopyCompat,可使在 API 小于 26 时使用先进的 PixelCopy。虽然使用了反射调用,但整体速度还是比
View#getDrawingCache()
快不少图上部分为 PixelCopy 在 API 24 时的表现(平均耗时 40ms 左右),图下部分为
View#getDrawingCache()
的表现(平均耗时 60-70ms 左右) -
takeScreenshot()
方法实现由View#getDrawingCache()
修改为View#drawToBitmap()
,速度快一倍以上(平均耗时 30ms 左右)
- 修复多 Activity 下,日间夜间切换动画无法正常播放的问题
-
在 API 26 以上使用 PixelCopy 进行屏幕截图,能保留阴影等效果
删除
screenshot()
方法,替换为takeScreenshotCompat()
-
修复
isViewClickable
逻辑不起作用的问题
- 修复 #1:部分手机不能立即 attach view 从而导致无法启动动画的问题
- 修复 API 小于 28 时动画不能显示的问题