Wen/coderao (author of Jane's book)
original link: http://www.jianshu.com/p/68b383b129f9
copyright belongs to the author, please contact the author to obtain authorization, and Mark "book author".
When a bunch of views of the same style are used more than once in the project, for ease of use, we want to get them into a separate class to customize the view.
For example, we're going to do something like this:
Beauty.png
This piece consists of two things: a ImageView and a label. First we create a new class MyView that inherits from UIView.
In the MyView. m file, you can set the two child controls to myview properties or member variables as you wish, and here we set them as properties.
@property (nonatomic, strong) UIImageView *imageView;@property (nonatomic, strong) UILabel *label;
The next step is to add controls to the custom view.
The usual idea is to rewrite the UIView method of construction. Well, here's the first note:
1. To override the UIView initWithFrame: method Instead of the Init method
Why is it? Because when external calls to Init's method, the inside will silently call initWithFrame: method, you can not guarantee that other colleagues call your class when the initWithFrame: method, if you only rewrite the Init method, Then two of the child controls are not created.
So we write this:
- (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { /* 添加子控件的代码*/ } return self;}
Next start to add the child control, do not know if there will be a small partner is written like this:
-(Instancetype) initWithFrame: (CGRect) Frame {if (Self = [Super Initwithframe:frame]) {self.imageview = [[ Uiimageview Alloc]init]; self.imageview.frame = cgrectmake (0, 0, self.frame.size.width, self.frame .size.width); [self addsubview:selfreturn self;}
Is there a problem with that? If all is well written and run, can you see ImageView? The answer is uncertain. The problem arises in assigning a value to the ImageView frame.
The width and height of the ImageView are directly used with self.frame.size.width, but this time self.frame may not be worth it.
As we said above, if the MyView init method is called externally, it will also be executed here, when the frame is not assigned a value.
So a second note:
2. Do not directly in the construction method itself (self, or the view) of the width of the high, this time to take the width of the high is not allowed.
I think a beginner's custom Tableviewcell has encountered a problem like this:
When you add a child control to a cell by overriding the initialization method of the cell
(assuming that the cell's height is set to 100, you want to add a label at the bottom of the cell),
And so wrote:
Label.frame = CGRectMake (0,self.frame.size.height-20, 100, 20),
Run out but found that the added label is not in our desired position (bottom),
Instead, the cell is more biased (the actual Y value is 44-20 instead of 100-20).
And then, in debug, it was discovered that although the cell's height has been set to 100, the cell height taken from the initialization method is still the default of 44.
This is actually the reason why we can not take the frame or bounds in the control's construction method, when the value is not accurate.
So when we re-construct the method, we just need to put the controls in, for the time being, let's not think about where they are:
-(Instancetype) initWithFrame: (CGRect) Frame {if (self = [super initWithFrame: Frame] {self.imageview = [[self addsubview:selfself.label = [[UILabel alloc] INIT]; self.label.textAlignment = Span class= "hljs-built_in" >nstextalignmentcenter; [self addsubview:self.label];} return self;}
So when do you set the child control's frame?
A third note:
3. Layout child controls inside the Layoutsubviews method
As follows:
- (void) Layoutsubviews {Be sure to call the Super method [Super Layoutsubviews];Determine the frame of the child control (the frame/bounds of self is accurate here)cgfloat width = self.bounds< Span class= "hljs-variable" >.size.width; cgfloat height = self.bounds< Span class= "hljs-variable" >.size.height; self.imageview.frame = cgrectmake (0, 0, width, width); self.label.frame = cgrectmake (0, Width, width, height-width);}
It is important to note that the Layoutsubviews method of the parent class must be called first before layout.
Because in this method can obtain myview accurate width and height, we directly take its width height to set the ImageView and the label width Gao can
Of course, the creation of a child control does not have to be written in the MyView constructor, and since the declaration becomes a property, using lazy loading (the Get method of overriding the property) is also a good choice.
Customizing UIView with Code Note 123