Reprint please specify the source http://blog.csdn.net/allen315410/article/details/39581055
Some of the previous posts described how Android can customize the control, in fact, is to talk about how to "scratch" the customization of a new control, inherit view or inherit ViewGroup, the method of copying its related methods, this custom control way relatively difficult, And not all the new controls need to be done in this case. There are a lot of situations where we just use Android to provide me with good controls, which are cleverly combined in a layout that is a new control that I call "Custom combo Controls".
So, under what circumstances does this custom composite control work? Or when you do the project, you will find that some layouts will be reused, the same layout of the XML block will be duplicated repeatedly paste multiple times, this will cause the code structure confusion does not say, the code will increase, the various controls need to be declared in the Java code and processing the corresponding logic, the workload is really not small, so, Must find a reasonable "lazy" way to start the brain to simplify the above-mentioned unnecessary trouble. Let's take a look at a diagram, and for a simple layout, we'll implement a simple custom composite control for this diagram.
From the above diagram, we can see that there is no "brand new" control in this layout, it is using the native control of the Android system. Familiar with the Android interface layout of the people, it must feel that this layout is really small case, too simple, minutes can be finished. So here is the layout code for an entry:
<?xml version= "1.0" encoding= "Utf-8"? ><relativelayout xmlns:android= "http://schemas.android.com/apk/res/ Android "android:id=" @+id/rl_show_address "android:layout_width=" match_parent "android:layout_height=" 60dip "a ndroid:background= "@drawable/selector_blue" > <textview android:id= "@+id/tv_title" Android:layout_w Idth= "Wrap_content" android:layout_height= "wrap_content" android:layout_marginleft= "5dip" Android:lay out_margintop= "1dip" android:text= "This is the title" android:textcolor= "#000000" android:textsize= "20sp"/> <textview android:id= "@+id/tv_desc" android:layout_width= "wrap_content" android:layout_height= "WR Ap_content "android:layout_below=" @id/tv_title "android:layout_marginleft=" 6dip "Android:layout_margi ntop= "1dip" android:text= "This is description content" android:textcolor= "#99ff0000" android:textsize= "14sp"/> < CheckBox android:id= "@+id/Cb_status "android:layout_width=" wrap_content "android:layout_height=" Wrap_content "Android:layout_al Ignparentright= "true" android:layout_centervertical= "true" android:clickable= "false" Android:fo Cusable= "false"/> <!--plus a split line--<view android:layout_margintop= "7dip" Android:layo Ut_alignparentbottom= "true" android:layout_alignbottom= "@id/cb_status" android:layout_width= "Match_parent" android:layout_height= "0.2dip" android:background= "#000000"/></relativelayout>
As you can see, this layout is really quite simple. However, this time the product manager told you that the need to change, we need to add another such entry in this interface, so you think, ctrl+c,ctrl+v, easy to fix, and then change the ID of the control, in the Java Code Findviewbyid (ID), add a piece of logic code , finish the call. Did not expect this time the product again, the need to change, here need to add 10 such layout, so you ... Admittedly, this time again ctrl+c,ctrl+v is not suitable, the workload is very big, even if you do not bother, so do, you can not get the product will come again, the one to me to delete a few, that plus a few, is not going crazy.
Maybe we can come up with a lazy way. By analyzing the above layout, it can be found that each sub-item on the layout is constant, the layout is exactly the same, the only change is that the text on the red TextView with the state of the checkbox to change, and this change, we can find a way to extract into a method, the answer is sure to be able. We can encapsulate the layout of this seed entry into a Java class at once, each time we call this control, we set various property data beforehand, here is the custom attribute, for the custom attribute, can refer to my previous blog,Android custom Control--Custom properties , it is not here to repeat. Analysis of this attribute set how to define, from the above picture can be seen, the control needs to set the content is, the above TextView title, as well as the following TextView description information, and the description information is based on the status of the checkbox change, So both states (true or false) need to be defined in the attribute set, so the property set is there.
Under Engineering, under the Res/values directory, create a new Attrs.xml file that defines the following set of properties:
<?xml version= "1.0" encoding= "Utf-8"?><resources> <declare-styleable Name= "Combinationview" > <attr name= "desc_on" format= "string" ></attr> <attr name= "Desc_off" Format= "string" ></attr> <attr name= "title" format= "string" ></attr> </declare-styleable& Gt;</resources>
Having defined the property set, we need to define a Java class to render the layout, parse the property set, and provide a way for the object to modify the state of the control, which has achieved the effect of reuse. The question is, which class does the Java class we define need to inherit from? Here, we don't have to think about view, because this is not a new custom control, and you don't need onmessure and ondraw to measure to draw a view. What about ViewGroup? We don't have to use this class either, because the layout here is a good one, and you don't need to use OnLayout to set the display position for the child controls. So, what should we inherit? Can we imagine if the subclass of ViewGroup is possible? Implementing custom Controls In addition to inheriting view and ViewGroup, but also directly inherit the Android control to modify, this object-oriented thinking, it should not be difficult to imagine it. Because, the layout file with the relative layout relativelayout, we would certainly be able to customize the Java class to inherit this relativelayout,relativelayout provides some parameters and methods to facilitate our implementation of the child control layout. However, we have already written this directly in the child control layout, and do not need to use the parameters and methods provided by Relativelayout to lay it out. So, caused, even if not to inherit relativelayout, and change to linearlayout,framelayout ... It is also possible, as long as this layout class is a subclass of ViewGroup. The following is the implementation code for this custom composite control:
Package Com.example.combinationview;import Android.content.context;import Android.util.attributeset;import Android.view.view;import Android.widget.checkbox;import Android.widget.relativelayout;import Android.widget.textview;public class Combinationview extends Relativelayout {private TextView tv_title;private TextView tv_desc;private CheckBox cb_status;//namespace, when referencing this custom component, you need to use the private String namespace = "http/ Schemas.android.com/apk/res/com.example.combinationview ";//title private string title;//selected description private string desc_on;/ /Unselected description Private String Desc_off;public Combinationview (context context, AttributeSet Attrs) {Super (context, attrs);// Renders the layout of the custom composite control as Viewview view = view.inflate (context, R.layout.layout_combinationview, this); tv_title = (TextView) View.findviewbyid (r.id.tv_title); Tv_desc = (TextView) View.findviewbyid (R.ID.TV_DESC); cb_status = (CheckBox) View.findviewbyid (r.id.cb_status); title = Attrs.getattributevalue (namespace, "title");d esc_on = Attrs.getattributevalue (NamespaCE, "desc_on");d Esc_off = Attrs.getattributevalue (namespace, "Desc_off"); System.out.println (title + ":" + desc_on + ":" + Desc_off);//Initialize to child control if (title! = null) {Tv_title.settext (title);} if (Desc_off! = null) {Tv_desc.settext (Desc_off);}} /** * Determine if selected * * @return */public boolean isChecked () {return cb_status.ischecked ();} /** * Set Selected Status * * @param isChecked */public void setchecked (Boolean isChecked) {cb_status.setchecked (isChecked); if (Ische cked) {tv_desc.settext (desc_on);} else {tv_desc.settext (Desc_off);}}}
The code is simple, first inheriting relativelayout, copying its construction method, rendering the layout view in the construction method, then reading the properties of the property set, and displaying the default displayed properties to the child controls on the layout. In addition, to provide a method of judging the state ischecked () to determine whether the control is selected, provide a way to set the state setchecked (Boolean), to change the state. PS: In order to verify my above paragraph, the reader can inherit relativelayout, instead inherit linearlayout or inherit Framelayout, run try, also can achieve.
Here's how to reference this custom composite control, which you first need to define in the activity's layout file:
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:example= "http// Schemas.android.com/apk/res/com.example.combinationview "android:layout_width=" Match_parent "Android:layout_ height= "match_parent" android:orientation= "vertical" > <com.example.combinationview.combinationview and Roid:id= "@+id/cv_first" android:layout_width= "match_parent" android:layout_height= "wrap_content" exam Ple:desc_off= "I was not selected description 1" example:desc_on= "I was selected description 1" example:title= "I was Heading 1" > </com.example.combina Tionview. combinationview> <com.example.combinationview.combinationview android:id= "@+id/cv_second" android:l Ayout_width= "Match_parent" android:layout_height= "wrap_content" example:desc_off= "I am an unselected description 2" example :d esc_on= "I was selected description 2" example:title= "I am Heading 2" > </com.example.combinationview.CombinationView> <com. Example.combinationview.CombinationView Android:id= "@+id/cv_third" android:layout_width= "match_parent" android:layout_height= "Wrap_content" Example:desc_off= "I was not selected description 3" example:desc_on= "I was selected description 3" example:title= "I was heading 3" > </com.example.c Ombinationview. combinationview> <com.example.combinationview.combinationview android:id= "@+id/cv_fourth" android:l Ayout_width= "Match_parent" android:layout_height= "wrap_content" example:desc_off= "I am an unselected description 4" Example :d esc_on= "I was selected description 4" example:title= "I was heading 4" > </com.example.combinationview.combinationview></linearl Ayout>
First, in the above definition of four custom composite controls, you can see, the code is much more streamlined not?! Note: The custom set of properties is referenced here, so you must add a namespace on the layout node
Xmlns:example= "Http://schemas.android.com/apk/res/com.example.combinationview"
Where example is the name of the namespace and is arbitrary, but must have the same name as the reference property in the control, or it will be an error. The following string is the path of the attribute set, the first half is fixed, the last "/" after the content must be the project package name, otherwise error.
Here is the business logic code in activity, nothing to say
Package Com.example.combinationview;import Android.os.bundle;import Android.view.view;import Android.view.view.onclicklistener;import Android.app.activity;public class Mainactivity extends Activity implements Onclicklistener {private Combinationview cv_first;private combinationview cv_second;private CombinationView cv_third; Private Combinationview Cv_fourth; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate ( Savedinstancestate); Setcontentview (r.layout.activity_main); Cv_first = (Combinationview) findViewById (R.id.cv_ first); Cv_second = (Combinationview) Findviewbyid (r.id.cv_second); Cv_third = (Combinationview) Findviewbyid (R.id.cv_ third); Cv_fourth = (Combinationview) Findviewbyid (R.id.cv_fourth); Cv_first.setonclicklistener (this); cv_ Second.setonclicklistener (This), Cv_third.setonclicklistener (This), Cv_fourth.setonclicklistener (this);} @Overridepublic void OnClick (View v) {switch (V.getid ()) {Case r.id.cv_first:if (cv_first.ischecked ()) {cv_ First.setchecked (false);} ELSE {cv_first.setchecked (TRUE);} Break;case r.id.cv_second:if (cv_second.ischecked ()) {cv_second.setchecked (false);} else {cv_second.setchecked (true );} Break;case r.id.cv_third:if (cv_third.ischecked ()) {cv_third.setchecked (false);} else {cv_third.setchecked (true);} Break;case r.id.cv_fourth:if (cv_fourth.ischecked ()) {cv_fourth.setchecked (false);} else {cv_fourth.setchecked (true );} Break;default:break;}}}
Well, the custom combo control is finished, very simple, but more commonly used. Later in the project to use, think of the implementation of the steps, custom a combination of controls, it is more convenient to use, than simply copy the paste is not only tall, but also improve the reusability of the code, simplifying the structure of the code and reduce the amount of code.
Please download the source code here
Android Custom Controls--Custom combo controls