Customize View by yourself, you must inherit View class. For the View class, it must run this three methods in flow. Brief describe as below
- onMeasure(): Set the layout size.
- onLayout(): Set the layout position.
- onDraw(): Draw the layout content.
Before the flow, I will explain a little the constructor of View or ViewGroup. Normally, there are three constructor we need to override.
- public View (Context context): It will be used in Java code when you code new Customize(context).
- public View (Context context, AttributeSet attrs): When you set some attributes in xml layout and don't set Style.
- public View (Context context, AttributeSet attrs, int defStyle): Base on the 2 and set the Style.
So if don't use Style, we can just only focus on public View (Context context, AttributeSet attrs).
There're three main methods of Measure class.
- getMode(int measureSpec): It can obtain the spec mode from measureSpec.
- getSize(int measureSpec): It can obtain the spec size from measureSpec.
- makeMeasureSpec(int size, int mode): According to the size and the mode to create a new measureSpec.
Here are three type of mode:
- UNSPECIFIED: Parent's View doesn't force the constraint of Children's View. They can be any size.
- EXACTLY: Parent's View has already confirmed Children's View exactly. Children will be constrained and their settings of the size will be ignored.
- AT_MOST: The size of children's View cannot over set from assigned size.
Actually, onMeasure(widthMeasure, heightMeasure) of two parameters are that an integer number of combing from mode and size , you have to get the mode or the size from MeasureSpec.getMode or MeasureSpec.getSize for getting Parent's parameters.
So the size of the view will be effected by three aspects.
- The MeasureSpec of Parent's View.
- The LayoutParams of Children's View.
- setMeasuredDimension() or the methods of set mMeasuredWidth, mMeasuredHeight.
Each of view includes ViewGroup.LayoutParams class or delegate class and LayoutParams show The relationship between View and Parents's View. The size of view is decided by View and Parent's View. Normally, when we want to add a view to RelativeLayout or LinearLayout, no matter by addView or write in xml layout file, onMeasure() will be called automatically. And the two parameters of onMeasure are from Parent's View.
Of course we can set the value of width and height directly in xml layout file or match_parent/wrap_content, we can also set LayoutParams in the code. The settings will correspond to the parameters of onMeasure method.
For example,
- Set a value(width=200dp) or match_parent/fill_parent in xml or LayoutParams. Mode is MeasureSpec.EXACTLY.
- Set (width=wrap_content). Mode is MeasureSpec.AT_MOST. Here is a table of heightMeasureSpec or widthMeasureSpec from Parent to Children when the system calls measure() method.
Parent's View MeasureSpec Child's View LayoutParams Child's View invalidate()
We often use this method. It will help us to request to redraw(draw()) the tree of View. If views don't change the size then layout() won't be called.
- invalidate(): Request a redraw and draw() will be called, but only caller will do draw().
- setSelection(): Request a redraw and draw() will be called, but only caller will do draw().
- setVisibility(): Switch INVISIBLE to VISIBLE, invalidate() will be called indirectly.
- setEnabled(): Request a redraw and draw() will be called.
It will cause that measure() and layout() run. This is for re-layout the tree of Views, so it's not including draw() method.
Adaptive ImageView