在activity中调用setTheme来切换夜间模式的方法可能大家有看过相关的文章了,但是调用setTheme设置的主题后界面并没有变化,这时需要调用activity的recreate方法另设置的主题生效,但是试过的朋友们都知道,activity调用recreate方法以后会有一瞬间的闪屏今天写这篇文章的主题主要是关于如何避免setTheme切换主题后调用recreate的闪屏

关于如何通过改变theme更换主题的文章如果您还没有看过的话可以看一下这篇文章或者自行搜索一下recreate

recreate.gif

效果实现

1.属性动画 实现

使用属性动画配合ArgbEvaluator这个类来对所有需要变换颜色的View设置一个渐变动画属性动画

anim.gif

|

这个方法的缺点有一下几个:只要是需要有颜色变化的View要设置id并通过findViewById获取其对象,增加代码量,大家都知道设置id写findViewById有多蛋疼吧(笔者最讨厌设置控件的id了)

每一个设置的attr的color就需要写一个属性动画,代码量又增多了

RecyclerView或ListView还有某些特殊控件如何进行颜色改变(如MD风格的Button RadioButton Switch 等不能通过设置background改变颜色的控件)

接下来来看一下代码中如何实现吧

通过以下方法获取主题中设置的attrs对应颜色/**

* @param theme 需要获取attrs颜色的theme

* @param id 需要获取的attrs颜色id

* @return color

*/public static int getColorFromTheme(Resources.Theme theme, @AttrRes int id)

{

TypedValue typedValue = new TypedValue();

theme.resolveAttribute(id, typedValue, true);        return typedValue.data;

}

我们要做的是获取到当前颜色和更换后的主题颜色

activity中使用getTheme获取到Theme对象int startColorPrimary = ThemeUtil.getColorFromTheme(getTheme()R.attr.colorPrimary);

setTheme(R.style.NightTheme);int endColorPrimary = ThemeUtil.getColorFromTheme(getTheme(),R.attr.colorPrimary);

接下来就是设置一个属性动画配合ArgbEvaluator实现颜色的渐变ValueAnimator animator = ValueAnimator

.ofObject(new ArgbEvaluator(),

startColorPrimary, endColorPrimary)

.setDuration(300);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override

public void onAnimationUpdate(ValueAnimator animation) {                int color = (int) animation.getAnimatedValue();                //设置背景色的控件(Toolbar,背景layout等)

mView.setBackgroundColor(color);                //TextView字体颜色

mTextView.setTextColor(color);                //ImageView设置Tint

mImageView.setColorFilter(color);                //设置状态栏或导航栏颜色(API>=21)

getWindow().setStatusBarColor(color);

getWindow().setNavigationBarColor(color);

}

});

animator.start();

对所有需要变换颜色的控件进行操作就实现了切换效果

下面是关于RecyclerView和MD风格的Button RadioButton Switch更变颜色的方法

(其中RadioButton Switch的实现并不完美 如果有知道的欢迎补充)

通过获取RecyclerView当前在屏幕上显示的Item改变其颜色int childCount = mRecyclerView.getChildCount();for (int childIndex = 0; childIndex

ViewGroup childView = (ViewGroup) mRecyclerView.getChildAt(childIndex);                //这里的childView是RecyclerView每一个item的最外层view

//可以通过id获取每一个item里的控件

View mView = childView.findViewById(R.id.item_view);                //这里设置属性动画改变view的颜色

............

}

让 RecyclerView 缓存在 Pool 中的 Item 失效

这里的思路是通过反射拿到 AbsListView 类中的 RecycleBin 对象,然后同样再用反射去调用 clear 方法

此方法选取自知乎和简书的夜间模式实现套路Class recyclerViewClass = RecyclerView.class;            try {

Field declaredField = recyclerViewClass.getDeclaredField("mRecycler");

declaredField.setAccessible(true);

Method declaredMethod = Class.forName(RecyclerView.Recycler.class.getName()).getDeclaredMethod("clear", (Class>[]) new Class[0]);

declaredMethod.setAccessible(true);

declaredMethod.invoke(declaredField.get(mRecyclerView), new Object[0]);

RecyclerView.RecycledViewPool recycledViewPool = mRecyclerView.getRecycledViewPool();

recycledViewPool.clear();

} catch (Exception e) {

e.printStackTrace();

}

Button RadioButton Switch Progressbar通过设置Tint改变其颜色//Switch(不完美,会改变未选择时thumb的颜色 默认为灰白色)mSwitch.setThumbTintList(ColorStateList.valueOf(color));//RadioButton(不完美,会改变未选中时圆圈的颜色 默认为灰色)CompoundButtonCompat.setButtonTintList(mRadioButton, ColorStateList.valueOf(color));//Button ProgressbarViewCompat.setBackgroundTintList(mBotton, ColorStateList.valueOf(color));通过属性动画实现的缺点比较明显,布局越复杂编写的难度以及代码量就越多,最终实现的效果也不是非常完美,难点在于特殊的控件如何改变颜色,这里有兴趣的读者可以自行研究一下,下面介绍一种更简单的方式

2.startActivity 实现

此方法原理和调用recreate是相似的,通过创建一个相同的activity并加上动画可以避免闪屏startActivity

startActivity.gif

|

这个方法的难点在于:如何还原上一个activity的状态让用户感觉不到控件的变化

下面上代码

创建一个新的相同activity并设置渐入渐出动画然后结束当前activitystartActivity(new Intent(this, MainActivity.class));overridePendingTransition(R.anim.start_anim, R.anim.out_anim);finish();

这里通过启动activity创建的intent来传递以前旧界面的数据

比如EditText的输入内容RecyclerView的数据以及滑动距离

这里列出保存RecyclerView滑动距离 具体需要保存的数据需要根据界面的内容来编写//获取RecyclerView的滑动距离//调用getScrollY获取到的数据为0,也可以通过监听滑动事件保存滑动距离private int getScrollYDistance() {

LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();        int position = layoutManager.findFirstVisibleItemPosition();

View firstVisibleChildView = layoutManager.findViewByPosition(position);        int itemHeight = firstVisibleChildView.getHeight();        return (position) * itemHeight - firstVisibleChildView.getTop();

}

//通过intent传递数据到新activityIntent intent = new Intent(this, MainActivity.class);

intent.putExtra("scrollY",getcrollYDistance());//在activity的onCreate方法中还原数据//RecyclerView的setScrollBy方法只有在view测量完毕后调用才能生效mRecyclerView.post(new Runnable() {            @Override

public void run() {

mRecyclerView.scrollBy(0,getIntent().getIntExtra("scrollY", 0));

}

});使用startActivity这种方式实现的效果是不是比较简单,代码量相对也较小

难点就在于网络请求的list数据如何进行传递、保存,intent里面传递过多数据容易引起崩溃

因为是创建的新activity,最终实现的效果也比较完美

总结

以上就是我总结的如何避免切换主题时闪屏的方法,这是我第一次写技术总结,肯定有不少问题,希望需要的朋友们能够从种学习到新的知识

最后附上Demo链接https://github.com/Misutesu/NightModeDemo

(此Demo选择切换模式的RadioButton的选中状态好像有点问题,我暂时没有找到原因,如果有发现了的朋友欢迎留言告诉我)

感谢您的阅读

作者:Misutesu

链接:https://www.jianshu.com/p/b44494432619

android 闪屏动态界面,Android开发 关于避免切换主题时闪屏的几种方式相关推荐

  1. Android开发 关于避免切换主题时免闪屏的几种方式

    Android开发 关于避免切换主题时闪屏的几种方式 在activity中调用setTheme来切换夜间模式的方法可能大家有看过相关的文章了,但是调用setTheme设置的主题后界面并没有变化,这时需 ...

  2. 【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )

    文章目录 I . Android Studio 中使用 Android.mk 配置动态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  3. IOS开发基础之团购案例17-xib和UITableView两种方式实现

    IOS开发基础之团购案例17-xib和UITableView两种方式实现 Design By Johnson Shanghai 实现效果 系统和Xcode版本 注意的细节 关键性的代码 // // V ...

  4. android 9 申请动态权限android.permission.WRITE_EXTERNAL_STORAGE 允许后应用闪退

    问题描述:如题,在调试android 9 高通msm8953平台时,客户反馈应用在允许Manifest.permission.WRITE_EXTERNAL_STORAGE权限后,应用闪退. 从log分 ...

  5. android写qq动态界面,Android_Android仿QQ空间主页面的实现,今天模仿安卓QQ空间,效果如 - phpStudy...

    Android仿QQ空间主页面的实现 今天模仿安卓QQ空间,效果如下: 打开程序的启动画面和导航页面我就不做了,大家可以模仿微信的那个做一下,很简单.这次主要做一下主页面的实现,下面是主页面的布局: ...

  6. android碎片调用动态碎片,Android Training - 使用碎片创建一个动态UI

    为了能够在Android中创建动态和多窗口的用户界面,你需要封装UI组件和activity行为在不同的模块中,以便你可以在不同的activity间切换.你可以使用Fragment类创建这些模块,类似于 ...

  7. android里qq登录界面,Android仿QQ登陆窗口实现原理

    今天根据腾讯qq,我们做一个练习,来学习如何制作一个漂亮的布局.首先看一下官方图片 还是一个启动画面,之后进入登录页面,导航页面就不介绍了,大家可以参考微信的导航页面.首先程序进入SplashActi ...

  8. Android宫格动态列,Android实现宫格图片连续滑动效果

    本文给大家介绍如何在Android中实现宫格图片连续滑动效果. 在这之前,写过几篇关于在Android中实现滑动的效果,毕竟滑动效果在Andriod开发中也使用得比较频繁,有兴趣的朋友请查看我以前的文 ...

  9. android背景颜色动态修改,Android自定义TextView带圆角及背景颜色(动态改变圆角背景颜色)...

    最近根据项目需求自定义了一个TextView控件,主要用来做状态的标识,比如一个订单状态有各种,当然了这种设置在Android中可以直接用xml文件来处理,但是对于xml文件太过于麻烦,针对不同的颜色 ...

  10. Android 编程下帧动画在 Activity 启动时自动运行的几种方式

    Android 开发过程中部分 Activity 在显示的时候就要求给用户显示一个进度框来改善用户体验,比如:Activity 在启动的时候就去联网请求数据.读取数据库内容等.进度框显示样式如下,采用 ...

最新文章

  1. 计算机网络第六章:应用层
  2. LVS的三种负载均衡以及高可用原理(VS/NAT、VS/TUN、VS/DR)
  3. mysql event执行记录_mysql event建立模板(可记录执行履历)
  4. 从零开始netty学习笔记之BIO
  5. 时间序列研(part1)--随机过程
  6. 推导基姆拉尔森公式根据日期计算星期
  7. 软考倒计时25天: 案例背诵点
  8. date命令使用文档.txt
  9. matlab 不同函数间传递结构体数据_VC与Matlab混合编程及复杂数据:结构体传递
  10. 推荐几个Mac系统桌面吸色工具!颜色吸取器
  11. xpath批量下载简历模板
  12. android之仿朋友圈程序,Android仿微信朋友圈添加图片的实例代码
  13. float数据十六进制表示法,十六进制读取float数据
  14. Echarts图列legend动态设置选中或者不选中 selected
  15. gcd算法以及exgcd
  16. 美术 2.4 UV原理基础
  17. GB2312编码范围
  18. 微信小游戏排行榜卡顿或无法滑动
  19. 性能测试七种常用方法,以及四大应用领域
  20. 《硬核父母的五项修炼》读后感

热门文章

  1. 明源售楼系统技术解析(三)付款定义新增、修改、删除
  2. 错误请联系管理员文件 index.php,GS登录报错,提示【访问权限失败,请联系管理员处理】...
  3. ‘xxx‘ is missing in props validation
  4. 佛青云怎么过鸿蒙,神都夜行录鸿蒙之境策驱三运高级怎么打 鸿蒙之境策驱三运高级打法攻略...
  5. 六、T100固定资产之固定资产月结处理
  6. TypeScript 使用 infer 实现类型推断
  7. 抢不到回家的票,还真不是12306技术不行
  8. fastlane php,fastlane 自动化打包不同的target,以及手动传版本号参数
  9. P8462 「REOI-1」奶油蛋糕
  10. 红色小吃加盟网站源码 织梦dede模板[带手机版数据同步]