Overview of Android Skin-changing technology

Source: Internet
Author: User
Tags set background

Original source:

http://blog.zhaiyifan.cn/2015/09/10/Android%E6%8D%A2%E8%82%A4%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/background

Throughout the current Android app, the skin-changing requirements can be categorized as

    • Day/night Theme toggle (or other name, usually 2 sets), like a flush/optional stock/Everyday sounds, UI is represented as a switcher.

    • A variety of theme switches, usually member privileges, such as qq/qq space.

For the first, visual inspection should be done directly through the local theme, that is, all the images/colors of the resources are packaged in the APK. And for the second, it is relatively more complex, because as a kind of online services, may be on the shelves of new skin, and so many skin packs in the APK is too much volume, so the skin resources will be selected after the download, you can not directly use the Android set of theme.

Technical Solutions

Two kinds of internal resource loading scheme and dynamic download resource download. Dynamic download can be called a kind of black technology, because often need to hack the system of some methods, so in some models and new APIs may sometimes have pits, but the relative benefits are many

    • Picture/color value and other resources due to the background issued, can be updated at any time

    • APK volume reduction

    • For application developers, skin changes are almost transparent and do not need to be concerned with several sets of skins

    • Can be sold as a value-added service!!

Internal resource Loading scenarios

Internal resource loading is done via Android's own set of theme, which is much more workload relative to business development (need to define attr and theme), and different schemes are similarly settheme in baseactivity, The difference is mainly in the strategy of solving the following 2 problems:

    • How to refresh in real time after settheme without recreating the page (especially the item inside the listview).

    • Which view needs to be refreshed and refreshed (background?) Font color? ImageView's src? )。

Custom View

Multipletheme

Custom view is done in order to refresh immediately after settheme, update the page UI corresponding resources (such as TextView replace the background and text color), in the above project, the Rootview through the traversal, Settheme operations are performed on all view/viewgroup that implement Coloruiinterface, even if refreshed.

This is obviously too heavy to replace the various view/viewgroup in the application.

Manually binding view and the type of resource to be changed

Colorful

This one... Let's take a look at the usage.

Viewgroupsetter listviewsetter = new Viewgroupsetter (mnewslistview);//Bind the News_title view in the ListView item view, Modify the Text_color attribute Listviewsetter.childviewtextcolor (R.id.news_title, R.attr.text_color) when changing the skin;// Constructs a colorful object to bind the object relationship of the view to the property mcolorful = new Colorful.builder (this)  . Backgrounddrawable (R.id.root_view, R.ATTR.ROOT_VIEW_BG)  //Set the view background picture  . BackgroundColor (r.id.change_btn, R.ATTR.BTN_BG)  //Set background color  . TextColor (R.id.textview, R.attr.text_color)  . Setter (Listviewsetter)//manually set setter  . Create ();//Set text color

I just want to change the skin, but also in the activity to set their own to change which view of what properties, corresponding to which attribute? Is the cost too high? And the logic of activity can easily be messed up.

Dynamic resource Load Scheme resource replacement

Open source projects can be referenced

Androidchangeskin

Android-skin-loader

That is, the GetResource method that overrides the application, priority loading the resource bundle under the local Skin Pack folder, for performance problem, can be optimized by attribute or resource name specification (if need to change skin and start with skin_). This does not add extra overhead to non-skinning resources.

You can focus on the skininflaterfactory and Skinmanager in the project (implementing your own GetColor, getdrawable method).

However, due to the Android 5.1 source code, the implementation of the Getdrawable method has been modified, so it will lead to the problem of no skin (in fact, the loaddrawable has been modified, even the parameters are changed, similar internal API changed a lot on 5.1).

4.4 of the source code in Resources.java:

Public drawable getdrawable (int id) throws Notfoundexception {Typedvalue value;    Synchronized (maccesslock) {value = Mtmpvalue;    if (value = = null) {value = new typedvalue ();    } else {mtmpvalue = null;  } getValue (ID, value, true);  }//actual resource loaded by loaddrawable method drawable res = loaddrawable (value, id);    Synchronized (Maccesslock) {if (Mtmpvalue = = null) {Mtmpvalue = value; }} return res;} Loaddrawable will go to preload's longsparsearray inside find/*package*/drawable loaddrawable (typedvalue value, int id) throws NotFoun  dexception {if (trace_for_preload) {//LOG only Framework resources if (id >>> + = 0x1) {final      String name = Getresourcename (ID);    if (name = null) ANDROID.UTIL.LOG.D ("Preloaddrawable", name);  }} Boolean iscolordrawable = false;    if (Value.Type >= typedvalue.type_first_color_int && value.type <= typedvalue.type_last_color_int) {  Iscolordrawable = true; } final Long key = IscolordrAwable? Value.data: (((long) Value.assetcookie) << 32) |  Value.data;  Drawable dr = Getcacheddrawable (iscolordrawable, Mcolordrawablecache:mdrawablecache, key);  if (dr! = null) {return DR; } ... return Dr;

And in the 5.1 code Resources.java:

As you can see, the method parameter is added with Themepublic drawable getdrawable (int id, @Nullable Theme Theme) throws notfoundexception {Typedvalue va  Lue    Synchronized (maccesslock) {value = Mtmpvalue;    if (value = = null) {value = new typedvalue ();    } else {mtmpvalue = null;  } getValue (ID, value, true);  Final drawable res = loaddrawable (value, ID, theme);    Synchronized (Maccesslock) {if (Mtmpvalue = = null) {Mtmpvalue = value; }} return res;} /*package*/drawable loaddrawable (typedvalue value, int ID, Theme Theme) throws Notfoundexception {if (trace_for_preload       {//LOG only Framework resources if ((id >>>) = = 0x1) {final String name = Getresourcename (ID);      if (name = null) {LOG.D ("preloaddrawable", name);  }}} final Boolean iscolordrawable;  Final arraymap<string, longsparsearray<weakreference<constantstate>>> caches;  Final long Key; if (Value.Type >= typedvalue.type_first_color_int &AMP;&Amp    Value.Type <= typedvalue.type_last_color_int) {iscolordrawable = true;    caches = Mcolordrawablecache;  key = Value.data;    } else {iscolordrawable = false;    caches = Mdrawablecache; Key = (((long) Value.assetcookie) << 32) |  Value.data;  }//First, check whether we have a cached version of this drawable//that is inflated against the specified theme.    if (!mpreloading) {final drawable cacheddrawable = getcacheddrawable (caches, key, theme);    if (cacheddrawable! = null) {return cacheddrawable; }  }

The name of the method is changed.

Hack Resources Internally

The black technology method directly hack,resources.java the Resources:

Information about preloaded resources.  Note that they is not//protected by a lock, because when preloading in zygote we is all//single-threaded, and after T Hat these is immutable.private static final longsparsearray<drawable.constantstate>[] Spreloadeddrawables; private static final longsparsearray<drawable.constantstate> spreloadedcolordrawables        = new Longsparsearray<drawable.constantstate> ();p rivate static final longsparsearray<colorstatelist> Spreloadedcolorstatelists        = new longsparsearray<colorstatelist> ();

Replace these three longsparsearray directly in the resources, because the APK runtime resource is loaded from these three arrays, so as long as the Interceptor mode is used:

public class Drawablepreloadinterceptor extends longsparsearray<drawable.constantstate>

Self-realization of a longsparsearray, and through the reflection set back, you can achieve the skin, specific getdrawable and other methods are how to take the preload array, you can see the source of Resources.

Wait, is that so easy? , NONO, juvenile you are too naïve, how to load xml,9patch padding How to update, how to pack/load Custom skin pack, drawable state How to refresh, and so on. These are all you need to consider, in the presence of plug-ins in the app, you also need to consider whether to overwrite each other resource ID problem, and then need to modify APT, the resource ID is placed in 2 range.

Hand Q and independent version of the QQ space is the use of this scheme, the effect is very good.

Summarize

Although the dynamic load scheme compares black technology, it may be problematic due to changes in the system API, but the relative

Benefits are

    • High flexibility to update skin packs at any time in the background

    • Relatively transparent, developers almost do not care about a few sets of skin, do not have to define a variety of theme and attr, even the package of skin bags-can be given to the design or special students

    • APK Volume savings

      Problems that exist

    • Without a well-developed open source project, if we take the second scenario of dynamic loading, the required project features include:

    • Custom Skin Pack Structure

    • Skin-changing engine, load skins pack resources and load, refresh in real time.

    • Skin Pack Packaging Tools

    • Compatibility with all types of ROMs

If there is such a project, once and for all, interested students can contact, we have to engage in a.

The internal loading scheme is similar, the main solution is the problem of instant refresh, however, from some of the current open source projects, there is still no particularly simple solution. Let me choose, I'd rather have the interface re-created, like restarting the activity, or remove all the view and add it back.

Overview of Android Skin-changing technology

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.