In a recent project, a message flow similar to Sina Weibo is needed, with each text and nine picture, so this involves a ListView or ScrollView nested gridview problem. The height of the GridView problem on the Internet is easy to find the answer, that is, overwrite the Onmeasure method, and then set the height of the measurespec. However, the width of the problem does not have any information, the width of the problem is such as the GridView column number is 3, so even if there is only one picture, the width of the GridView is Match_parent, Click events in the ListView that cause the user to click outside the picture range but within the GridView range cannot be captured.
:
The problem arises as above, when there is only one icon when the width of the GridView (gray area) is also match_parent, this time clicking the GridView area is the ListView is not responsive, However, if the background color of the GridView is consistent with the background of the ListView, the user is not able to see the width of the GridView, and when the user clicks outside the image, the possible action is to enter the detail page of the message, but since the GridView is Match_parent, So the ListView doesn't get a click event at all, so the experience is bad. The effect we need is this:
that is, the size of the GridView can include the size of the picture, so that when the background color of the GridView is the default, users click outside the image of the area is clicked on the ListView item.
Let's see how to solve this problem, first of all, the layout is not talk about, mainly talk about the problem of the width of the GridView. To solve the height problem of the GridView, you need to overwrite the Onmeasure method of the GridView, the code is as follows:
public class Mgridview extends GridView {public Boolean hasscrollbar = true; /** * @param context */public Mgridview (context context) {This (context, NULL); } public Mgridview (context context, AttributeSet Attrs) {Super (context, attrs, 0); } public Mgridview (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle); } @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {int expandspec = Heightme Asurespec; if (hasscrollbar) {expandspec = Measurespec.makemeasurespec (integer.max_value >> 2, M Easurespec.at_most); Super.onmeasure (Widthmeasurespec, expandspec);//note here The meaning is to directly measure the height of the GridView} else {super.onmeasure (WI Dthmeasurespec, Heightmeasurespec); } }}
In the Onmeasure method, because Hasscrollbase is true, we notice the commented branch in the code. This is actually the height of the GridView at the time of onmeasure, not just the height of several of the view. Without this step, the height of the GridView will not be fully displayed. Calculates the height of the GridView so that it does not need to slide up and down to show the other item, because the problem is that the GridView is nested in the ScrollView or the component containing the ScrollView, causing the conflict.
To solve the problem of width, the idea is to manually calculate the number of images per gridview in the GetView method of the ListView, if the number of images is less than the number of columns per row of the GridView, manually calculate the required width for each child view, Then the width of the GridView = child number * The width of each child view. To avoid repeated calculations, we cache the results of the calculations. The calculation code is as follows:
/** * @author mrsimple */public final class Gridviewutils {/** * storage width */static Sparseintarray Mgvwidth = n EW Sparseintarray (); /** * Calculates the height of the GridView * * @param gridview to calculate the GridView */public static void Updategridviewlayoutparams ( Mgridview gridView, int maxcolumn) {int childs = Gridview.getadapter (). GetCount (); if (Childs > 0) {int columns = Childs < Maxcolumn? Childs% Maxcolumn:maxcolumn; Gridview.setnumcolumns (columns); int width = 0; int cachewidth = mgvwidth.get (columns); if (cachewidth! = 0) {width = cachewidth; else {//calculates the width of each row of the GridView, and calculates the width of all item if item is less than 3; Otherwise, only 3 child widths are computed, so a row has a maximum of 3 child. (Here we take 3 as an example) int rowcounts = Childs < Maxcolumn? Childs:maxcolumn; for (int i = 0; i < rowcounts; i++) {View Childview = Gridview.getadapter (). GetView (i, NULL, GRIDVI ew; Childview.measure (0, 0); width + = childview.getmeasuredwidth (); }} viewgroup.layoutparams params = Gridview.getlayoutparams (); Params.width = width; Gridview.setlayoutparams (params); if (mgvwidth.get (columns) = = 0) {mgvwidth.append (columns, width); } } }
The GetView method for the ListView is as follows:
@Override public View getView (int position, view Convertview, ViewGroup parent) {Viewholder viewholder = null; if (Convertview = = null) {Convertview = Minflater.inflate (R.layout.listview_item, parent, false); Viewholder = new Viewholder (); Viewholder.mgridview = (Mgridview) Convertview.findviewbyid (R.id.my_gridview); Viewholder.mtextview = (TextView) Convertview.findviewbyid (R.ID.MY_TV); Convertview.settag (Viewholder); } else {Viewholder = (Viewholder) convertview.gettag (); } final ListViewItem item = getItem (position); Set the adapter ViewHolder.mGridView.setAdapter of the GridView (New Gridviewadapter (Mcontext, item.mimages)); Calculates the GridView width, setting the default to NumColumns to 3. Gridviewutils.updategridviewlayoutparams (Viewholder.mgridview, 3); ViewHolder.mTextView.setText (Item.mtext); return convertview; }
In this way, we solve the problem of the width and height of the message flow.
Demo Address: Punch here ~
Simple message Flow UI for the ListView nesting GridView in Android (addressing the wide-height problem)