combination Mode definition :
Compose objects into the structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
Group objects into a tree structure to represent a "partial-whole" hierarchy, making users consistent in the use of individual objects and grouped objects.
as shown in the figure above (intercepted from the head Patterns), it consists of three main parts :
1. Component Abstract components. Defines the common methods and properties that participate in a grouped object, and you can define some default functions or properties.
2. Leaf leaves node. The smallest building block that makes up the combined tree.
3. Composite Branch node components. Its function is to combine the branch node and the leaf node to form a tree-shaped structure.
High-level module calls are simple. All nodes of a tree structure are component, the local and the whole are the same for the caller, no difference, so the high-level module does not care about its own processing is a single object or the entire composition structure, simplifies the high-level module code.
Increased node free expansion. Using the combination mode, if you want to add a branch node or leaf node is very simple, as long as the parent node to find it can be, very easy to expand, in line with the "open-closing principle."
One of the most widely used models. Applications in the maintenance and presentation part-the overall relationship of the scene, such as the Tree menu, folder management and so on.
In the Android source, you can find examples of using combinatorial patterns, where the viewgroup and view structure described in the Android Source Learning Observer model application is a combination pattern, as shown in the following structure:
Now let's look at how they are organized together, first in the view class, define the specific actions, then inherit the view class in the ViewGroup class, and add the associated add, delete, and find child view nodes, as follows:
Copy Code code as follows:
* @attr ref Android. R.styleable#viewgroup_clipchildren
* @attr ref Android. R.styleable#viewgroup_cliptopadding
* @attr ref Android. R.styleable#viewgroup_layoutanimation
* @attr ref Android. R.styleable#viewgroup_animationcache
* @attr ref Android. R.styleable#viewgroup_persistentdrawingcache
* @attr ref Android. R.styleable#viewgroup_alwaysdrawnwithcache
* @attr ref Android. R.styleable#viewgroup_addstatesfromchildren
* @attr ref Android. R.styleable#viewgroup_descendantfocusability
* @attr ref Android. R.styleable#viewgroup_animatelayoutchanges
*/
Public abstract class ViewGroup extends View implements Viewparent, Viewmanager {
then look at the increase in the child node function:
Copy Code code as follows:
/**
* Adds a child view. If No layout parameters are already set on the child, the
* Default parameters for this viewgroup are set on the child.
*
* @param child of child view to add
*
* @see #generateDefaultLayoutParams ()
*/
public void AddView (View child) {
AddView (Child,-1);
}
/**
* Adds a child view. If No layout parameters are already set on the child, the
* Default parameters for this viewgroup are set on the child.
*
* @param child of child view to add
* @param index the position at which to add the child
*
* @see #generateDefaultLayoutParams ()
*/
public void AddView (View child, int index) {
Layoutparams params = Child.getlayoutparams ();
if (params = = null) {
params = Generatedefaultlayoutparams ();
if (params = = null) {
throw new IllegalArgumentException ("Generatedefaultlayoutparams () cannot return null");
}
}
AddView (Child, index, params);
}
/**
* Adds A child view with this ViewGroup ' s default layout parameters and the
* Specified width and height.
*
* @param child of child view to add
*/
public void AddView (View child, int width, int height) {
Final Layoutparams params = Generatedefaultlayoutparams ();
Params.width = width;
Params.height = height;
AddView (Child,-1, params);
}
/**
* Adds A child view with the specified layout parameters.
*
* @param child of child view to add
* @param params the layout parameters to set on the child
*/
public void AddView (View child, layoutparams params) {
AddView (Child,-1, params);
}
/**
* Adds A child view with the specified layout parameters.
*
* @param child of child view to add
* @param index the position at which to add the child
* @param params the layout parameters to set on the child
*/
public void AddView (View child, int index, layoutparams params) {
if (DBG) {
System.out.println (this + "AddView");
}
Addviewinner () would call Child.requestlayout () when setting the new Layoutparams
Therefore, we call Requestlayout () in ourselves before, so this child ' s request
would be blocked at our level
Requestlayout ();
Invalidate (true);
Addviewinner (Child, index, params, false);
}
In ViewGroup we found the Add AddView () method, with the addition of child nodes, there must be a relative deletion of the child node method, and then look:
Copy Code code as follows:
public void Removeview (view view) {
Removeviewinternal (view);
Requestlayout ();
Invalidate (true);
}
/**
* Removes a view during layout. This is useful if in your onlayout () method,
* You are need to remove more views.
*
* @param view the view to remove the group
*/
public void Removeviewinlayout (view view) {
Removeviewinternal (view);
}
/**
* Removes a range of views during layout. This is useful if in your onlayout () method,
* You are need to remove more views.
*
* @param start the index of the ' the '
* @param count the number of views to remove the group
*/
public void Removeviewsinlayout (int start, int count) {
Removeviewsinternal (Start, count);
}
/**
* Removes the view at the specified position in the group.
*
* @param index The position in the group of the ' view to remove '
*/
public void Removeviewat (int index) {
Removeviewinternal (index, Getchildat (index));
Requestlayout ();
Invalidate (true);
}
/**
* Removes the specified range of views from the group.
*
* @param start the ' the ' of the ' the ' the ' range of views to remove
* @param count the number of views to remove
*/
public void removeviews (int start, int count) {
Removeviewsinternal (Start, count);
Requestlayout ();
Invalidate (true);
}
private void removeviewinternal (view view) {
Final int index = indexofchild (view);
if (index >= 0) {
Removeviewinternal (index, view);
}
}
private void removeviewinternal (int index, view view) {
if (mtransition!= null) {
Mtransition.removechild (this, view);
}
Boolean clearchildfocus = false;
if (view = = mfocused) {
View.clearfocusforremoval ();
Clearchildfocus = true;
}
if (view.getanimation ()!= null | |
(Mtransitioningviews!= null && mtransitioningviews.contains (view)) {
Adddisappearingview (view);
else if (view.mattachinfo!= null) {
View.dispatchdetachedfromwindow ();
}
onviewremoved (view);
Needglobalattributesupdate (FALSE);
Removefromarray (index);
if (Clearchildfocus) {
Clearchildfocus (view);
}
}
/**
* Sets the Layouttransition object for this viewgroup. If the Layouttransition object is
* NOT NULL, changes in layout which occur because of children being-added to or removed from
* The ViewGroup is animated according to the animations defined by that layouttransition
* object. By default, the transition object was null (so layout changes are not animated).
*
* @param transition The Layouttransition object that would animated changes in layout. A value
* of <code>null</code> means no transition would run on layout changes.
* @attr ref Android. R.styleable#viewgroup_animatelayoutchanges
*/
public void Setlayouttransition (layouttransition transition) {
if (mtransition!= null) {
Mtransition.removetransitionlistener (Mlayouttransitionlistener);
}
mtransition = transition;
if (mtransition!= null) {
Mtransition.addtransitionlistener (Mlayouttransitionlistener);
}
}
/**
* Gets the Layouttransition object for this viewgroup. If the Layouttransition object is
* NOT NULL, changes in layout which occur because of children being-added to or removed from
* The ViewGroup is animated according to the animations defined by that layouttransition
* object. By default, the transition object was null (so layout changes are not animated).
*
* @return Layouttranstion The Layouttransition object that would animated changes in layout.
* A value of <code>null</code> means no transition would run on layout changes.
*/
Public Layouttransition getlayouttransition () {
return mtransition;
}
private void removeviewsinternal (int start, int count) {
Final View focused = mfocused;
Final Boolean detach = Mattachinfo!= null;
View clearchildfocus = null;
Final view[] children = Mchildren;
Final int end = start + count;
for (int i = start; i < end; i++) {
Final view view = Children[i];
if (mtransition!= null) {
Mtransition.removechild (this, view);
}
if (view = = focused) {
View.clearfocusforremoval ();
Clearchildfocus = view;
}
if (view.getanimation ()!= null | |
(Mtransitioningviews!= null && mtransitioningviews.contains (view)) {
Adddisappearingview (view);
else if (detach) {
View.dispatchdetachedfromwindow ();
}
Needglobalattributesupdate (FALSE);
onviewremoved (view);
}
Removefromarray (Start, count);
if (Clearchildfocus!= null) {
Clearchildfocus (Clearchildfocus);
}
}
/**
* Call this method to remove the
* ViewGroup.
*/
public void Removeallviews () {
Removeallviewsinlayout ();
Requestlayout ();
Invalidate (true);
}
/**
* Called by a viewgroup subclass to remove the child views from itself,
* When it must the know it size on screen before it can calculate how many
* Child views it would render. An example is a Gallery or a ListView, which
* May "have" children, but actually only render the number of children
* That can currently fit inside the object in screen. Don't call
* This method unless your are extending viewgroup and understand the
* View measuring and layout pipeline.
*/
public void Removeallviewsinlayout () {
Final int count = Mchildrencount;
if (count <= 0) {
Return
}
Final view[] children = Mchildren;
Mchildrencount = 0;
Final View focused = mfocused;
Final Boolean detach = Mattachinfo!= null;
View clearchildfocus = null;
Needglobalattributesupdate (FALSE);
for (int i = count-1 i >= 0; i--) {
Final view view = Children[i];
if (mtransition!= null) {
Mtransition.removechild (this, view);
}
if (view = = focused) {
View.clearfocusforremoval ();
Clearchildfocus = view;
}
if (view.getanimation ()!= null | |
(Mtransitioningviews!= null && mtransitioningviews.contains (view)) {
Adddisappearingview (view);
else if (detach) {
View.dispatchdetachedfromwindow ();
}
onviewremoved (view);
View.mparent = null;
Children[i] = null;
}
if (Clearchildfocus!= null) {
Clearchildfocus (Clearchildfocus);
}
}
/**
* Finishes the removal of a detached view. This method would dispatch the detached from
* Window event and notify the hierarchy change listener.
*
* @param child, the child, definitely removed from the view hierarchy
* @param animate if True and the view has an animation, the view's placed in the
* Disappearing views list, otherwise, it's detached from the window
*
* @see #attachViewToParent (View, int, android.view.ViewGroup.LayoutParams)
* @see #detachAllViewsFromParent ()
* @see #detachViewFromParent (View)
* @see #detachViewFromParent (int)
*/
protected void Removedetachedview (View child, Boolean animate) {
if (mtransition!= null) {
Mtransition.removechild (this, child);
}
if (child = = mfocused) {
Child.clearfocus ();
}
if ((Animate && child.getanimation ()!= null) | |
(Mtransitioningviews!= null && mtransitioningviews.contains (child))) {
Adddisappearingview (child);
else if (child.mattachinfo!= null) {
Child.dispatchdetachedfromwindow ();
}
Onviewremoved (child);
}
Similarly, there are functions for finding children nodes:
Copy Code code as follows:
/**
* Returns The view at the specified position in the group.
*
* @param index the position at which to get the view from
* @return The view at the specified position or null if the position
* Does not exist within the group
*/
Public View getchildat (int index) {
if (Index < 0 | | | Index >= mchildrencount) {
return null;
}
return Mchildren[index];
}
Note: One of the specific leaf nodes, such as button, it is inherited TextView, TextView is inherited view, the code is as follows:
Copy Code code as follows:
public class TextView extends View implements Viewtreeobserver.onpredrawlistener {
。。。
}
Note: The use of (inherited) to the ViewGroup class has our commonly used container class (packing and accommodating various view), such as LinearLayout, Framelayout, and so on, the code is as follows:
Copy Code code as follows:
public class LinearLayout extends ViewGroup {
public static final int horizontal = 0;
public static final int VERTICAL = 1;
。。。
}
public class Framelayout extends ViewGroup {
...
}
public class Relativelayout extends ViewGroup {
private static final String Log_tag = "Relativelayout";
Private static Final Boolean debug_graph = false;
...
}
public class Absolutelayout extends ViewGroup {
Public Absolutelayout {
Super (context);
}
}
...
Finally, the basic control inheritance diagram is sent:
I have limited ability, write very rough, waiting for everyone's criticism, thank you ~ ~ ~