Principles of Style/Theme in Andriod and analysis of Activity interface file selection process

Source: Internet
Author: User

Principles of Style/Theme in Andriod and analysis of Activity interface file selection process

By studying the previous blog post <start with setContentView ()>, we have mastered the process of creating the layout file of the Activity component and

Its top-level control, DecorView, continues to explore the generateLayout () method:

1. system definition and usage of Theme in Activity;

2. How to select an appropriate layout File Based on the configured Feature (attribute.

In addition, the Theme and Style concepts are briefly described below:

BothLet's take a look at another Theme. NoTitleBar attribute definition in Android, which inherits the "Theme" set by default.

True

 

In fact, any elements (including attributes) declared in the xml file must obtain their values through code and perform proper logical operations. So

Where does the system parse these Window attributes and select an appropriate layout file?

Ii. parsing Theme and selecting layout files

If you are not familiar with the setContentView () call process, you can first read the previous blog article <start with setContentView ()>.

Today, we will go deep into the generateLayout () method. The main function of this method is to parse these Window attributes and then select the appropriate

The layout file carries the layout file as our Activity or Window interface, that is, the direct sub-View of DecorView.

 

Before specific analysis, Android also provides two simple APIs for us to define the interface style, as shown in the following two methods:

1. requestFeature () sets the style Feature of the interface. For example, FEATURE_NO_TITLE (no title ),

FEATURE_PROGRESS (the title bar has a progress bar ). It must be called before setContentView (); otherwise, an exception is reported.

The FEATURE attribute is defined in the Window. java class.

2. getWindow (). setFlags () to add some flags for the current WindowManager. LayoutParams.

The Flag is defined in the WindowManager. LayoutParams. java class.


The following example shows how to hide the status bar and title bar:

 

@ Override publicvoidonCreate (BundlesavedInstanceState) {super. onCreate (savedInstanceState); // hidetitlebarofapplication // mustbeforesettingthelayout requestWindowFeature (Window. FEATURE_NO_TITLE); // hidestatusbarofAndroid // couldalsobedonelater getWindow (). setFlags (WindowManager. layoutParams. FLAG_FULLSCREEN, WindowManager. layoutParams. FLAG_FULLSCREEN); setContentView (R. layout. main);} complete example, as shown in blog

Source code analysis:

These two methods are implemented in the Window. java class, as follows:

PublicclassWindow {/** Flagforthe "optionspanel" feature. thisisenabledbydefault. */publicstaticfinalintFEATURE_OPTIONS_PANEL = 0;/** Flagforthe "notitle" feature, turningoffthetitleatthetop * ofthescreen. */progress = 1;/** Flagfortheprogressindicatorfeature */publicstaticfinalintFEATURE_PROGRESS = 2;/** progress */progress = 3;/** progress */progress = 4; /** Flagforindeterminateprogress */publicstaticfinalintFEATURE_INDETERMINATE_PROGRESS = 5;/** Flagforthecontextmenu. thisisenabledbydefault. */publicstaticfinalintFEATURE_CONTEXT_MENU = 6; // menu/** Flagforcustomtitle. youcannotcombinethisfeaturewithothertitlefeatures. */publicstaticfinalintFEATURE_CUSTOM_TITLE = 7; // default FEATURESFEATURE_OPTIONS_PANEL & FEATURE_CONTEXT_MENU protectedstaticfinalintDEFAULT_FEATURES = (1 < Notethatsomeflagsmustbesetbeforethewindowdecorationis

 

* Created. * Thesewillbesetforyoubasedonthe {@ linkandroid. r. attr # windowIsFloating} * attribute. * @ paramflagsThenewwindowflags (seeWindowManager. layoutParams ). * @ parammaskWhichofthewindowflagbitstomodify. * /// mask indicates the corresponding mask. When setting the corresponding bit, you need to clear the mask of the corresponding bit before performing or operations. Similar functions can be found in View. java setFlags () method publicvoidsetFlags (intflags, intmask) {finalWindowManager. layoutParamsattrs = getAttributes (); // The current WindowManager. layoutParams property // Add the configured flags to the attrs property. flags = (attrs. flags &~ Mask) | (flags & mask); mForcedWindowFlags | = mask; if (mCallback! = Null) {// Activity and Dialog implement the Window. Callback interface mCallback. ondeskwattributeschanged (attrs) by default; // Callback ondeskwattributeschanged () method }}...}

 

In fact, it is quite simple, mainly for logical operators.
MFeatures indicates the Feature value of the current Window.
Flags are saved in the current WindowManager. LayoutParams. flag attribute.

 

Next, we will analyze the generateLayout () method in detail.

If the current interface's DecorView object is empty (usually called by setContentView () or addContentView (),

The DecorView object and the corresponding mContentParent object that loads the xml layout.

Step 1. Create a DecorView object

PrivatevoidinstallDecor () {if (mDecor = null) {mDecor = generateDecor (); // create a DecorView object mDecor. setDescendantFocusability (ViewGroup. FOCUS_AFTER_DESCENDANTS); // sets the focus capture action} if (mContentParent = null) {// mContentParent serves as the Parent of our custom layout. mContentParent = generateLayout (mDecor); // create mContentParent. ...}}
Step 2. Create an mContentParent object

 

 

ProtectedViewGroupgenerateLayout (DecorViewdecor) {// Applydatafromcurrenttheme. typedArraya = getWindowStyle (); // obtain the TypedArray object corresponding to the current Theme attribute. // The next step is to get the Attribute value ..., subsequent analysis // whether the interface is a Dialog style, android: sharewisfloating attribute mIsFloating =. getBoolean (com. android. internal. r. styleable. window_windowIsFloating, false );...}

 

First, obtain the TypeArray object corresponding to the System-defined Style, and then obtain the corresponding property value. Continue to analyze getWindowStyle ()

Method.

2.1,

/*** Returnthe {@ linkandroid. r. styleable # Window} attributesfromthis * window 'stheme. */publicfinalTypedArraygetWindowStyle () {synchronized (this) {if (mWindowStyle = null) {// call the corresponding method of the Context class and return the corresponding TypedArray object, the parameter is the custom property set mWindowStyle = mContext. obtainStyledAttributes (com. android. internal. r. styleable. window) ;}returnmwindowstyle ;}call the obtainStyledAttributes () method corresponding to the Context class. The parameter passes the set of custom properties corresponding to the Window.

2.2,

/*** RetrievestyledattributeinformationinthisContext 'stheme. see * {@ linkResources. theme # obtainStyledAttributes (int [])} * formoreinformation. ** @ seeResources. theme # obtainStyledAttributes (int []) */publicfinalTypedArrayobtainStyledAttributes (int [] attrs) {// obtain the TypedArray object returngetTheme () corresponding to the current Theme first (). obtainStyledAttributes (attrs);} since the Activity inherits from the ContextThemeWapprer class, ContextThemeWapprer overrides the getTheme () method.

2.3

 

@ Override publicResources. ThemegetTheme () {if (mTheme! = Null) {// during the first access, the mTheme object is null returnmTheme;} // whether the Theme resource has been specified. The default Theme if (mThemeResource = 0) is not selected) {mThemeResource = com. android. internal. r. style. theme;} initializeTheme (); // initialize Theme resource returnmTheme;} First, determine whether the method is called for the first time, that is, whether the mTheme object is created;

 

Second, determine whether the resource ID corresponding to the Theme is set. If not, select the default theme style.

Com. android. internal. R. style. Theme.

Finally, initialize the corresponding resource.

 

/*** Calledby {@ link # setTheme} and {@ link # getTheme} toapplyatheme * resourcetothecurrentThemeobject. canoverridetochangethe * default (simple) behavior. thismethodwillnotbecalledinmultiple * threadssimultaneously. ** @ paramthemeTheThemeobjectbeingmodified. * @ paramresidThethemestyleresourcebeingappliedto Theme. * @ ParamfirstSettotrueifthisisthefirsttimeastyleisbeing * appliedto Theme. */ProtectedvoidonApplyThemeResource (Resources. themetheme, intresid, booleanfirst) {theme. applyStyle (resid, true);} privatevoidinitializeTheme () {finalbooleanfirst = mTheme = null; // whether it is the first call if (first) {mTheme = getResources (). newTheme (); Resources. themetheme = mBase. getTheme (); // call getTheme () of the ContextImpl class to obtain the default Theme if (theme! = Null) {thinkeme. setTo (theme); // apply theme configuration to the attributes of the thinkeme} onApplyThemeResource (thinkeme, thinkemeresource, first );}

 

If you have not manually set the mThemeResource, select the default Theme provided for us in the system. You can also set Theme manually.

Resource, as described in the beginning.

Method 1: Call the setTheme () method in the Activity. This method is implemented in the ContextThemeWrapper. java class.

 

@ Override publicvoidsetTheme (intresid) {mThemeResource = resid; // you can specify the initializeTheme ();}

 

Method 2: In the AndroidManifest file, configure the android: theme attribute for the Activity node. When you start

The setTheme () method is called during Activity. File Path: frameworks \ base \ core \ java \ android \ app \ ActivityThread. java

 

Privatefinalactivityjavasmlaunchactivity (ActivityClientRecordr, IntentcustomIntent ){... activityactivity = null; try {// create Activity instance java. lang. classLoadercl = r. packageInfo. getClassLoader (); activity = mInstrumentation. newActivity (cl, component. getClassName (), r. intent );}... try {... if (activity! = Null) {// create the corresponding information. contextImplappContext = newContextImpl (); appContext. init (r. packageInfo, r. token, this); appContext. setOuterContext (activity); CharSequencetitle = r. activityInfo. loadLabel (appContext. getPackageManager ());... activity. attach (appContext, this, getInstrumentation (), r. token, r. ident, app, r. intent, r. activityInfo, title, r. parent, r. embeddedID, r. lastNonConfigurationInstance, r. lastnongateati OnChildInstances, config);... // activityInfo information is called by ActivityManagerService through IPC. // you can refer to the ActivityInfo API of AndroidSDK. Inttheme = r. activityInfo. getThemeResource (); if (theme! = 0) {activity. setTheme (theme); // call the setTheme () method. For details, see method 1}... returnactivity ;}
Summary: If Theme Resource is not set, the default Theme Style is selected. Otherwise, the Theme we set is selected.

 

Because the mTheme object is relatively uniform, but every time you apply a new Style ID, it feels that the Android framework

The application resources form a unified resource library. All styles defined by the application are stored in the resource library.

ID value display to obtain the corresponding value set. However, we do not know how to obtain resources from the system.

Obtain the corresponding resource or even a group of resources. But fortunately, Lao Luo is currently studying this topic, hoping to find the answer in Lao Luo's article.

Visible <

Android Resource Management Framework (Asset Manager) brief introduction and learning plan>

In addition, the Dialog constructor is also enlightening. It creates a ContextThemeWapper object for the specified Theme and then creates

Create the corresponding Window object. You can study the specific process on your own.

PublicDialog (Contextcontext, inttheme) {// create a ContextThemeWrapper object and specify ThemeID mContext = newContextThemeWrapper (context, theme = 0? Com. android. internal. r. style. theme_Dialog: theme); mWindowManager = (WindowManager) context. getSystemService (Context. WINDOW_SERVICE); // pass the ContextThemeWrapper object to construct the specified ID. windoww = PolicyManager. makeNewWindow (mContext );...}

PS: the default attribute after Android 4.0 is Theme_Holo. When calling related functions, the SDK will be judged

Version, and then select the corresponding Theme. Related functions: @ Resources. java

 

/** @ Hide */publicstaticintselectDefaultTheme (intcurTheme, inttargetSdkVersion) {returnselectSystemTheme (curTheme, targetSdkVersion, com. android. internal. r. style. theme, com. android. internal. r. style. theme_Holo, com. android. internal. r. style. theme_DeviceDefault);}/** @ hide */publicstaticintselectSystemTheme (intcurTheme, inttargetSdkVersion, intorig, intholo, intdeviceDefault) {// whether Theme if (curTheme! = 0) {returncurTheme;} // judge the version number. HONEYCOMB indicates Android3.0, and ICE_CREAM_SANDWICH indicates Android4.0 if (targetSdkVersion

 

 

Step 3. Through the preceding analysis, we obtain the TypeArray object corresponding to the Window attribute, and then obtain the corresponding attribute value.

The following code is used:

 

ProtectedViewGroupgenerateLayout (DecorViewdecor) {// Applydatafromcurrenttheme. typedArraya = getWindowStyle (); // obtain the TypedArray object corresponding to the current Theme attribute. // whether the interface is a Dialog style. android: Invalid wisfloating attribute mIsFloating =. getBoolean (com. android. internal. r. styleable. window_appswisfloating, false); intflagsToUpdate = (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR )&(~ GetForcedWindowFlags (); // if it is a dicedstyle, set the width and height values of the current WindowManager. LayoutParams to indicate that the page size is specified by the layout file size. // Because of the default WindowManager. the width and height of LayoutParams are MATCH_PARENT, which is consistent with the screen size. if (mIsFloating) {setLayout (WRAP_CONTENT, WRAP_CONTENT); setFlags (0, flagsToUpdate); // cancel tags | signature mark} else {setFlags (FLAG_LAYOUT_IN_SCREEN | tags, flagsToUpdate );} // whether there is no title bar, android: windowNoTitle attribute if (. getBoolean (com. android. internal. r. styleable. window_windowNoTitle, false) {re QuestFeature (FEATURE_NO_TITLE); // Add FEATURE_NO_TITLE} // whether it is full screen, android: windowFullscreen attribute if (. getBoolean (com. android. internal. r. styleable. window_windowFullscreen, false) {setFlags (FLAG_FULLSCREEN, FLAG_FULLSCREEN &(~ GetForcedWindowFlags ();} // whether the wallpaper is displayed. android: windowShowWallpaper attribute if (. getBoolean (com. android. internal. r. styleable. window_windowShowWallpaper, false) {setFlags (FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER &(~ GetForcedWindowFlags ();} WindowManager. LayoutParamsparams = getAttributes (); // The current WindowManager. LayoutParams object if (! HasSoftInputMode () {// whether the softInputMode mode has been set. You can use the # setSoftInputMode () method to set params. softInputMode =. getInt (com. android. internal. r. styleable. window_windowSoftInputMode, // android: windowSoftInputMode params. softInputMode); // It can be created by WindowManager. layoutParams specifies} // whether it is a child Activity of an Activity. Generally, it is not. getContainer () returns null. if (getContainer () = null) {if (mBackgroundDrawable = null) {// you have obtained the specified background image. if (mBackgroundResource = 0) {// you have obtained the specified background image resource mBackgroundResource =. getResourceId (// background image id, android: windowBackground com. android. internal. r. styleable. window_windowBackground, 0 );}}...} // Inflatethewindowdecor. intlayoutResource; intfeatures = getLocalFeatures (); // equivalent to mFeatures, set by requestFeature. if (features & (1 <

 

Extract the corresponding property values in sequence, and call different functions based on these values, such as requestFeature () and

WindowMamager. LayoutParams: Flag settings (this mask is very troublesome to implement bitwise operations. Some people know it.

You can give me some advice .) For example, if it is a dialog box window, FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR is not set.

Because it indicates the corresponding Activity window.

1. FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR indicates a typical Activity window.
2. FLAG_LAYOUT_IN_SCREEN indicates a typical full screen window.

3. Others represent other dialog box windows.

Finally, load different layout files based on the corresponding Feature value.

 

PS: Some netizens said they had canceled/hidden the ActionBar in the Forum a few days ago. In Android 4.0, an ActionBar-supported resource file

Definition: file path: frameworks \ base \ core \ res \ layout \ screen_action_bar.xml

 

Android: fitsSystemWindows = "true"> android: layout_height = "wrap_content" style = "? Android: attr/actionBarStyle ">

The specific analysis is still found in the source code of generateLayout @ PhoneWindow. java and 4.0. Is it feasible to directly set the status to gone?

 

Related Article

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.