主题不是通过按 Switch 设置的。应用程序不会崩溃
Theme is not set by pressing Switch. App doesn't crash
我们的应用程序将 运行 有 2 个主题。我们在 themes.xml
中用 AppTheme.White
和 AppTheme.Black
定义了它。
我们知道错误出在我们的 MainActivity
代码中的某个地方。如果我们在设置弹出窗口中按下 Darkmode 开关,开关将被触发,但主题不会改变。我们在我们的 TestApp 中单独尝试过它,问题不在于颜色或布局管理。我们很确定我们的 setOnCheckedChangeListener
方法出了问题。谢谢您的帮助!仅供参考:应用程序不会崩溃。
出现此错误:
W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Switch.setOnCheckedChangeListener(android.widget.CompoundButton$OnCheckedChangeListener)' on a null object reference
at com.example.LulusApp.BaseActivity.onOptionsItemSelected(BaseActivity.java:203)
at android.app.Activity.onMenuItemSelected(Activity.java:3543)
at androidx.fragment.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:383)
at androidx.appcompat.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:228)
at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
at androidx.appcompat.app.ToolbarActionBar.onMenuItemClick(ToolbarActionBar.java:65)
at androidx.appcompat.widget.Toolbar.onMenuItemClick(Toolbar.java:207)
at androidx.appcompat.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:779)
at androidx.appcompat.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:834)
at androidx.appcompat.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:158)
这是我们的 MainActivity.class
,其中包含一个弹出式窗口 Window:
private final static int THEME_WHITE = 1;
private final static int THEME_BLACK = 2;
public void updateTheme() {
if (Utility.getTheme(getApplicationContext()) <= THEME_WHITE) {
setTheme(R.style.AppTheme_White);
} else if (Utility.getTheme(getApplicationContext()) == THEME_BLACK) {
setTheme(R.style.AppTheme_Black);
}
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int dot_menu_items = item.getItemId();
if (dot_menu_items == R.id.action_about) {
setFragment(aboutFragment);
return true;
} else if (dot_menu_items == R.id.action_settings) {
dialogBuilder = new AlertDialog.Builder(this);
View settingsView = getLayoutInflater().inflate(R.layout.settings_popup, null);
settingsView.setClipToOutline(true);
dialogBuilder.setView(settingsView);
dialog = dialogBuilder.create();
dialog.show();
try {
Switch darkmodeSwitch = (Switch) findViewById(R.id.darkmode_switch_popup);
int getcurrentmode = Utility.getTheme(getApplicationContext());
if (getcurrentmode == 2) {
darkmodeSwitch.setChecked(true);
}
darkmodeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (isChecked) {
Utility.setTheme(getApplicationContext(), 2);
} else {
Utility.setTheme(getApplicationContext(), 1);
}
recreateActivity();
}
});
}catch (Exception e){
e.printStackTrace();
}
return true;
} else if (dot_menu_items == R.id.action_premium) {
return true;
}
return super.onOptionsItemSelected(item);
}
这里是我们的 settings_popup.xml
:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorPrimary"
android:layout_gravity="center"
tools:context=".BaseActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="500dp"
android:background="#7845ff">
<Switch
android:id="@+id/darkmode_switch_popup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="50px"
android:background="#032342"
android:padding="50px"
android:text="Darkmode"
android:textColor="?attr/colorPrimary"
android:textSize="18sp"
tools:ignore="UseSwitchCompatOrMaterialXml" />
</LinearLayout>
</FrameLayout>
我们还为 sharedPreferences
定义了一个 Utility.java
来保存更改的设置:
public class Utility {
public static void setTheme(Context context, int theme) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putInt(context.getString(R.string.prefs_theme_key), theme).apply();
}
public static int getTheme(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getInt(context.getString(R.string.prefs_theme_key), 1);
}
}
这里还有我们的 themes.xml
:
<resources>
<style name="AppTheme.White" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/primaryColor_white</item>
<item name="colorPrimaryDark">@color/primaryColorDark_white</item>
<item name="colorAccent">@color/primaryAccent_white</item>
<item name="backgroundColor">@color/primaryColorDark_white</item>
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<style name="AppTheme.Black" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/primaryColor_black</item>
<item name="colorPrimaryDark">@color/primaryColorDark_black</item>
<item name="colorAccent">@color/primaryAccent_black</item>
<item name="backgroundColor">@color/primaryColorDark_black</item>
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">@android:anim/fade_in</item>
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
</style>
</resources>
我们还在 colors.xml
:
中为我们的主题定义了颜色
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primaryColor_white">#6002ee</color>
<color name="primaryColorDark_white">#FFFFFF</color>
<color name="primaryAccent_white">#76FF03</color>
<color name="primaryColor_black">#FFFFFF</color>
<color name="primaryColorDark_black">#6002ee</color>
<color name="primaryAccent_black">#121212</color>
</resources>
我们的主题定义在我们的 manifest.xml
:
android:theme="@style/AppTheme.White">
您收到此错误是因为您从 activity 访问了 Switch,但它在对话框视图中用于修复,您只需要更改此行
Switch darkmodeSwitch = findViewById(R.id.darkmode_switch_popup);
通过这个:
Switch darkmodeSwitch = settingsView.findViewById(R.id.darkmode_switch_popup);
我们的应用程序将 运行 有 2 个主题。我们在 themes.xml
中用 AppTheme.White
和 AppTheme.Black
定义了它。
我们知道错误出在我们的 MainActivity
代码中的某个地方。如果我们在设置弹出窗口中按下 Darkmode 开关,开关将被触发,但主题不会改变。我们在我们的 TestApp 中单独尝试过它,问题不在于颜色或布局管理。我们很确定我们的 setOnCheckedChangeListener
方法出了问题。谢谢您的帮助!仅供参考:应用程序不会崩溃。
出现此错误:
W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Switch.setOnCheckedChangeListener(android.widget.CompoundButton$OnCheckedChangeListener)' on a null object reference
at com.example.LulusApp.BaseActivity.onOptionsItemSelected(BaseActivity.java:203)
at android.app.Activity.onMenuItemSelected(Activity.java:3543)
at androidx.fragment.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:383)
at androidx.appcompat.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:228)
at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
at androidx.appcompat.app.ToolbarActionBar.onMenuItemClick(ToolbarActionBar.java:65)
at androidx.appcompat.widget.Toolbar.onMenuItemClick(Toolbar.java:207)
at androidx.appcompat.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:779)
at androidx.appcompat.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:834)
at androidx.appcompat.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:158)
这是我们的 MainActivity.class
,其中包含一个弹出式窗口 Window:
private final static int THEME_WHITE = 1;
private final static int THEME_BLACK = 2;
public void updateTheme() {
if (Utility.getTheme(getApplicationContext()) <= THEME_WHITE) {
setTheme(R.style.AppTheme_White);
} else if (Utility.getTheme(getApplicationContext()) == THEME_BLACK) {
setTheme(R.style.AppTheme_Black);
}
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int dot_menu_items = item.getItemId();
if (dot_menu_items == R.id.action_about) {
setFragment(aboutFragment);
return true;
} else if (dot_menu_items == R.id.action_settings) {
dialogBuilder = new AlertDialog.Builder(this);
View settingsView = getLayoutInflater().inflate(R.layout.settings_popup, null);
settingsView.setClipToOutline(true);
dialogBuilder.setView(settingsView);
dialog = dialogBuilder.create();
dialog.show();
try {
Switch darkmodeSwitch = (Switch) findViewById(R.id.darkmode_switch_popup);
int getcurrentmode = Utility.getTheme(getApplicationContext());
if (getcurrentmode == 2) {
darkmodeSwitch.setChecked(true);
}
darkmodeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if (isChecked) {
Utility.setTheme(getApplicationContext(), 2);
} else {
Utility.setTheme(getApplicationContext(), 1);
}
recreateActivity();
}
});
}catch (Exception e){
e.printStackTrace();
}
return true;
} else if (dot_menu_items == R.id.action_premium) {
return true;
}
return super.onOptionsItemSelected(item);
}
这里是我们的 settings_popup.xml
:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorPrimary"
android:layout_gravity="center"
tools:context=".BaseActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="500dp"
android:background="#7845ff">
<Switch
android:id="@+id/darkmode_switch_popup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="50px"
android:background="#032342"
android:padding="50px"
android:text="Darkmode"
android:textColor="?attr/colorPrimary"
android:textSize="18sp"
tools:ignore="UseSwitchCompatOrMaterialXml" />
</LinearLayout>
</FrameLayout>
我们还为 sharedPreferences
定义了一个 Utility.java
来保存更改的设置:
public class Utility {
public static void setTheme(Context context, int theme) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putInt(context.getString(R.string.prefs_theme_key), theme).apply();
}
public static int getTheme(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getInt(context.getString(R.string.prefs_theme_key), 1);
}
}
这里还有我们的 themes.xml
:
<resources>
<style name="AppTheme.White" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/primaryColor_white</item>
<item name="colorPrimaryDark">@color/primaryColorDark_white</item>
<item name="colorAccent">@color/primaryAccent_white</item>
<item name="backgroundColor">@color/primaryColorDark_white</item>
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<style name="AppTheme.Black" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/primaryColor_black</item>
<item name="colorPrimaryDark">@color/primaryColorDark_black</item>
<item name="colorAccent">@color/primaryAccent_black</item>
<item name="backgroundColor">@color/primaryColorDark_black</item>
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">@android:anim/fade_in</item>
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
</style>
</resources>
我们还在 colors.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primaryColor_white">#6002ee</color>
<color name="primaryColorDark_white">#FFFFFF</color>
<color name="primaryAccent_white">#76FF03</color>
<color name="primaryColor_black">#FFFFFF</color>
<color name="primaryColorDark_black">#6002ee</color>
<color name="primaryAccent_black">#121212</color>
</resources>
我们的主题定义在我们的 manifest.xml
:
android:theme="@style/AppTheme.White">
您收到此错误是因为您从 activity 访问了 Switch,但它在对话框视图中用于修复,您只需要更改此行
Switch darkmodeSwitch = findViewById(R.id.darkmode_switch_popup);
通过这个:
Switch darkmodeSwitch = settingsView.findViewById(R.id.darkmode_switch_popup);