Android peels are nothing new, and there are plenty of third-party peels and implementations. The main reasons for choosing QMUI library of Tencent to demonstrate the skin changing function of APP are as follows: 1. The realization process of skin changing function is simple and easy to understand; 2. 2. Easy to adapt to Dark Mode provided by Android 10; 3, can also whoring QMUI various components, effects (this is important, 😁 haha ~);
1. Skin changing process realization:
1.1. New construction project
Create a new empty project from AndroidStudio and add the QMUI dependency:
Implementation ‘com. Qmuiteam: qmui: 2.0.0 – alpha10’
1.2. Define attR and its implementation style (emphasis)
This step requires us to cooperate with the designer to sort out a set of colors and background resources for the App to use. Then we named it in XML as attR. This project example:
src/main/res/values/styles.xml:
<resources>
<attr name="colorPrimary" format="color" />
<attr name="colorBg1" format="color" />
<attr name="colorBg2" format="color" />
<attr name="colorBg3" format="color" />
<attr name="colorTextWhite" format="color" />
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimaryDefault</item>
<item name="colorBg1">@color/colorBgDefault1</item>
<item name="colorBg2">@color/colorBgDefault2</item>
<item name="colorBg3">@color/colorBgDefault3</item>
<item name="colorTextWhite">@color/colorTextWhite</item>
</style>
<style name="app_skin_1" parent="AppTheme">
<item name="colorPrimary">@color/colorPrimarySkin1</item>
<item name="colorBg1">@color/colorBgDefault1Skin1</item>
<item name="colorBg2">@color/colorBgDefault1Skin2</item>
<item name="colorBg3">@color/colorBgDefault1Skin3</item>
</style>
<style name="app_skin_2" parent="AppTheme">
<item name="colorPrimary">@color/colorPrimarySkin2</item>
<item name="colorBg1">@color/colorBgDefault2Skin1</item>
<item name="colorBg2">@color/colorBgDefault2Skin2</item>
<item name="colorBg3">@color/colorBgDefault2Skin3</item>
</style>
</resources>
Copy the code
src/main/res/values/colors.xml:
<? The XML version = "1.0" encoding = "utf-8"? > <resources> <color name="colorPrimaryDefault">#FCE4EC</color> <color name="colorBgDefault1">#F06292</color> <color name="colorBgDefault2">#EC407A</color> <color name="colorBgDefault3">#880E4F</color> <color name="colorTextWhite">#FFFFFF</color> <color name="colorPrimarySkin1">#E3F2FD</color> <color name="colorBgDefault1Skin1">#90CAF9</color> <color name="colorBgDefault1Skin2">#42A5F5</color> <color name="colorBgDefault1Skin3">#0D47A1</color> <color name="colorPrimarySkin2">#FAFAFA</color> <color name="colorBgDefault2Skin1">#757575</color> <color name="colorBgDefault2Skin2">#424242</color> <color name="colorBgDefault2Skin3">#212121</color> </resources>Copy the code
Style supports inheritance. For example, app_SKIN_1 inherits from AppTheme. When looking for its value via attr, if it is not found in app_SKIN_1, it will go to AppTheme. So we can use the theme of our App as one of our skins, and all other skins will inherit from this skin.
1.3 Customized skin change management
Different skins and colors of APP have been defined. We need to define a class that connects with QMUI and is used to manage these skins. The code functions include: skin loading, switching and other operations.
src/main/java/com/qxc/testandroid/QDSkinManager.java:
package com.qxc.testandroid; import android.content.Context; import android.content.res.Configuration; import com.qmuiteam.qmui.skin.QMUISkinManager; public class QDSkinManager { public static final int SKIN_DEFAULT = 1; public static final int SKIN_1 = 2; public static final int SKIN_2 = 3; public static void install(Context context) { QMUISkinManager skinManager = QMUISkinManager.defaultInstance(context); skinManager.addSkin(SKIN_DEFAULT, R.style.AppTheme); skinManager.addSkin(SKIN_1, R.style.app_skin_1); skinManager.addSkin(SKIN_2, R.style.app_skin_2); boolean isDarkMode = (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; int storeSkinIndex = QDPreferenceManager.getInstance(context).getSkinIndex(); if (isDarkMode && storeSkinIndex ! = SKIN_2) { skinManager.changeSkin(SKIN_2); } else if (! isDarkMode && storeSkinIndex == SKIN_1) { skinManager.changeSkin(SKIN_1); }else{ skinManager.changeSkin(storeSkinIndex); } } public static void changeSkin(int index) { QMUISkinManager.defaultInstance(QDApplication.getContext()).changeSkin(index); QDPreferenceManager.getInstance(QDApplication.getContext()).setSkinIndex(index); } public static int getCurrentSkin() { return QMUISkinManager.defaultInstance(QDApplication.getContext()).getCurrentSkin(); }}Copy the code
1.4. Custom skin preservation class
When we switch the skin, we need to save the switched skin information, and the next time we start the APP, we can directly load the switched skin.
src/main/java/com/qxc/testandroid/QDPreferenceManager.java:
package com.qxc.testandroid; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; public class QDPreferenceManager { private static SharedPreferences sPreferences; private static QDPreferenceManager sQDPreferenceManager = null; private static final String APP_VERSION_CODE = "app_version_code"; private static final String APP_SKIN_INDEX = "app_skin_index"; private QDPreferenceManager(Context context) { sPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); } public static final QDPreferenceManager getInstance(Context context) { if (sQDPreferenceManager == null) { sQDPreferenceManager = new QDPreferenceManager(context); } return sQDPreferenceManager; } public void setAppVersionCode(int code) { final SharedPreferences.Editor editor = sPreferences.edit(); editor.putInt(APP_VERSION_CODE, code); editor.apply(); } public void setSkinIndex(int index) { SharedPreferences.Editor editor = sPreferences.edit(); editor.putInt(APP_SKIN_INDEX, index); editor.apply(); } public int getSkinIndex() { return sPreferences.getInt(APP_SKIN_INDEX, QDSkinManager.SKIN_DEFAULT); }}Copy the code
1.5. APP loads QDSkinManager and ADAPTS dark mode
You only need to do this once. You are advised to customize the Application to implement this function.
SRC/main/Java/com/QXC/testandroid/QDApplication. Java:
package com.qxc.testandroid; import android.annotation.SuppressLint; import android.app.Application; import android.content.Context; import android.content.res.Configuration; import androidx.annotation.NonNull; public class QDApplication extends Application { @SuppressLint("StaticFieldLeak") private static Context context; public static Context getContext() { return context; } @Override public void onCreate() { super.onCreate(); context = getApplicationContext(); QDSkinManager.install(this); } @Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); UI_MODE_NIGHT_MASK == configuration. UI_MODE_NIGHT_YES) {// Modify Dark Mode if ((newconfig.uimode & configuration. UI_MODE_NIGHT_MASK) == configuration. UI_MODE_NIGHT_YES) { QDSkinManager.changeSkin(QDSkinManager.SKIN_2); } else if (QDSkinManager.getCurrentSkin() == QDSkinManager.SKIN_2) { QDSkinManager.changeSkin(QDSkinManager.SKIN_DEFAULT); }}}Copy the code
Don’t forget to specify our custom Application class in androidmanifest.xml:
<application
android:name=".QDApplication"
......
Copy the code
1.6. Start writing the Activity
Now that the basic work is done, let’s implement the defined peels. Modify the MainActivity layout file to write our UI layout:
SRC/main/res/layout/activity_main XML:
<? The XML version = "1.0" encoding = "utf-8"? > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" app:qmui_skin_background="?attr/colorPrimary" tools:context=".MainActivity"> <RelativeLayout android:id="@+id/v1" android:layout_width="match_parent" android:layout_height="50dp" app:qmui_skin_background="?attr/colorBg2" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="16sp" android:text="Title Bar" app:qmui_skin_text_color="?attr/colorTextWhite"/> </RelativeLayout> <RelativeLayout android:id="@+id/v2" android:layout_width="match_parent" android:layout_height="200dp" android:layout_below="@id/v1" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" app:qmui_skin_background="?attr/colorBg1" /> <com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton android:id="@+id/btn" android:layout_marginTop="10dp" android:layout_width="200dp" android:layout_height="50dp" android:layout_below="@id/v2" android:layout_centerHorizontal="true" android:gravity="center" app:qmui_radius="10dp" app:qmui_skin_background="?attr/colorBg3" app:qmui_skin_text_color="?attr/colorTextWhite" app:qmui_skin_border="?attr/colorBg2" android:text="change skin" /> </RelativeLayout>Copy the code
Note: To achieve skin, we set the color of the control using the skin properties provided by QMUI:
app:qmui_skin_xxx
Copy the code
QMUI’s official website has provided the following skin changing attributes for our use, which can meet the needs of conventional development, as shown in the picture below:
Now, let’s write the Activity code. In an Activity, we need to register with QMUISkinManager in order for the Activity to enjoy the skin function (note: In real development, if all the pages of the APP need to support peels, we try to write the registration of QMUISkinManager in BaseActivity.
There are two schemes to implement registration:
Plan 1:
We can inherit QMUIFragmentActivity or QMUIActivity from the Activity class to inject QMUISkinManager by default
Option 2 (To make it clear how to register, we choose this option. Don’t worry, it’s really easy) :
We implement the registration and unregistration of QMUISkinManager ourselves
package com.qxc.testandroid; import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import androidx.core.view.LayoutInflaterCompat; import com.qmuiteam.qmui.skin.QMUISkinLayoutInflaterFactory; import com.qmuiteam.qmui.skin.QMUISkinManager; public class MainActivity extends Activity { private QMUISkinManager skinManager; private Button btn; private int skinIndex; @ Override protected void onCreate (Bundle savedInstanceState) {/ / using QMUISkinLayoutInflaterFactory LayoutInflater layoutInflater = LayoutInflater.from(this); LayoutInflaterCompat.setFactory2(layoutInflater, new QMUISkinLayoutInflaterFactory(this, layoutInflater)); super.onCreate(savedInstanceState); . / / injection QMUISkinManager skinManager = QMUISkinManager defaultInstance (this); setContentView(R.layout.activity_main); initView(); initEvent(); } private void initView(){ btn = findViewById(R.id.btn); } private void initEvent(){// skinIndex = qdSkinManager.skin_default; btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(skinIndex + 1 > 3){ skinIndex = 0; } skinIndex += 1; QDSkinManager.changeSkin(skinIndex); }}); } @Override protected void onPause() { super.onPause(); } @Override public void onStart() { super.onStart(); QDSkinManager if(skinManager! = null){ skinManager.register(this); } } @Override protected void onStop() { super.onStop(); QDSkinManager if(skinManager! = null){ skinManager.unRegister(this); } } @Override protected void onResume() { super.onResume(); } @Override protected void onDestroy() { super.onDestroy(); }}Copy the code
At this point, the coding is over.
2. Knowledge development
QMUI Peels provide apis:
- QMUISkinManager: Stores the skin color configuration and distributes the current skin color to the activities, fragments, Dialogs, and popupWindows it manages. It is obtained via qmuiskinManager.of (name, context) and can be multi-instance. Therefore, an App can perform different skin changing management in different scenarios, such as skin changing of reading product readers and differentiated management of uiMode switching of other business modules.
- QMUISkinValueBuilder: Skin configuration to build a View instance (textColor, Background, border, separator, etc.)
- QMUISkinHelper: Method, some auxiliary tools. The most commonly used for QMUISkinHelper setSkinValue (View, QMUISkinValueBuilder), apply QMUISkinValueBuilder configuration to a View instance. If you’re using Kotlin, View. Skin {… } to configure the View instance.
- QMUISkinLayoutInflaterFactory: avi configuration items used to support XML parsing.
- IQMUISkinDispatchInterceptor: View can be realized through it, to intercept skin changes.
- IQMUISkinHandlerView: Views can implement this to completely customize the handling of different skins.
- IQMUISkinDefaultAttrProvider: View can be realized by it, provide the View the default default configuration, skinning support from the component level.
At the end of the article
Your likes collection is the biggest encouragement to me! Welcome to pay attention to my simple book, share Android dry goods, exchange Android technology. If you have any comments or technical questions about this article, please leave a comment in the comments section.
This article is from juejin.cn/post/703848… , if there is infringement, please contact to delete.