Get the width and height of the loaded layout during Android initialization (continued)-RelativeLayout trap

Source: Internet
Author: User

Get the width and height of the loaded layout during Android initialization (continued)-RelativeLayout trap

Next, the last question has been introduced. In the initialization or OnCreate method, get the width and height of the loaded layout. Finally, call view. measure (0, 0); then call getMeasuredWidth and getMeasuredHeight to obtain the measurement width and height. For details, refer to: How does Android get the width and height of the loaded layout during initialization?
When writing similar results today, load a header View to the ListView and add it to the listView header Through ListView $ addHeadView. For the sake of simplicity, I simplified the layout of this header view as follows: headview. xml

 
     
  
 

Then, you need to obtain the width and height of the layout during initialization:

// Layout loader private LayoutInflater inflater; // Viewprivate View headView in the header; // wide private int headViewWidth in the header View; // high private int headViewHeight in the header View; inflater = (LayoutInflater) context. getSystemService (Context. LAYOUT_INFLATER_SERVICE); headView = inflater. inflate (R. layout. headview, null); headView. measure (0, 0); headViewWidth = headView. getMeasuredWidth (); headViewHeight = headView. getMeasuredHeight (); Log. I (TAG, "headViewWidth -->" + headViewWidth + "headViewHeight -->" + headViewHeight); addHeaderView (headView );

Result .....

Program crashed! Nima, I'm not saying that headView. measure (0, 0) is good. After the call, we can get the layout width and height. Why is this error reported that the NULL pointer is abnormal?

Then, change the layout to a linear layout.

 
     
  
 

That's all...


The width and height of the measurement are also obtained:


Next, we began to study the problem. To simplify the problem, follow the previous steps. Add viewgroup_relativelayout.xml based on the previous layout. In fact, the outer LinearLayout is changed to RelativeLayout. Load the layout and then measure the width and height.

        
     
  

Result:


The ViewGroup of the View, textview, and linear layout is the same as the previous result. However, the ViewGroup with relative layout is directly suspended .. At the beginning, it was quite uncomfortable. Why do you often encounter problems? However, if you think that the process of solving the problem is the process of improving the level, you should study it. Hey hey ~

It is found through comparison that there is an error in RelativeLayout, so it is easy to locate the NULL pointer exception in the onMeasure function of RelativeLayout.

However, this function is complicated. More than two hundred lines of code involve a lot of domain variables and functions, and reading is quite tiring. Therefore, I searched the internet for a long time. On eoe, someone found the following method:

If Inflater is used, the above error occurs because the parent control is not specified for the Inflater Rendering component, so the Renderer does not parse the width and height attributes, a null pointer exception occurs.

Solution:

View. setLayoutParams (newLayoutParams (LayoutParams. WRAP_CONTENT, LayoutParams. WRAP_CONTENT); specify the width and height, and then call the measure method.

In fact, this is indeed the case. But why is there a problem with RelativeLayout in LinearLayout? I still haven't explained the reason.

I tried to solve the problem. The reason is not clear, so I must check the source code.The direction provided to me under this guidance is that the relatively layout parameter mLayoutParams is probably called in the onMeasure method. Because the parameter is null, a null pointer exception will be reported if it is called!

Next, place the checkpoint in the onMeasure function of the source code where mLayoutParams appears. Then breakpoint debugging

RelativeLayou class (I checked the source code of 4.2)

// 493 rows if (mLayoutParams. width> = 0) {width = Math. max (width, mLayoutParams. width);} // 523 rows if (mLayoutParams. height> = 0) {height = Math. max (height, mLayoutParams. height );}

Sure enough, the mLayoutParams variable does not exist and is null.

Till nowThe problem is clear. Because headView is called. when measure (0, 0); is passed through inflate (R. layout. headview, null); Method to load the layout. Therefore, the LayoutParams of the outer RelativeLayout layout is null, and mLayoutParams is called directly without checking whether the relative layout is null. width or mLayoutParams. height, so a null pointer error is reported.This may be a bug, I think.

Now that the problem is solved, it is easy to solve.

There are at least the following solutions:

1. When loading the layout, use inflater. inflate (R. layout. viewgroup_relativelayout, (ViewGroup) findViewById (R. id. mainLayout), false. In this case, the layout parameters are set.

2 manually set layout parameters to add

lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);setLayoutParams(lp);


Now let's take a look at the method described in the previous blog:

Private void measureView (View child) {ViewGroup. layoutParams lp = child. getLayoutParams (); if (lp = null) {lp = new ViewGroup. layoutParams (ViewGroup. layoutParams. FILL_PARENT, ViewGroup. layoutParams. WRAP_CONTENT); // child. setLayoutParams (lp);} // headerView width int childMeasureWidth = ViewGroup. getChildMeasureSpec (0, 0, lp. width); int childMeasureHeight; if (lp. height> 0) {childMeasureHeight = MeasureSpec. makeMeasureSpec (lp. height, MeasureSpec. EXACTLY);} else {childMeasureHeight = MeasureSpec. makeMeasureSpec (0, MeasureSpec. UNSPECIFIED); // UNSPECIFIED} // set the width and height to childchild. measure (childMeasureWidth, childMeasureHeight );}

It seems that the LayoutParams is determined to avoid the outer layout being RelativeLayout! However, the preceding method cannot be called directly. Because the new LayoutParams is not set, you need to call child. setLayoutParams (lp. Tested. OK!



Back to the blog and start adding the header View in the ListView, the problem is easily solved.

1. Change the relative layout to a linear layout.

2. The relative layout is still used. Use the two methods described above to set the layout parameters for the relative layout of the outer layer. For example, you can use the following method to bring the parent layout to the layout at home! So happy

Inflater = (LayoutInflater) context. getSystemService (Context. LAYOUT_INFLATER_SERVICE); headView = inflater. inflate (R. layout. headview, this, false); headView. measure (0, 0); // you can change it to the method measureView (headView) or headViewWidth = headView. getMeasuredWidth (); headViewHeight = headView. getMeasuredHeight (); Log. I (TAG, "headViewWidth -->" + headViewWidth + "headViewHeight -->" + headViewHeight); addHeaderView (headView );

Change headView. measure (0, 0); To measureView (headView); or.

However, when loading the layout, without the parent layout, headView = inflater. inflate (R. layout. headview, null) is called. The following code is used:

inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);headView = inflater.inflate(R.layout.headview, null);//headView.measure(0, 0);measureView(headView);headViewWidth = headView.getMeasuredWidth();headViewHeight = headView.getMeasuredHeight();Log.i(TAG, "headViewWidth-->" + headViewWidth + "  headViewHeight-->" + headViewHeight);addHeaderView(headView);

The program crashed again. View debugging results:


But don't worry. The error here is not a null pointer, but a class conversion exception. I believe the error can be easily modified.

Lp = new AbsListView. LayoutParams (AbsListView. LayoutParams. FILL_PARENT, AbsListView. LayoutParams. WRAP_CONTENT );

Then, you can complete the operation. The last piece of advice is to use RelativeLayout with caution when you need to measure the layout width. It is like a solution to the ScrollView and ListView conflicts. Here we only discuss one of the conflicts: as a result, the height of the ListView is incomplete and only some content is displayed. The solution is to measure the total height of the ListView, and then set the key code as follows. Imagine that if each item is RelativeLayout at this time, an error will certainly occur.

private void setListViewHeight(ListView listView) {           ListAdapter listAdapter = listView.getAdapter();            if (listAdapter == null) {               return;           }           int totalHeight = 0;           for (int i = 0; i < listAdapter.getCount(); i++) {               View listItem = listAdapter.getView(i, null, listView);               listItem.measure(0, 0);               totalHeight += listItem.getMeasuredHeight();           }           ViewGroup.LayoutParams params = listView.getLayoutParams();           params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));           listView.setLayoutParams(params);      }  

Finally, some of these things may have never been encountered when writing a program. Of course, they do not affect writing beautiful apps. However, I think that no matter what the problem is, the ability to solve the problem is helpful to learning.

The text expression ability is too bad, and the expression ability is hard to hurt! Else... At the beginning, I wrote a blog. Thank you for your attention.



Test the Demo of loading the wide and high parameters of various types of la s and the Demo of adding the header view as the relative layout in ListView.

Click here to download the code








Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.