Divided into three types:
- Inheriting existing controls: overriding OnDraw ()
- Combine existing controls: Inherit ViewGroup, usually a certain layout
- Customizing new controls: Inheriting view or Surfaceview, overriding Onmeasure,ondraw
Introduce a parameter inside the onmeasure measurespec
Source:
/** * Measurespec encapsulates the layout requirements that parent layouts pass to child layouts, each MEASURESPEC represents a set of requirements for width and height * Measurespec consists of size and mode. * Three mode: * 1.UNSPECIFIED * The parent does not have any constraints on the child, which can be any size (that is, unspecified) * (UNSPECIFIED in the source of processing and exactly. When the width height value of the view is set to 0 or if the width is not set, the pattern is unspecified * 2.EXACTLY * The parent determines the exact size of the child, the child is confined to the given boundary, ignoring its desired size. * (When the width or height is set to Match_parent, the mode is exactly, because the child view occupies the space of the remaining container, so it is determined by the size) * 3.at_most * Sub Maximum can reach the specified size * (When set to WRAP_ Content, a pattern of at_most, indicates the maximum size of a child view, so that the child view sets its own size according to this limit) * * Measurespecs uses binary to reduce the allocation of objects. */ Public classMeasurespec {//The Carry size is 2 of the 30 square (the size of int is 32 bits, so the carry 30 bit is to use the highest bit of int and the second-to-last digit is 32 and 31 bits to do the flag bit) Private StaticFinalintMode_shift = -; //operation Matte, 0x3 is 16, 10 binary is 3, binary is 11. 3 left carry 30, that is 11 00000000000 (11 followed by 30 0)//(The effect of the mask is to use 1 to annotate the desired value, and 0 to label the unwanted value.) Because 1 and any number do and operations are any number, 0 and any number do and operations are 0) Private StaticFinalintMode_mask =0x3<<Mode_shift; //0 left carry 30, that is 00 00000000000 (00 followed by 30 0) Public StaticFinalintUNSPECIFIED =0<<Mode_shift; //1 left carry 30, that is 01 00000000000 (01 followed by 30 0) Public StaticFinalintexactly =1<<Mode_shift; //2 left carry 30, that is 10 00000000000 (10 followed by 30 0) Public StaticFinalintAt_most =2<<Mode_shift; /** * Get a detailed measurement result based on the size and mode provided*/ //measurespec = size + mode; (Note: binary addition, not 10-binary addition!) ) //The purpose of this design is to use a 32-bit binary number, 32 and 31 bits to represent the value of mode, and the last 30 bits to represent the value of size//For example size=100 (4), Mode=at_most, then measurespec=100+10000...00=10000..00100 Public Static intMakemeasurespec (intSizeintmode) { returnSize +mode; } /** * Get mode with detailed measurement results*/ //mode = Measurespec & mode_mask; //Mode_mask = 11 00000000000 (11 followed by 30 0), the principle is to replace the 30-bit 0 in the post-mode_mask 30 bit with 1 in the post-Measurespec, and then retain the MODE value of 32 and 31 bits. //For example, 00..00100 & 11 00..00 (11 followed by 30 0) = 00..00 (At_most), which gives the value of mode Public Static intGetMode (intMeasurespec) { return(Measurespec &mode_mask); } /** * Get size with detailed measurement results*/ //size = Measurespec & ~mode_mask; //The principle is the same as above, but this time is to reverse the mode_mask, that is, 00 111111 (00 followed by 30 1), 32, 31 is replaced by 0 is to remove mode, retain the 30 bit size Public Static intGetSize (intMeasurespec) { return(Measurespec & ~mode_mask); } /** * Override the ToString method, print the mode and size information, omitted here*/ Public StaticString toString (intMeasurespec) { return NULL; }}
A typical view metric implementation:
@Overrideprotected voidOnmeasure (intWidthmeasurespec,intHeightmeasurespec) {Measuredheight=measureheight (HEIGHTMEASURESPEC); Measuredwidth=measurewidth (WIDTHMEASURESPEC); Setmeasureddimension (Measuredwidth, measuredheight); } Private intMeasurewidth (intWidthmeasurespec) { intSpecmode =Measurespec.getmode (WIDTHMEASURESPEC); intSpecsize =measurespec.getsize (WIDTHMEASURESPEC); //If you do not specify a limit, it is the default size intresult = -; if(Specmode = =measurespec.at_most) { //returns the outer boundary size if the parent component is populated by a controlresult =specsize; }Else if(Specmode = =measurespec.exactly) { //returns the actual size of the control if the space size is specifiedresult =specsize; } returnresult; } Private intMeasureheight (intHeightmeasurespec) { //TODO auto-generated Method Stub intSpecmode =Measurespec.getmode (HEIGHTMEASURESPEC); intSpecsize =measurespec.getsize (HEIGHTMEASURESPEC); //If you do not specify a limit, it is the default size intresult = -; if(Specmode = =measurespec.at_most) { //returns the outer boundary size if the parent component is populated by a controlresult =specsize; }Else if(Specmode = =measurespec.exactly) { //returns the actual size of the control if the space size is specifiedresult =specsize; } returnresult; }
Android Custom Control