Perfect solution to the scrolling conflict between EditText and ScrollView (Part Two)

  • 2021-07-24 11:48:25
  • OfStack

The last article perfectly solves the scrolling conflict between EditText and ScrollView (Part I) mentioned that we wrote a method to judge whether EditText can scroll in the vertical direction, so how did this method come from?
In fact, Android API has a method to judge whether the control can scroll in the vertical direction. The name of the method is canScrollVertically (int direction), and the code is as follows:


/**
   * Check if this view can be scrolled vertically in a certain direction.
   *
   * @param direction Negative to check scrolling up, positive to check scrolling down.
   * @return true if this view can be scrolled in the specified direction, false otherwise.
   */
  public boolean canScrollVertically(int direction) {
    final int offset = computeVerticalScrollOffset();
    final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
    if (range == 0) return false;
    if (direction < 0) {
      return offset > 0;
    } else {
      return offset < range - 1;
    }
  }

According to the annotation, it is not difficult to know that this method is used to judge whether the current control can scroll in the vertical direction: when the parameter direction is negative, it will judge whether the current control can scroll upward; Otherwise, when the parameter direction passes a non-negative value, it will judge whether the current control can scroll down.
From this, we know that we can use this method to judge whether a control can scroll in the vertical direction:


if(editText.canScrollVertically(-1) || editText.canScrollVertically(0)) {
      // You can scroll in the vertical direction 
    }

So why not use this method? Very helpless, because this method is only provided in API 14 (that is, Android 4.0), and most of the time we need to be compatible with mobile phones below 4.0, so we can't use it directly. Although can not use this method directly, but we can look at 1 below it is how to achieve the interior, directly copy over not to get! However, there is also a tragic news, computeVerticalScrollOffset (), computeVerticalScrollRange () and computeVerticalScrollExtent () are all protected methods, so we still can't use them, so we have to look at the internal implementation of these three methods together.

1. computeVerticalScrollOffset () method

The first is the computeVerticalScrollOffset () method: `


protected int computeVerticalScrollOffset() {
    return mScrollY;
  }

This method is defined in View, and neither EditText nor TextView is overridden, so it must return mScrollY. So how can we get mScrollY without this method? Guess a little bit, since there is such a variable as mScrollY, there should be its get method. Looking at API, it is not difficult to see that there is indeed an getScrollY () method in View:


public final int getScrollY() {
    return mScrollY;
  }

2. computeVerticalScrollRange () method

OK, we got the value of the first method through getScrollY (). Next, let's look at the second method computeVerticalScrollRange ():


protected int computeVerticalScrollRange() {
    return getHeight();
  }

This method was quickly found in View, but is this method what we need? Don't forget that we use EditText! So we need to see if this method is overloaded in EditText and TextView under 1. As we expected, this method is really overloaded in TextView:


@Override
  protected int computeVerticalScrollRange() {
    if (mLayout != null)
      return mLayout.getHeight();

    return super.computeVerticalScrollRange();
  }

This method returns the height of mLayout, so how do we get mLayout? We just used the getScrollY () method when we got mScrollY, so will there be an getLayout () method? With the attitude of giving it a try, I suddenly found that there is really such a method in TextView:


public final Layout getLayout() {
    return mLayout;
  }

3. computeVerticalScrollExtent () method

Well, we also got the value of the second method through getLayout (). getHeight (). Now let's look at the last method computeVerticalScrollExtent ():


protected int computeVerticalScrollExtent() {
    return getHeight();
  }

We also found this method in View, but based on the experience of the second method, we should also go to EditText and TextView to see if there is any overload in 1. Once again, as we expected, this method was overloaded in TextView:


@Override
  protected int computeVerticalScrollExtent() {
    return getHeight() - getCompoundPaddingTop() - getCompoundPaddingBottom();
  }

It is not difficult to find that the three methods used here, getHeight (), getCompoundPaddingTop () and getCompoundPaddingBottom (), are all public methods, which we can call directly.
At this point, we can completely rewrite the canScrollVertically (int direction) method, and the rewritten method is the canVerticalScroll (EditText editText) method used in our last article.


Related articles: