在安卓系统中动态更改日夜模式

3

我正在开发一款基于Android的GPS导航应用程序,需要根据光线传感器的值自动实现白天和黑夜主题的切换。问题在于我必须在不重新启动Activity或应用程序的情况下更改主题。

我尝试通过遵循此教程(http://sriramramani.wordpress.com/2012/12/06/runtime-theme-change/)来实现这一点,其中使用自定义状态来在日间和夜间模式之间切换。但是它需要进行许多更改,因为我的应用程序具有许多布局。此外,使用此实现方式,开发人员必须注意将来屏幕的白天和黑夜模式。

是否有任何简单有效的方法来实现这一点?


你是否对光传感器的值应用任何过滤器?我正在做类似的事情,只是好奇。 - fancy
是的。我正在读取传感器值,每1或2秒钟检测一次传感器值变化,并找到20个观测值的平均值。如果这个平均值大于一个阈值,那么我就会改变颜色。 - Ram Vibhakar
你尝试过在布局中使用夜间和非夜间限定符吗?就像这个链接中提到的:http://developer.android.com/guide/topics/resources/providing-resources.html - Vins
请查看此链接 https://stackoverflow.com/a/60164414/11158194 - Hardik Talaviya
2个回答

2

ViewFlipper!这是我在应用程序中使用的选项,允许用户选择白天或黑夜主题。由于Java的本质,它可以根据任何布尔值进行更改(即如果亮度比2秒前暗),但是,没有真正简单的方法来自动切换所有布局,而不需要编写切换代码或在别人的工作基础上构建。

以下是如何实现:

我有一个应用程序,其中包含1个活动、1个布局和一个按钮来切换颜色。

  • MainActivity.java
  • activity_main.xml(包含按钮)

将ViewFlipper作为每个布局的子元素放置,如下所示:(每个需要白天和黑夜模式的布局)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <ViewFlipper
    android:id="@+id/viewFlipper"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

  </ViewFlipper>

</RelativeLayout>

然后,对于每个布局,我制作了白天颜色布局和夜晚颜色布局。白天和夜晚布局都必须是ViewFlipper的子项,因此如果您折叠这两个布局,它应该是:
- < ViewFlipper> - < RelativeLayout> 白天元素放在这里< /RelativeLayout> - < RelativeLayout> 夜晚元素放在这里< /RelativeLayout> - < /ViewFlipper> 接下来是麻烦的部分:每个元素必须具有唯一的ID,因为它们在同一个文档中,例如,如果您想在同一屏幕上拥有白天按钮和夜晚按钮。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ViewFlipper
  android:id="@+id/viewFlipper"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <LinearLayout
    android:id="@+id/DayLayout"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    android:layout_marginBottom="15dp">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/profileDayBtn"
        android:textStyle="bold"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:background="#fff"
        android:textColor="#000" />
</LinearLayout>
<LinearLayout
    android:id="@+id/NightLayout"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/profileNightBtn"
    android:layout_marginBottom="20dp"
    android:layout_marginTop="15dp"
    android:textStyle="bold"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:background="#000"
    android:textColor="#fff" />
</LinearLayout>

</ViewFlipper>
</RelativeLayout>

这就是布局的全部内容,现在需要实际更改它:
在每个具有白天或夜晚布局的活动中添加此代码:(我将其添加到了每个活动的onCreate中,但这不适用于基于时间的开关)
    setContentView(R.layout.activity_main);

    Button dayBtn = (Button) findViewById(R.id.profileDayBtn);
    Button nightBtn = (Button) findViewById(R.id.profileNightBtn);

    View.OnClickListener changeColorMode = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          ViewFlipper vf = (ViewFlipper) findViewById( R.id.viewFlipper );
          if (v == dayBtn) {
            vf.showNext();
          } else if (v == nightBtn) {
            vf.showPrevious();
          }
    };
    dayBtn.setOnClickListener(changeColorMode);
    nightBtn.setOnClickListener(changeColorMode);
    }

布局被设置为activity_main,但是由于activity_main有一个viewflipper,它将其设置为viewflipper内的第一个根元素(索引0,即我的日间布局)。.showNext()将显示下一个根元素(索引1为我的夜间布局,如果我添加了更多,则依此类推)

总之,如果您需要显示特定的布局而不是猜测.showNext(),则可以调用

   viewFlipper.setDisplayedChild(viewFlipper.indexOfChild(XXX));

其中XXX可以被替换为布局的索引(0, 1等),或者XXX可以被替换为特定的布局ID,如下所示:viewFlipper.setDisplayedChild(viewFlipper.indexOfChild(findViewById(R.id.DayLayout))

我使用这个方法非常好用,因为它非常简单易懂,并且可定制性很强!希望这能帮到您。

- Stephen


0

不,主题/样式必须在创建视图/布局之前应用。

如果您想要实时更改主题,则必须在JAVA代码中完成所有操作,如setBackground(color)、setImageRes(xxx)、setTextColor(xxx)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接