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

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

After searching the scrolling conflict between EditText and ScrollView on the Internet, it is found that almost all solutions are to hand over the event to EditText when touching EditText, otherwise, hand over the event to ScrollView. This does initially solve the rolling conflict between the two, but it is not the best solution. For example, EditText could have displayed 6 lines of text, but at present only 5 lines of text are displayed. At this time, we slid in the EditText area and expected the whole page to scroll. However, because we handed the event to EditText for processing, the page could not scroll, which is a very poor experience. In fact, we prefer that when the scroll bar appears in EditText, the scroll event should be handled by itself, and in other cases, it should be handled by ScrollView. So how to achieve it? Next, let's make a small Demo to realize this scheme.

1. Layout files

First, write the layout file, and it can be seen that this is a very simple layout: an ScrollView wraps an LinearLayout in the vertical direction, and there are two TextView and one EditText in LinearLayout, in which a background rectangle_shape is set to distinguish the range of EditText.


<ScrollView
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent">


 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical">

 <TextView
 android:layout_width="match_parent"
 android:layout_height="300dp"
 android:text="Hello World Begin!"/>


 <EditText
 android:id="@+id/edit_text"
 android:hint="EditText"
 android:layout_width="match_parent"
 android:layout_height="200dp"
 android:gravity="top"
 android:background="@drawable/rectangle_shape"/>

 <TextView
 android:layout_width="match_parent"
 android:layout_height="300dp"
 android:text="Hello World End!"/>
 </LinearLayout>

</ScrollView>

2.rectangle_shape

Background rectangle_shape code, there is no technical content. . . . . .


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
 <solid android:color="#ffffff"/>
 <stroke android:color="#cccccc"
 android:width="1dp"/>

</shape>

3. Code in MainActivity

This is the main code logic. First set OnTouchListener to EditText, then judge whether the currently clicked area is EditText in OnTouch method, if it is EditText area, then judge whether it can scroll in vertical direction, if it can scroll, then hand over the event to EditText for processing, otherwise hand over the event to ScrollView for processing.
The most important thing here is how to judge that the EditText area can scroll in the vertical direction. The code here has been encapsulated into a method, which can be used directly. So why do you want to judge like this? If you are still interested, please continue to read the perfect solution to the scrolling conflict between EditText and ScrollView (below).


public class MainActivity extends Activity implements View.OnTouchListener {

  private EditText mEditText;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mEditText = (EditText) findViewById(R.id.edit_text);
    mEditText.setOnTouchListener(this);
  }

  @Override
  public boolean onTouch(View view, MotionEvent motionEvent) {
    // Touching is EditText And currently EditText If you can scroll, you can hand the event to EditText Treatment; Otherwise, the event is handed over to its parent class 
    if ((view.getId() == R.id.edit_text && canVerticalScroll(mEditText))) {
      view.getParent().requestDisallowInterceptTouchEvent(true);
      if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
        view.getParent().requestDisallowInterceptTouchEvent(false);
      }
    }
    return false;
  }

  /**
   * EditText Can you scroll in the vertical direction 
   * @param editText  Need to be judged EditText
   * @return true : You can scroll   false : Cannot scroll 
   */
  private boolean canVerticalScroll(EditText editText) {
    // Rolling distance 
    int scrollY = editText.getScrollY();
    // Total height of control content 
    int scrollRange = editText.getLayout().getHeight();
    // The actual display height of the control 
    int scrollExtent = editText.getHeight() - editText.getCompoundPaddingTop() -editText.getCompoundPaddingBottom();
    // The difference between the total height of the control content and the actual display height 
    int scrollDifference = scrollRange - scrollExtent;

    if(scrollDifference == 0) {
      return false;
    }

    return (scrollY > 0) || (scrollY < scrollDifference - 1);
  }
}



Related articles: