作者:Bgwan
链接:https://zhuanlan.zhihu.com/p/22520818
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

网上看到过大多实现夜间模式的效果,实现方式总结起来,发现好繁琐,大多数夜间模式实现都是基于另一套apk来,作为依赖实现,像QQ,微信,这种直接提供给你一套皮肤来切换背景,如果要做这个皮肤开发的工作量不小于一个软件的开发周期,而知乎简书这种夜间模式的实现就相对于更加轻量级了。

今天这里采用qydq/提供的an框架来简单快速实现夜间模式,an框架提供了两种方式实现夜间模式,一种比较简单,一种比较复杂。

Athor IP:sunshuntao(qydq)(莳萝花)。

Email:qyddai@gmail.com。

知乎地址:Android开发 - 知乎专栏

Begin

♥♥♥ 请关注后获取源码 ♥♥♥

创建时间:2016年08月29日;最近修改时间:2016年08月30日。

GitHub - qydq/an-maven-base: android studio创建github 的repository

Tips

1。前言(包含该项目主要实现的功能的简短说明,运行配置;可选)。

2。实现效果(如果没有可以省略,但是建议要包含,因为项目以后自己看到的时候会帮助自己理解)。

3。思路或使用(代码)。

## *** 使用方法 *** ##

4。重要知识点(总结,思考)。

5。内容参考(尊重原创)。

6。联系作者。

*** -----------------------------woshifengexian-----------------------------------***

2,实现效果

3。思路或使用(代码)。

稍微说一下,首先外面切换的时候,只是设置了部分区域的夜间模式,这里主要以示区别,你自己也可以试着把那个模块区域加上夜间模式,下面的内容会讲解到。

点击进去也设置了夜间模式,可以看到也是部分区域设置了夜间模式(这里是随便选了一种颜色就当作皮肤,你可以改成夜间模式灰色即可),因为点击后的界面我们要用第二种方式来实现夜间模式,这里以示区别。具体根据业务需求来采用相应的方法。

下面开始讲解两种夜间模式的实现方法。首先在编译build.gradle中加入an框架如下依赖,

自己备注一下:base应该是轻量级别的依赖关系,an应该是重量级的依赖,这里算是一个瑕疵。

  1. compile 'com.github.qydq:an-maven-base:0.0.8'

1)第一种实现方法,稍微有点复杂。

首先我们需要一个夜间模式的帮助类,还有要找到需要设置夜间模式的Layout

  1. //主题切换测试
  2. private DayNightHelper mDayNightHelper;
  3. private RecyclerView mRecyclerView;
  4. private LinearLayout mHeaderLayout;
  5. private List<RelativeLayout> mLayoutList;
  6. private List<TextView> mTextViewList;
  7. private List<CheckBox> mCheckBoxList;

在setContentView()之前,加入初始化的夜间模式主题,如

  1. mDayNightHelper = new DayNightHelper(this);
  2. initTheme();
  3. setContentView(R.layout.activity_main);

initTheme()如下,作用是关闭应用第二次进入如果是夜间模式则显示夜间模式,反之亦然,

  1. private void initTheme() {
  2. if (mDayNightHelper.isDay()) {
  3. setTheme(R.style.DayTheme);
  4. } else {
  5. setTheme(R.style.NightTheme);
  6. }
  7. }

简单的findViewById

  1. mLayoutList = new ArrayList<>();
  2. mLayoutList.add((RelativeLayout) findViewById(R.id.jianshu_layout));
  3. mLayoutList.add((RelativeLayout) findViewById(R.id.zhihu_layout));
  4. mTextViewList = new ArrayList<>();
  5. mTextViewList.add((TextView) findViewById(R.id.tv_jianshu));
  6. mTextViewList.add((TextView) findViewById(R.id.tv_zhihu));
  7. mCheckBoxList = new ArrayList<>();
  8. CheckBox ckbJianshu = (CheckBox) findViewById(R.id.ckb_jianshu);
  9. ckbJianshu.setOnCheckedChangeListener(this);

其次是对某一事件的监听 ,修改主题,这里是CheckBox

  1. @Override
  2. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  3. int viewId = buttonView.getId();
  4. if (viewId == R.id.ckb_jianshu) {
  5. changeThemeByJianShu();
  6. } else if (viewId == R.id.ckb_zhihu) {
  7. changeThemeByZhiHu();
  8. }
  9. }

这里讨论知乎的实现讨论,可以看到这里启动了一个夜间模式切换的动画,这样不至于一下子就变了背景。动画是实现的渐变效果,给用户好的体验效果。toggleThemeSetting是对CheckBox的事件监听来j。

  1. /**
  2. * 使用知乎的实现套路来切换夜间主题
  3. */
  4. private void changeThemeByZhiHu() {
  5. showAnimation();
  6. toggleThemeSetting();
  7. refreshUI();
  8. }

showAnimation和toggleThemSetting的代码如下,

  1. /**
  2. * 展示一个切换动画
  3. */
  4. private void showAnimation() {
  5. final View decorView = getWindow().getDecorView();
  6. Bitmap cacheBitmap = getCacheBitmapFromView(decorView);
  7. if (decorView instanceof ViewGroup && cacheBitmap != null) {
  8. final View view = new View(this);
  9. view.setBackgroundDrawable(new BitmapDrawable(getResources(), cacheBitmap));
  10. ViewGroup.LayoutParams layoutParam = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
  11. ViewGroup.LayoutParams.MATCH_PARENT);
  12. ((ViewGroup) decorView).addView(view, layoutParam);
  13. ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f);
  14. objectAnimator.setDuration(300);
  15. objectAnimator.addListener(new AnimatorListenerAdapter() {
  16. @Override
  17. public void onAnimationEnd(Animator animation) {
  18. super.onAnimationEnd(animation);
  19. ((ViewGroup) decorView).removeView(view);
  20. }
  21. });
  22. objectAnimator.start();
  23. }
  24. }
  1. /**
  2. * 切换主题设置
  3. */
  4. private void toggleThemeSetting() {
  5. if (mDayNightHelper.isDay()) {
  6. mDayNightHelper.setMode(DayNightMode.NIGHT);
  7. setTheme(R.style.NightTheme);
  8. } else {
  9. mDayNightHelper.setMode(DayNightMode.DAY);
  10. setTheme(R.style.DayTheme);
  11. }
  12. }

再者,开始更新UI,refresh当前的UI,initThem是进入是的模式是夜间还是白天。

  1. TypedValue background = new TypedValue();//背景色
  2. TypedValue textColor = new TypedValue();//字体颜色
  3. Resources.Theme theme = getTheme();
  4. theme.resolveAttribute(R.attr.anBackground, background, true);
  5. theme.resolveAttribute(R.attr.anTextColor, textColor, true);
  6. mHeaderLayout.setBackgroundResource(background.resourceId);
  7. for (RelativeLayout layout : mLayoutList) {
  8. layout.setBackgroundResource(background.resourceId);
  9. }
  10. for (CheckBox checkBox : mCheckBoxList) {
  11. checkBox.setBackgroundResource(background.resourceId);
  12. }
  13. for (TextView textView : mTextViewList) {
  14. textView.setBackgroundResource(background.resourceId);
  15. }
  16. Resources resources = getResources();
  17. for (TextView textView : mTextViewList) {
  18. textView.setTextColor(resources.getColor(textColor.resourceId));
  19. }

最后,你不觉得很奇怪吗?就凭借上面的代码就可以实现夜间模式切换效果,未免太简单了吧,其实不用奇怪,就是这么简单,我们只要在加入an框架的background即可,这样,每次设置好相应的夜间模式或正常模式,an框架都会帮助去进行主题的设置。

在Layout布局代码中按照如下这样的标准加入相应的,属性。

  1. <LinearLayout
  2. android:id="@+id/header_layout"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:background="?attr/anBackground"
  6. android:orientation="vertical">
  7. <RelativeLayout
  8. android:id="@+id/jianshu_layout"
  9. android:layout_width="match_parent"
  10. android:layout_height="35dp"
  11. android:background="?attr/anBackground">
  12. <TextView
  13. android:id="@+id/tv_jianshu"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:layout_centerVertical="true"
  17. android:layout_marginLeft="10dp"
  18. android:background="?attr/anBackground"
  19. android:text="简书夜间模式切换方案"
  20. android:textColor="?attr/anTextColor" />
  21. <CheckBox
  22. android:id="@+id/ckb_jianshu"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:layout_alignParentRight="true"
  26. android:layout_centerVertical="true"
  27. android:layout_marginRight="20dp"
  28. android:background="?attr/anBackground" />
  29. </RelativeLayout>

第一种方式的所有实现夜间模式套路,这里已经完全,完完全全给出来了,你不需要额外的配置,这样就可以完成夜间模式,但是相对于第二种方式就显得比较复杂了。an框架也提供的另一种简单的夜间模式,如2)中。

2)第二种夜间模式实现方式,简单夜间模式实现方式,如效果图第二个点击进入的窗口(即改变背景)

同样在CheckBox中,监听即可完成夜间模式的设置,下次启动则可以生效,从效果图可以看到,改变了主题颜色(改变主题也可以认为就是夜间模式,只不过换个颜色)上面也说了,不能写一个皮肤出来,大材小用。,业务也不需要。

  1. @Override
  2. public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
  3. SharedPreferences.Editor editor = sp.edit();
  4. if (sp.getBoolean("isNightMode", false)) {
  5. editor.putBoolean("isNightMode", false);
  6. editor.commit();
  7. getWindow().getDecorView().setBackground(this.getResources().getDrawable(com.an.an_base.R.drawable.yy_drawable_bgnigt_shape));
  8. } else {
  9. editor.putBoolean("isNightMode", true);
  10. editor.commit();
  11. getWindow().getDecorView().setBackground(getResources().getDrawable(com.an.an_base.R.drawable.yy_drawable_bgday_shape));
  12. }

从效果图也可以看到,之前设置的夜间模式,显示出来了,是因为我为了验证第一种(设置夜间模式的方法是否有效)而加入的代码,可以看到第一种夜间模式完全OK,加入了下面代码

  1. mDayNightHelper = new DayNightHelper(this);
  2. initTheme();
  3. setContentView(R.layout.activity_create_code);
  1. private void initTheme() {
  2. if (mDayNightHelper.isDay()) {
  3. setTheme(R.style.DayTheme);
  4. } else {
  5. setTheme(R.style.NightTheme);
  6. }
  7. }

4。重要知识点(总结,思考)。

引用了an框架,具体也可以参考,网易博客。

5。内容参考(尊重原创)。

第一种实现套路是参考知乎上另一位童鞋的夜间模式的实现套路修改而来的,这里已经完全简化了使用方式,通过本博客既可以快速集成。

参考,链接(我又上网找到了,但不是知乎的,是传送门也有参考)

知乎和简书的夜间模式实现套路_Android程序员

第二种为个人设计

6。联系作者。

## 联系作者。

Athor:sunshuntao(qydq)(莳萝花)。

Email:qyddai@gmail.com。

知乎地址:Android开发 - 知乎专栏

End

♥♥♥ 请关注后获取源码 ♥♥♥

至:授人以鱼,不如授人与渔,话不多说,yu前几篇博客已经介绍过,更多内容请关注。

Android 利用an框架快速实现夜间模式的两种套路的更多相关文章

  1. Android 高级UI设计笔记23:Android 夜间模式之 两种常用方法(降低屏幕亮度+替换theme)

    1. 夜间模式 所谓的夜间模式,就是能够根据不同的设定,呈现不同风格的界面给用户,而且晚上看着不伤眼睛.特别是一些新闻类App实现夜间模式是非常人性化的,增强用户体验. 2. 我根据网上的资料 以及自 ...

  2. Android 利用an框架快速实现网络请求(含下载上传文件)

    作者:Bgwan链接:https://zhuanlan.zhihu.com/p/22573081来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. an框架的网络框架是完全 ...

  3. 内核知识第12讲,SSDT表.以用户模式到系统模式的两种方式.

    内核知识第12讲,SSDT表.以用户模式到系统模式的两种方式. 一丶IDT解析. 我们知道.IDT表中存放着各种中断信息.比如当我们调用int 3的时候,则会调用IDT表中的第三项来进行调用. 而函数 ...

  4. Android开发之使用sqlite3工具操作数据库的两种方式

    使用 sqlite3 工具操作数据库的两种方式 请尊重他人的劳动成果,转载请注明出处:Android开发之使用sqlite3工具操作数据库的两种方式 http://blog.csdn.net/feng ...

  5. 探究Repository模式的两种写法与疑惑

    现如今DDD越来越流行,园子里漫天都是介绍关于它的文章.说到DDD就不能不提Repository模式了,有的地方也叫它仓储模式. 很多时候我们对Repository都还停留在Copy然后使用的阶段, ...

  6. 单例Singleton模式的两种实现方法

    在设计模式中,有一种叫Singleton模式的,用它可以实现一次只运行一个实例.就是说在程序运行期间,某个类只能有一个实例在运行.这种模式用途比较广泛,会经常用到,下面是Singleton模式的两种实 ...

  7. Android夜间模式的几种实现

    一.直接修改widget颜色,这种方式实现起来最简单,但需要每个控件都去修改,太过复杂.例如: /** * 相应交互,修改控件颜色 * @param view */public void onMeth ...

  8. android利用apkplug框架实现主应用与插件通讯(传递随意对象)实现UI替换

    时光匆匆,乍一看已半年过去了,经过这半年的埋头苦干今天最终有满血复活了. 利用apkplug框架实现动态替换宿主Activity中的UI元素.以达到不用更新应用就能够更换UI样式的目的. 先看效果图: ...

  9. Android中实现全屏、无标题栏的两种办法

    在进行UI设计时,我们经常需要将屏幕设置成无标题栏或者全屏.要实现起来也非常简单,主要有两种方法:配置xml文件和编写代码设置. 1.在xml文件中进行配置 在项目的清单文件AndroidManife ...

随机推荐

  1. 平板电脑上完美体验Windows 8 (视频)

    平板电脑上完美体验Windows 8 (视频) 目前,计算机产业正面临重大变革,三网融合,云计算,物联网正加速终端产品的融合.4C融合成为终端产品的未来发展趋势,是4C融合的代表性产品,它破了传统的W ...

  2. 深入了解"网上邻居"原理

    说到“网上邻居”,相信很多人都很熟悉.但是说起“网上邻居”的工作机制,可能大家就不太清楚了. 要说“网上邻居”的工作机制,不妨联系一下生活中的例子:比如我(A),要拜访一个远方的朋友(B),我要去他的 ...

  3. UVA 10306 e-Coins(全然背包: 二维限制条件)

    UVA 10306 e-Coins(全然背包: 二维限制条件) option=com_onlinejudge&Itemid=8&page=show_problem&proble ...

  4. 给指定的用户无需密码执行 sudo 的权限

    给指定的用户无需密码执行 sudo 的权限 cat /etc/passwd 可以查看所有用户的列表 w 可以查看当前活跃的用户列表 cat /etc/group 查看用户组 cat /etc/pass ...

  5. 20.Node.js EventEmitter的方法和事件

    转自:http://www.runoob.com/nodejs/nodejs-tutorial.html EventEmitter 提供了多个属性,如 on 和 emit.on 函数用于绑定事件函数, ...

  6. http 协议上传文件multipart form-data boundary 说明--转载

    原文地址:http://xixinfei.iteye.com/blog/2002017 含义 ENCTYPE="multipart/form-data" 说明: 通过 http 协 ...

  7. [Python] The get() method on Python dicts and its "default" arg

    # The get() method on dicts # and its "default" argument name_for_userid = { 382: "Al ...

  8. Android内存泄露分析之StrictMode

    转载请注明地址:http://blog.csdn.NET/yincheng886337/article/details/50524709 StrictMode(严格模式)使用 StrictMode严格 ...

  9. Vue使用Promise自定义confirm确认框组件

    使用Promise模拟浏览器确认框,可自定义标题,内容,按钮文字和类型 参数名 类型 说明 title String 标题 content String 内容 yesBtnText String 确认 ...

  10. tcl -mode

    -exact     严格匹配(如string equal) -glob 通配符式匹配(string match) -regexp   正则表达式匹配(regexp) array get和array ...