Computer >> Hướng Dẫn Máy Tính >  >> Xử Lý Sự Cố >> Android

Cách thêm Dark Theme vào Android App

Đối với developer, tạo app Android là quá trình dễ dàng - thiết kế UI hấp dẫn mới là khó khăn. Đó là lý do chúng tôi viết hướng dẫn "Thiết kế UI Android App không xấu xí", cho developer cần cảm hứng tạo UI đơn giản nhưng thu hút. Trong hướng dẫn đó chúng tôi nhắc ngắn gọn thêm dark/night mode, và bài này sẽ hướng dẫn chi tiết.

Thêm dark/night mode toggle vào app là tùy chọn tuyệt vời cho user - tiết kiệm pin, dễ chịu cho mắt ban đêm. Background trắng chữ đen, hoặc tổ hợp màu "sáng" trong UI rất mỏi mắt, nhất là ban đêm. Do đó background tối với chữ sáng ít hại mắt hơn, đây là lý do nhiều app phổ biến thêm dark theme - YouTube và Reddit gần đây, dù Facebook vẫn chưa ra mắt sau khi hứa tháng 5.

Nếu muốn dễ dàng thêm dark mode toggle vào Android app, hãy làm theo hướng dẫn Appuals này và comment nếu gặp vấn đề!

Tạo XML Attributes

Đầu tiên cần tạo file XML attributes xử lý theming. Cách này tốt hơn đưa 2 bộ resource vào APK cho 2 theme (làm phồng APK), vì Android có thể thay đổi màu gốc qua attribute XML này.

Trong thư mục 'resources' của app, tạo file attrs.xml thêm các dòng (đây là 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>

Trước Lollipop không thể chỉ định attribute cho drawable, phải chỉ resource ID cho drawable - tuy nhiên, giờ không còn trường hợp đó.

Thêm Styles

Để hoạt động, cần tạo 2 style riêng biệt chia sẻ cùng base. Style đầu là theme 'light' chính, thứ hai là theme 'dark'.

<!-- 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>

Đây là style thực tế cho activity cụ thể:

<!-- 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>

Cần chỉ định một theme này vào Manifest cho activity của app, trong trường hợp này là FeedActivity.

Styling Views

Ví dụ styling views - trong trường hợp này cho lỗi redirect "Page not found".

<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" />

Cách bật Dynamic Theme Switching

Cách tốt nhất và hiệu quả nhất để bật chuyển theme động là load giá trị SharedPreference (dùng lưu setting) vào Application instance dùng pattern Singleton, nghĩa là không phải làm ở đầu mỗi Activity.

public class App extends Application {
public static final String TAG = "App";
private boolean isNightModeEnabled = false;
@Override
public void onCreate() {
super.onCreate();
// Load Night Mode state ở đây
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;
}
}

Vì instance này launch trước mọi thứ, nó cho phép gọi isNightModeEnabled() Boolean bất cứ khi nào, ở bất kỳ activity nào thuộc app sau khi mở.

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);
}
}

Tuy nhiên, nếu muốn áp dụng theme khác từ theme chỉ định trong manifest, nó phải làm trước gọi parent onCreate().

Set State dùng AppCompat

AppCompat hữu ích cho nhiều việc, ở đây dùng để set mode state. Nghĩa là không còn cần dùng app instance tạo cached state, giảm app cache bloat (dù chỉ chút xíu).

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

Ở đây, bạn có thể dùng:

  • AppCompatDelegate.MODE_NIGHT_YES
  • AppCompatDelegate.MODE_NIGHT_NO
  • AppCompatDelegate.MODE_NIGHT_AUTO

Lấy State

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);
}
}

Đó là xong - bạn có thể tiếp tục tùy chỉnh giá trị theo ý thích, nhưng hướng dẫn này là giới thiệu tuyệt vời để bắt đầu thêm native dark theme vào Android app.