您的位置:首页 > 移动开发 > Android开发

Android实现夜间模式

2017-09-21 19:05 197 查看
分下面几步实现:

1.加入依赖: compile ‘com.android.support:appcompat-v7:23.2.1’

网上说要加入v7的25版本,但在那种情况下会出现报错,具体可以参考我之前的博文:

http://blog.csdn.net/kururunga/article/details/78054323

导入完sync一下

2.自定义Application:

package lwp.testr11;

import android.app.Application;
import android.support.v7.app.AppCompatDelegate;

/**
* Created by fh on 17-9-21.
*/
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
/**
* 默认设置一直使用夜间模式
*
* 这里AppCompatDelegate.setDefaultNightMode()方法可以接受的参数值有4个:
* MODE_NIGHT_NO. Always use the day (light) theme(一直应用日间(light)主题).
* MODE_NIGHT_YES. Always use the night (dark) theme(一直使用夜间(dark)主题).
* MODE_NIGHT_AUTO. Changes between day/night based on the time of day(根据当前时间在day/night主题间切换).
* MODE_NIGHT_FOLLOW_SYSTEM(默认选项). This setting follows the system’s setting, which is essentially MODE_NIGHT_NO(跟随系统,通常为MODE_NIGHT_NO).
*/
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}

}


替换AndroidMainfest android:theme=”@style/AppNightTheme”

AppNight

<style name="AppNightTheme"      parent="Theme.AppCompat.DayNight">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</s
4000
tyle>


3.res目录下建立values-night资源:

values-night/colors:

<!-- night values colors.xml -->
<resources>
<color name="colorPrimary">#35464e</color>
<color name="colorPrimaryDark">#212a2f</color>
<color name="colorAccent">#212a2f</color>
<color name="textColorPrimary">#616161</color>
<color name="viewBackground">#212a2f</color>
<color name="colorDayNightChange">@android:color/holo_blue_dark</color>
</resources>


values-night/strings:

<resources>
<string name="app_name">DayNight</string>
<string name="day_night_label">夜间模式</string>
</resources>


对应与values/color:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#009688</color>
<color name="colorPrimaryDark">#00796B</color>
<color name="colorAccent">#009688</color>
<color name="textColorPrimary">#616161</color>
<color name="viewBackground">@android:color/white</color>
<color name="colorDayNightChange">@android:color/holo_orange_dark</color>
</resources>


values/strings:

<resources>
<string name="app_name">DayNight</string>
<string name="day_night_label">日间模式</string>
</resources>


在夜间模式下加载values-night里的资源,而在日间模式则加载values资源,就是这写资源导致颜色,字体的变化。

4.MainActivity实现如下:

package lwp.testr11;

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
private Button mDayNightChange;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("Hello","Hello");
mDayNightChange = (Button) findViewById(R.id.day_night_change);

mDayNightChange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int mode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (mode == Configuration.UI_MODE_NIGHT_YES) {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else if (mode == Configuration.UI_MODE_NIGHT_NO) {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}

recreate();
}
});
}
}


对应的布局文件如下:

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

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/day_night_label"
android:textSize="20sp"
android:textColor="@color/colorDayNightChange" />

<Button
android:id="@+id/day_night_change"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="5dp"
android:text="日夜间模式切换"
android:textSize="20sp"
android:textColor="@color/colorDayNightChange"/>
</LinearLayout>


5.大功告成,点击Run吧!

这种方式,通过设置主题的方式实现夜间和日间,只能实现两种效果,优点是简单方便资源消耗少,缺点是只有两种模式选择,也会导致activity被重新创建(调用了recreate方法),这种情况下,activity异常关闭有一些信息需要我们自己保存。

比如我就发现了这样一个问题:

在我的activity中设定了一个EditText,这个edittext输入了一个字符串,在点击日夜间模式切换的时候,由于activity重新创建导致数据丢失,此时采用在onSaveInstanceState和onRestoreInstanceState里写逻辑即可。

具体实现如下:

@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
outState.putString("ok",s);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);

savedInstanceState.getString("ok");
}


附上完整的MainActivity代码:

package lwp.testr11;

import android.content.res.Configuration;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {
private Button mDayNightChange;
private EditText et;
private String s;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("Hello","Hello");
et = (EditText) findViewById(R.id.et);
mDayNightChange = (Button) findViewById(R.id.day_night_change);

mDayNightChange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
s = et.getText().toString();
int mode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (mode == Configuration.UI_MODE_NIGHT_YES) {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else if (mode == Configuration.UI_MODE_NIGHT_NO) {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}

recreate();
}
});
}

@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
outState.putString("ok",s);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);

savedInstanceState.getString("ok");
}
}


通过系统自带的Bundle思路解决。

然而我发现并不是这个重写onSaveInstanceState和onRestoreInstanceState的问题而是系统会自动为异常销毁的activity保存数据(应该是调用上述两个方法),注意,当且仅当该组件有id,此时我

package lwp.testr11;

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
imp
c40f
ort android.support.v7.app.AppCompatDelegate;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
private Button mDayNightChange;
//   private EditText et;
//  private String s;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("Hello","Hello");
//  et = (EditText) findViewById(R.id.et);
mDayNightChange = (Button) findViewById(R.id.day_night_change);

mDayNightChange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//       s = et.getText().toString();
int mode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (mode == Configuration.UI_MODE_NIGHT_YES) {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else if (mode == Configuration.UI_MODE_NIGHT_NO) {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}

recreate();
}
});
}

//    @Override
//    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
//        super.onSaveInstanceState(outState, outPersistentState);
//   //   outState.putString("ok",s);
//    }

//    @Override
//    protected void onRestoreInstanceState(Bundle savedInstanceState) {
//        super.onRestoreInstanceState(savedInstanceState);
//
//        savedInstanceState.getString("ok");
//    }

//    @Override
//    protected void onPause() {
//        super.onPause();
//      //  Bundle bundle=new Bundle();
//      //  bundle.putString("ok",s);
//    }
}


将onRestoreInstanceState,onSaveInstanceState注释掉,并且也没把edittext实例化出来,此时,只要xml中设置了edittext的id,即可在activity被销毁的重建的适合保存数据,并不需要重写onSaveInstanceState和onRestoreInstanceState。所以我就想是不是系统调用onSaveInstanceState和onRestoreInstanceState的时候是遍历该activity中所有带id的控件进行数据保存,总结一下:如果不给一个view设置一个id,那么在Activity调用onSaveInstantceState(Bundle outState)方法时,就没办法保存它的状态,而且即使它当前是焦点view,也没办法将其焦点状态记录在Bundle对象中,这会导致在需要取出Bundle状态对象时,出现问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息