Problem: When setting the default width to MyView, mode changes to exactly in the measure process and cannot be adapted to the content size. View TextView source code, found that not only the three modes of processing alone, but also let at_most do adaptive content, this problem is a bit complicated, left to solve later
The measurement of the view will call back the Onmeasure method, so the first thing to do is to make a onmeasure method, the function of this method is a wide-height measurement, and then must be called setmeasureddimension to set Otherwise, the illegalstateexception exception will be triggered.
This method is not written, the default is measured in exactly mode, and exactly only supports match_parent and specified dimensions, which is not valid because Wrap_content has a default value, so the system is set to match directly _parent.
protectedvoidonMeasure(intint heightMeasureSpec) { super.onMeasure(widthMeasureSpec,heightMeasureSpec);}
When the system callback Onmeasure, is to read from the layout file wide-height settings, such as specifying match_parent and specific size, it is obvious here mode for Exactly,measurespec here not to repeat, The official website explains View.measurespec, in which case we do not need to handle it because it conforms to the default measurement mode.
But what if we want the control to be self-adapting? That is wrap_content. And what should we do? Previously mentioned in the layout file settings wrap_content Invalid, you can test it yourself.
Workaround: The reason is invalid, because in the onmeasure when the default to exactly to deal with, then we just write a measurement method.
Two methods for measuring width and height are given below
measureWidth
And measureHeight
, you just have to deal with the pattern when it's not exactly.
@Override protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {Super. Onmeasure (Widthmeasurespec, Heightmeasurespec); Setmeasureddimension (Measurewidth (Widthmeasurespec), Measureheight (Heightmeasurespec)); }Private int Measurewidth(intWidthmeasurespec) {LOG.I ("Measurewidth"," "+measurespec.tostring (Widthmeasurespec));intresult= $;//Specify default size if((Measurespec.getmode (WIDTHMEASURESPEC)!=measurespec.exactly)) {result = Math.min (Result,measurespec.getsize (Widthmeasurespec));returnResult }returnMeasurespec.getsize (WIDTHMEASURESPEC); }Private int Measureheight(intHeightmeasurespec) {LOG.I ("Measureheight"," "+measurespec.tostring (Heightmeasurespec));intresult= $;//Specify default size if((Measurespec.getmode (HEIGHTMEASURESPEC)!=measurespec.exactly)) {result = Math.min (Result,measurespec.getsize (Heightmeasurespec));returnResult }returnMeasurespec.getsize (HEIGHTMEASURESPEC); }
Log:
Through the log discovery, the starting measurement mode is at_most, because we set the wrap_content, and then specify the default size in the measurement method that we define, so it becomes exactly.
Effect:
Before implementing your own measurement method
After you have implemented your own measurement methods
You can see that by implementing your own method, the wrap_content becomes effective and the default value is 200DP.
Android Notes View Article (1) View measurement