SoFunction
Updated on 2025-04-07

ScrollView nested GridView, ListView example in Android

Examples of ScrollView nesting GridView and ListView in Android

In Android development, there are often some UIs that need to be dynamically laid out with fixed styles. However, since UIs now like to pull an interface very long, in many cases we need to use ScrollView to nest list controls to implement the UI. This leads to many unpleasant problems.

Question 1: The list control is not displayed completely

The reason is that in the case of nesting, ScrollView cannot correctly calculate the height of the list control.

There are two solutions

Plan 1

After the adapter assignment is completed, the code dynamically calculates the height of the list. Here is a calculation code for ListView. The calculation method of GridView is similar, but the number of columns needs to be considered. The following code does not add the calculation of the list control padding. If you set this property, you need to add the calculation code.

public void setListViewHeightBasedOnChildren(ListView listView) {  
    // Get the Adapter corresponding to ListView    ListAdapter listAdapter = ();  
    if (listAdapter == null) {  
      return;  
    }  

    int totalHeight = 0;  
    for (int i = 0, len = (); i < len; i++) {  
      // ()Return the number of data items      View listItem = (i, null, listView);  
      // Calculate the width and height of the child item View      (0, 0);  
      // Statistics the total height of all children      totalHeight += ();  
    }  

     params = ();  
     = totalHeight+ (() * (() - 1));  
    // () Get the height occupied by the separator between children    // Finally get the height required for the complete display of the entire ListView    (params);  
  }  

Plan 2

Rewrite the onMeasure method of the list control. This solution will not show the scrollbar of the list control itself, and the viewholder reuse mechanism will be invalid.

@Override
  public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int expandSpec = (1 << 16, MeasureSpec.AT_MOST);
    (widthMeasureSpec, expandSpec);
  }

Scheme 1 has many codes and needs to be written multiple times. It is recommended to write them into a tool class for easy call; Scheme 2 has performance problems when the data volume is too large to be displayed on one screen, and when swiping quickly, the ScrollView will constantly calculate the height of the list control. The thief affects the drawing performance.
There are pros and cons of the two solutions, everyone chooses for themselves

Question 2: The list control automatically gets focus, causing the ScrollView to automatically scroll to the position where the list control is located

There are actually many solutions to this problem, and it can be summed up in two ways.

Plan 1

Wait for all the list control data to be loaded (including picture loading) to call (ScrollView.FOCUS_UP);

Method to let the ScrollView scroll to the top. The time of loading completion is difficult to control, and if it is not done well, there will be scrolling animations, which is very embarrassing.

Plan 2

Rewrite the following two methods of list control to return false

@Override
  public boolean isFocused() {
    return false;
  }

  @Override
  public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
    return false;
  }

The advantages and disadvantages of the two solutions are very obvious. Oh, I have not discovered the disadvantages of the second solution at present. If you find any pitfalls when using this, please leave a message to inform us

Question 3 Sliding conflict

There are several key points to solve, but first you have to be familiar with the event delivery of view

You need to decide to rewrite the following methods of list control and ScrollView according to the situation. Return different bool values ​​to the method according to the situation to tell the control whether to intercept or pass events. If the control needs to be scrolled in which direction, the event will be transmitted in which direction. As a developer with pursuit, remember not to intercept all the time.

 @Override
  public boolean onTouchEvent(MotionEvent ev) {
    return (ev);
  }

  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    return (ev);
  }

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    return (ev);
  }

Give a small easter egg

getParent().requestDisallowInterceptTouchEvent(boolean b);

This code can determine whether to let the parent container get the event in the child control

Thank you for reading, I hope it can help you. Thank you for your support for this site!