Подтвердить что ты не робот

Android WebView внутри ScrollView прокручивает только scrollview

В моем приложении у меня есть ScrollView, который содержит некоторые линейные просмотры, некоторые текстовые изображения и One Webview, затем другие линейные макеты и т.д. Проблема в том, что WebView не прокручивается. Scroll прослушивает только ScrollView. Любые предложения?


<ScrollView >
    <TextView />
    <WebView />              <-- this does not scroll
    <TextView />
</ScrollView >
4b9b3361

Ответ 1

Вот решение. Найдено в Интернете. У меня есть подклассы WebView, и я использую метод requestDisallowInterceptTouchEvent(true);, чтобы позволить моему веб-просмотру обрабатывать событие прокрутки.

TouchyWebView.java

package com.mypackage.common.custom.android.widgets

public class TouchyWebView extends WebView {

    public TouchyWebView(Context context) {
        super(context);
    }

    public TouchyWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        requestDisallowInterceptTouchEvent(true);
        return super.onTouchEvent(event);
    }          
}

И в layout.xml

<com.mypackage.common.custom.android.widgets.TouchyWebView 
                android:id="@+id/description_web"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                 />

Ответ 2

Решение, предоставляемое @panos, работает, но оно все еще имеет проблемы при использовании с ScrollView. Следующая улучшенная версия преодолевает эту проблему.

public class TouchyWebView extends WebView {

public TouchyWebView(Context context) {
  super(context);
}

public TouchyWebView(Context context, AttributeSet attrs) {
  super(context, attrs);
}

public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
}

    @Override
    public boolean onTouchEvent(MotionEvent event) {

  //Check is required to prevent crash
  if (MotionEventCompat.findPointerIndex(event, 0) == -1) {
    return super.onTouchEvent(event);
  }

  if (event.getPointerCount() >= 2) {
    requestDisallowInterceptTouchEvent(true);
  } else {
    requestDisallowInterceptTouchEvent(false);
  }

  return super.onTouchEvent(event);
}

@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
  super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
  requestDisallowInterceptTouchEvent(true);


 }

  }

Кроме того, для вашего TouchyWebView могут потребоваться следующие настройки.

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);

Ответ 3

Решение Panos для меня достаточно с одним исключением... Моя фиксированная высота (200dp) WebView может быть пустой или может загружать много контента. Таким образом, это может быть или не быть прокручиваемым "самим собой". Решение Panos потребляет MotionEvent всегда, поэтому, когда WebView пуст и пользователь нажимает WebView и прокручивается, тогда WebView не будет прокручиваться (потому что нет содержимого) и прокручиваемого родителя также, вызывают WebView "ласточки" MotionEvent - так что ничего не происходит. Я добавил небольшой оператор if для ожидаемого поведения:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(computeVerticalScrollRange() > getMeasuredHeight())
        requestDisallowInterceptTouchEvent(true);
    return super.onTouchEvent(event);
}
  • когда WebView пуст и не вертикально-прокручивается, а затем computeVerticalScrollRange() == getMeasuredHeight()
  • когда WebView имеет контент длиннее его высоты (прокручивается), тогда computeVerticalScrollRange() > getMeasuredHeight()

Ответ 4

Просто добавьте одну строку в файл класса

mWebview.setNestedScrollingEnabled(true);

или добавить тег Webview в XML

android:nestedScrollingEnabled="true"

Предупреждение: только для API 21 и 21+

Ответ 5

Работа с решениями @Panos и @Dipendra У меня все еще были проблемы с mapview внутри scrollview. Он не будет последовательно прокручивать по вертикали, и методы были бы устаревшими, поэтому я разработал этот трюк, который я использую с mapview внутри scrollviews, и отлично работает. Надеюсь, это поможет некоторым из вас.

public class TouchyWebView extends WebView {
ViewParent mViewParent;

public TouchyWebView(Context context) {
    super(context);
}

public TouchyWebView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
    mViewParent = viewParent;
}


@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (null == mViewParent) {
                getParent().requestDisallowInterceptTouchEvent(true);
            } else {
                mViewParent.requestDisallowInterceptTouchEvent(true);
            }
            break;
        case MotionEvent.ACTION_UP:
            if (null == mViewParent) {
                getParent().requestDisallowInterceptTouchEvent(false);
            } else {
                mViewParent.requestDisallowInterceptTouchEvent(false);
            }
            break;
        default:
            break;
    }
    return super.onTouchEvent(event);
}

@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
    requestDisallowInterceptTouchEvent(true);


}

}

Я также следил за советом @Dipendra о настройках элементов управления.

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);

Ответ 7

Вы можете изменить на 3 макета:

  • Первый заголовок TextView
  • WebView - основной макет
  • Второй TextView - нижний колонтитул


WebView web = (WebView) findViewById(R.id.webView);
View header = getLayoutInflater().inflate(R.layout.header_layout, null);
View footer = getLayoutInflater().inflate(R.layout.foorer_layout, null);
web.addHeaderView(headerComment);
web.addFooterView(footerComment);