Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีเปลี่ยน Theme ระหว่างรันโปรแกรม (Runtime) ใน Android

ภาพรวม

ตัวอย่างนี้แสดงวิธีเปลี่ยน Theme ของ Activity ขณะรันโปรแกรม โดยใช้ setTheme() **ก่อน** setContentView()

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

Android Studio → File → New Project

ขั้นตอนที่ 2: Layout (res/layout/activity_main.xml)

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Hello World!"
        android:textSize="24sp"/>

</RelativeLayout>

ขั้นตอนที่ 3: MainActivity.java (เปลี่ยน Theme ใน onCreate)

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // สำคัญ: ต้องเรียก setTheme() ก่อน super.onCreate() และ setContentView()
        setTheme(android.R.style.Theme_Black); // ใช้ System Theme

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

ขั้นตอนที่ 4: Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="app.com.sample">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

การทดสอบ

รันแอป - จะแสดง Theme สีดำ (Theme_Black) แทน Theme เริ่มต้น

⚠️ ข้อจำกัดสำคัญ

  • ต้องเรียก setTheme() ก่อน super.onCreate() และ setContentView() - เรียกหลังจะไม่มีผล
  • เปลี่ยน Theme ได้เฉพาะ Activity นั้นๆ ไม่ใช่ Whole App
  • ไม่สามารถเปลี่ยน Theme หลัง setContentView() แล้ว (ต้อง Recreate)

วิธีเปลี่ยน Theme ทั้งแอป (App-wide Theme Change)

ต้อง Recreate Activity ทั้งหมด หรือ Restart App:

1. ใช้ SharedPreferences เก็บ Theme Preference

// ThemeHelper.java
public class ThemeHelper {
    private static final String PREF_THEME = "theme_pref";
    private static final String KEY_THEME = "theme";

    public static void setTheme(Context context, int themeResId) {
        context.getSharedPreferences(PREF_THEME, Context.MODE_PRIVATE)
                .edit().putInt(KEY_THEME, themeResId).apply();
    }

    public static int getTheme(Context context) {
        return context.getSharedPreferences(PREF_THEME, Context.MODE_PRIVATE)
                .getInt(KEY_THEME, R.style.AppTheme);
    }
}

// ใน BaseActivity (extends ทุก Activity)
@Override
protected void onCreate(Bundle savedInstanceState) {
    setTheme(ThemeHelper.getTheme(this));
    super.onCreate(savedInstanceState);
    // ...
}

// เปลี่ยน Theme
ThemeHelper.setTheme(this, R.style.DarkTheme);
recreate(); // หรือ restart App

2. ใช้ AppCompatDelegate (DayNight Mode - API 17+)

// เปลี่ยนโหมด Dark/Light ทั้งแอป
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);   // Dark
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);    // Light
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); // ตามระบบ

// ต้อง Recreate Activity เพื่อ見效果
recreate();

3. Custom Themes (Light/Dark)

<!-- res/values/themes.xml (Light) -->
<style name="Theme.MyApp.Light" parent="Theme.MaterialComponents.DayNight.Light">
    <item name="colorPrimary">@color/purple_500</item>
    <item name="colorOnPrimary">@color/white</item>
</style>

<!-- res/values-night/themes.xml (Dark) -->
<style name="Theme.MyApp.Dark" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
    <item name="colorPrimary">@color/purple_200</item>
    <item name="colorOnPrimary">@color/black</item>
</style>

System Themes ที่ใช้ได้ทันที

  • android.R.style.Theme_Black - สีดำ
  • android.R.style.Theme_Light - สีขาว
  • android.R.style.Theme_Holo - Holo (API 11+)
  • android.R.style.Theme_Material - Material (API 21+)
  • Theme.AppCompat.Light.DarkActionBar - AppCompat Light
  • Theme.AppCompat.DayNight.DarkActionBar - DayNight

สรุป

ความต้องการวิธีที่แนะนำ
เปลี่ยน Theme Activity เดียวครั้งเดียวsetTheme() ก่อน super.onCreate()
ผู้ใช้สลับ Light/Dark ได้AppCompatDelegate.setDefaultNightMode() + recreate()
Custom Theme หลายแบบSharedPreferences + BaseActivity.setTheme() + recreate()
ตาม System SettingTheme.MaterialComponents.DayNight + MODE_NIGHT_FOLLOW_SYSTEM