สำหรับนักพัฒนา การสร้างแอป Android เป็นกระบวนการง่าย - แต่การออกแบบ UI ที่ดึงดูดสายตาคือสิ่งที่ยากจริงๆ นั่นคือเหตุผลที่เราเขียนคู่มือ "How to Design an Android App UI That Doesn't Suck" สำหรับนักพัฒนาที่ต้องการแรงบันดาลใจในการสร้าง UI เรียบง่ายแต่ดูดี ในคู่มือนั้นเราได้กล่าวถึงการเพิ่ม dark/night mode theme สั้นๆ และในคู่มือนี้เราจะแนะนำทีละขั้นตอน
การเพิ่ม dark/night mode theme ให้แอปของคุณสามารถเป็นตัวเลือกที่ยอดเยี่ยมสำหรับผู้ใช้ - ประหยัดแบตเตอรี่ และอ่อนตากับตาในตอนกลางคืน พื้นหลังสีขาวกับข้อความสีดำ หรือการผสมสี 'สว่าง' ใดๆ ใน UI ของคุณ เป็นเรื่องเครียดต่อตาอย่างมาก โดยเฉพาะตอนกลางคืน ดังนั้น พื้นหลังมืดกับข้อความสว่างจึงเครียดน้อยกว่าและอันตรายต่อตาน้อยกว่า ซึ่งเป็นเหตุผลที่แอปยอดนิยมหลายตัวเริ่มรวม dark theme - YouTube และ Reddit ล่าสุด แม้ Facebook ยังไม่เผยแพร่หลังสัญญาเมื่อเดือนพฤษภาคม
หากคุณต้องการเพิ่ม dark mode ที่ toggle ได้ง่ายๆ ให้ติดตามคู่มือ Appuals นี้และคอมเมนต์หากเจอปัญหา!
การสร้าง XML Attributes
ก่อนอื่นคุณต้องสร้างไฟล์ XML attributes ที่จะจัดการ theming นี่ดีกว่าการรวมทรัพยากรสองชุดใน APK สำหรับธีมสองแบบ และทำให้ APK size ฟูขึ้น เนื่องจาก Android สามารถเปลี่ยนสีบน attributes ผ่าน XML นี้ได้โดยเนทีฟ
ดังนั้นในโฟลเดอร์ 'resources' ของแอปของคุณ สร้างไฟล์ชื่อ attrs.xml และเพิ่มบรรทัดเหล่านี้ (นี่คือ styleable attributes):
<declare-styleable name="CTAppTheme"> <attr name="primaryTextColor" format="color"/> <attr name="secondaryTextColor" format="color"/> <attr name="dividerColor" format="color"/> <attr name="backgroundCardColor" format="color"/> <attr name="iconPlaceholder" format="integer"/> </declare-styleable>
ก่อน Lollipop เราไม่สามารถระบุ attributes สำหรับ drawables ได้ จึงต้องระบุ resource IDs สำหรับ drawables - แต่ตอนนี้ไม่ใช่กรณีนั้นแล้ว
การเพิ่ม Styles
เพื่อให้ทำงาน เราต้องสร้างสอง styles แยกกันที่ share base เดียวกัน อันแรกชัดเจนคือ 'light' theme หลักของคุณ และอันที่สองคือ 'dark' theme
<!-- Light base activity theme --> <style name="ActivityTheme.Primary.Base.Light" parent="Theme.AppCompat.NoActionBar"> <item name="primaryTextColor">#F4F4F6</item> <item name="secondaryTextColor">#96F4F4F6</item> <item name="backgroundCardColor">#FFFF</item> <item name="dividerColor">#F2F2F3</item> <item name="iconPlaceholder">@drawable/i_light_plholder</item> </style> <!-- Dark base activity theme --> <style name="ActivityTheme.Primary.Base.Dark" parent="Theme.AppCompat.NoActionBar"> <item name="primaryTextColor">#33343B/item> <item name="secondaryTextColor">#8033343B</item> <item name="backgroundCardColor">#28292e</item> <item name="dividerColor">#F2F2F3</item> <item name="iconPlaceholder">@drawable/i_dark_pholder</item> </style>
นี่คือ styles จริงสำหรับ activity ที่กำหนด:
<!-- Specific Feed activity theme --> <style name="FeedActivityThemeLight" parent="ActivityTheme.Primary.Base.Light"> <item name="android:windowBackground">#F4F4F6</item> </style> <style name="FeedActivityThemeDark" parent="ActivityTheme.Primary.Base.Dark"> <item name="android:windowBackground">#33343B</item> </style>
คุณต้องระบุหนึ่งในธีมเหล่านี้ใน Manifest สำหรับ activity ของแอป ซึ่งในกรณีนี้คือ FeedActivity
การจัดสไตล์ Views
นี่คือตัวอย่างการจัดสไตล์ views ของคุณ - ในตัวอย่างนี้ เป็นสำหรับ "Page not found" redirect error
<ImageView android:id="@+id/placeHolderAssetImageView" android:layout_width="100dp" android:layout_height="100dp" android:src="?attr/iconPlaceholder" android:layout_marginBottom="8dp" /> <TextView android:id="@+id/placeHolderTitleTextView" android:text="Page not found." android:textSize="16dp" android:textColor="?attr/primaryTextColor" android:layout_margin="16dp" />
วิธีเปิดใช้งาน Dynamic Theme Switching
วิธีที่ดีที่สุดและมีประสิทธิภาพที่สุดในการเปิดใช้งาน dynamic theme switching คือการโหลดค่า SharedPreference ที่ใช้เก็บการตั้งค่า เข้าไปใน Application instance โดยใช้ Singleton pattern ซึ่งหมายความว่าเราไม่ต้องทำที่เริ่มต้นของแต่ละ Activity
public class App extends Application { public static final String TAG = "App"; private boolean isNightModeEnabled = false; @Override public void onCreate() { super.onCreate(); // We load the Night Mode state here SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this); this.isNightModeEnabled = mPrefs.getBoolean("NIGHT_MODE", false); } public boolean isNightModeEnabled() { return isNightModeEnabled; } public void setIsNightModeEnabled(boolean isNightModeEnabled) { this.isNightModeEnabled = isNightModeEnabled; } }
เนื่องจาก instance นี้ถูกเปิดก่อนอะไรก็ตาม มันช่วยให้คุณเรียก isNightModeEnabled() Boolean ได้ทุกเมื่อที่คุณต้องการ ใน activity ใดก็ตามที่เป็นของแอปหลังจากที่เปิดแล้ว
public final class FeedActivity extends AppCompatActivity { private final static String TAG = "FeedActivity"; @Override protected void onCreate(Bundle savedInstanceState) { if (MyApplication.getInstance().isNightModeEnabled()) { setTheme(R.style.FeedActivityThemeDark); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_feed); } }
อย่างไรก็ตาม หากคุณต้องการใช้ธีมที่ต่างจากที่ระบุใน manifest file มัน ต้องทำก่อน เรียก parent onCreate() method
การตั้งค่าสถานะด้วย AppCompat
AppCompat มีประโยชน์มากสำหรับหลายสิ่ง และในกรณีนี้ เราจะใช้มันเพื่อตั้งค่า mode state หมายความว่าคุณไม่ต้องใช้ app instance สร้าง cached state อีกต่อไป ดังนั้นลดการฟูของ app cache (แม้จะเพียงเล็กน้อย)
AppCompatDelegate .setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
ที่นี่ คุณสามารถใช้ได้:
- AppCompatDelegate.MODE_NIGHT_YES
AppCompatDelegate.MODE_NIGHT_NO
AppCompatDelegate.MODE_NIGHT_AUTO
การดึงสถานะ
AppCompatDelegate.getDefaultNightMode(); public final class FeedActivity extends AppCompatActivity { private final static String TAG = "FeedActivity"; @Override protected void onCreate(Bundle savedInstanceState) { if (AppCompatDelegate.getDefaultNightMode() ==AppCompatDelegate.MODE_NIGHT_YES) { setTheme(R.style.FeedActivityThemeDark); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_feed); } }
นี่ควรเป็นทั้งหมดแล้ว - คุณสามารถปรับแต่งและ tweak ค่าได้ตามใจชอบ แต่คู่มือนี้เป็นการแนะนำที่ดีมากสำหรับเริ่มต้นรวม native dark theme ในแอป Android ของคุณ