2016-01-14 3 views
12

У меня есть веб-страницу для тестирования (https://storage.googleapis.com/htmltestingbucket/nested_scroll_helper.html), который просто выводит счетчик события прокрутки HTML-поймал в фиксированном заголовкеHTML прокрутке события в WebView Android, которая находится внутри ScrollView

Когда Android WebView является единственным прокручиваемым элементом во фрагменте, все отлично, и WebView отправляет события прокрутки на страницу

Если я хочу добавить собственные элементы выше и ниже WebView, тогда все становится намного сложнее.

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:custom="http://schemas.android.com/apk/res-auto" 
    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="wrap_content" 
      android:padding="20dp" 
      android:text="SOMETHING ABOVE THE WEBVIEW" /> 

     <WebView 
      android:id="@+id/webview" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" /> 

     <TextView 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:padding="20dp" 
      android:text="SOMETHING BELOW THE WEBVIEW" /> 

    </LinearLayout> 
</ScrollView> 

Я знаю, что это не хорошо иметь WebView внутри ScrollView, но я должен обеспечить единый опыт скроллинг с гибридным контентом и собственно прокрутки событий в HTML-документе. я нашел много вопросов по этому вопросу, но я был в состоянии создать полное решение от конца до конца


Кроме того, я знаю, что ворс имеет OFFICAL проверки, что:

NestedScrolling --------------- Резюме: Вложенные скроллинг виджеты

Приоритет: 7/10 Серьезность: Предупреждение Категория: Корректность

с прокруткой виджет, таких как SCRo llView не должны содержать вложенные прокрутки виджетов, так как это имеет различные вопросы юзабилити

И все же, я не могу реализовать содержимое веб-просмотра в родной, так что я нужен альтернативный способ сделать это

+0

См. Принятый ответ http://stackoverflow.com/questions/9718245/webview-in-scrollview – MASh

+0

Я видел его перед отправкой, обратите внимание: «Так как Android KitKat ни один из описанных ниже решений не работает - вы нужно будет искать различные подходы, например, FadingActionBar Мануэля Пейнадо, который предоставляет прокручивающийся заголовок для WebViews «. -> Я не ищу проблему с родным элементом над веб-просмотром, это намного проще –

+0

Я не ищу проблему с собственным элементом ТОЛЬКО над веб-просмотром, это намного проще –

ответ

1

Содержать Webview внутри scrollview здесь вам нужно измерить высоту веб-представления и установить его в параметрах макета.

Здесь я попытался дать ответ на прокручиваемый веб-просмотр.

<ScrollView 
     android:layout_width="fill_parent" android:background="#FF744931" 
     android:layout_height="fill_parent"> 

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

      <TextView 
       android:id="@+id/txtVoiceSeachQuery" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:textColor="#FF0000" 
       android:textSize="26sp" /> 

      <TextView 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:padding="20dp" 
       android:text="SOMETHING ABOVE THE WEBVIEW" /> 

      <com.example.ScrollableWebView 
       android:id="@+id/webview" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       app:isWebViewInsideScroll="true" /> 

      <TextView 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:padding="20dp" 
       android:text="SOMETHING BELOW THE WEBVIEW" /> 

     </LinearLayout> 
    </ScrollView> 

Рез/значения/attrs.xml

Чтобы добавить атрибут для пользовательского элемента управления

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
<declare-styleable name="ScrollableWebView"> 
    <attr name="isWebViewInsideScroll" format="boolean"></attr> 
</declare-styleable> 
</resources> 

ScrollableWebView

public class ScrollableWebView extends WebView { 
    private boolean webViewInsideScroll = true; 
    public static final String RESOURCE_NAMESPACE = "http://schemas.android.com/apk/res-auto"; 

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

    public ScrollableWebView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setWebViewInsideScroll(attrs.getAttributeBooleanValue 
       (RESOURCE_NAMESPACE, "isWebViewInsideScroll", true)); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     if (isWebViewInsideScroll()) { 
      int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST); 
      super.onMeasure(widthMeasureSpec, expandSpec); 
      ViewGroup.LayoutParams params = getLayoutParams(); 
      params.height = getMeasuredHeight(); 
      setLayoutParams(params); 
     } else { 
      super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     } 
    } 

    public boolean isWebViewInsideScroll() { 
     return webViewInsideScroll; 
    } 

    public void setWebViewInsideScroll(boolean webViewInsideScroll) { 
     this.webViewInsideScroll = webViewInsideScroll; 
    } 
} 

Чтобы получить значение атрибута, вы также можете использовать Stylable, но здесь я это сделал, не используя его.

ScrollableWebView webview = (ScrollableWebView) findViewById(R.id.webview); 
     webview.loadUrl("https://storage.googleapis.com/htmltestingbucket/nested_scroll_helper.html"); 

Ниже ссылка выхода

Если вы не хотите, чтобы создать атрибут файла & добавить Пользовательские атрибуты в рес/значений/ATTRS.xml, то вы можете игнорировать этот файл & check this pastebin здесь я дал без каких-либо специальных атрибутов, таких как isWebViewInsideScroll. вы также можете удалить его из макета xml. Дайте мне знать, если угодно.

+0

Спасибо за усилия и инвестиции, но ваш ответ не очень хорош, так как он не решает, что я просил. на самом деле скриншоты, которые вы предоставили, уже показали это. Просто откройте ссылку, которую я предоставил в Chrome или на рабочем столе, посмотрите, как она себя ведет (или любой браузер). Черный текст должен оставаться на вершине веб-просмотра и распечатывать события прокрутки JS, которые он получил. Фактически, вам не нужно, чтобы onMeasure() вы написали, чтобы поместить WebView в прокрутку. –

+0

отлично работает для интеграции внутри переработку. хотя использование WebView.getSettings(). setUseWideViewPort (true), похоже, испортит его. для меня это отлично работает. спасибо – Ramin

0

если вы размещаете вы Webview внутри Scrollview вы не получите HTML эффект прокрутки, потому что ваше содержание WebView не будет прокручиваться (он будет помещен полный lengtth внутри Scrollview.)
Чтобы справиться с вашей необходимости размещать элементы выше и ниже вас может прослушивать прокрутку webview и использовать DragViewHelper или nineoldandroids для перемещения header и footer, так что пользователь будет думать, что это один элемент (вам не требуется прокрутка).

webView.setOnScrollChangeListener(new View.OnScrollChangeListener() { 
    @Override 
    public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { 

     ViewHelper.setTranslationY(headerTextView, -event.getY()); 

    } 
}); 


public class ObservableWebView extends WebView { 
private OnScrollChangeListener onScrollChangeListener; 

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

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

public ObservableWebView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
} 

@Override 
protected void onScrollChanged(int l, int t, int oldl, int oldt) { 
    super.onScrollChanged(l, t, oldl, oldt); 
    if (onScrollChangeListener != null) { 
     onScrollChangeListener.onScrollChange(this, l, t, oldl, oldt); 
    } 
} 

public void setOnScrollChangeListener(OnScrollChangeListener onScrollChangeListener) { 
    this.onScrollChangeListener = onScrollChangeListener; 
} 

public OnScrollChangeListener getOnScrollChangeListener() { 
    return onScrollChangeListener; 
} 

public interface OnScrollChangeListener { 
    /** 
    * Called when the scroll position of a view changes. 
    * 
    * @param v   The view whose scroll position has changed. 
    * @param scrollX Current horizontal scroll origin. 
    * @param scrollY Current vertical scroll origin. 
    * @param oldScrollX Previous horizontal scroll origin. 
    * @param oldScrollY Previous vertical scroll origin. 
    */ 
    void onScrollChange(WebView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY); 
} 
} 

Этот пример должен помочь вам скрыть header, я использовал nineoldandroid для него

+0

Я попробую, моя проблема в том, что вокруг моего веб-браузера есть много элементов, включая всплывающее окно и т. д. Так что очень (!!!) громоздко управлять всем своим. Мне интересно, могу ли я инкапсулировать его в свое собственное представление, которое расширяет WebView, но также реализует все функции scrollview. Проблема в том, что мне также нужно расширить FrameLayout, чтобы реализовать свой собственный вид прокрутки. Каждая дорога, которую я заглядываю, становится более беспорядочной. –

+0

Но как примечание, хотя я очень ценю ваш ответ, мой вопрос озаглавлен «Прокрутка HTML-событий в Android WebView, находящемся внутри ScrollView», и вы предлагаете мне отказаться от ScrollView. Я поставил на это щедрость, потому что я не хочу отказываться от ScollView ... Мне это нужно. Вопрос был упрощен, чтобы показать только текст выше и ниже, реальное приложение намного сложнее. –

0

на самом деле это не так хорошо положить прокручивать вид в другой. Попробуйте использовать это:

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

И

<WebView 
    android:id="@+id/webview" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="1"/> 
0

кажется самый элегантный способ, которым я мог бы найти, чтобы справиться с этим следующим образом: - Слушайте SrollView свитков: Вы можете использовать ObservableScrollView или звоните setOnScrollChangeListener() от уровня API 23 - Вычислить прокрутки Y смещение в пикселях - Вызов WebView.evaluateJavascript() - Передайте это все детали события прокрутки Так общие понятия, проходящая: "$ (document) .trigger ('scroll');" как первый парам evaluateJavascript

Я до сих пор тестирование деталей и разработка перегибов, но кажется, что лучший способ пойти, я буду стараться, чтобы изменить этот ответ с деталями, как я решить эту

If в любом случае имеет лучшее решение для Я хотел бы услышать его

0

у меня такая же проблема в последнее время, и я нашел свои сообщения здесь :)

у меня есть WebView вложенного в ScrollVIew. И страница, которую я загрузил в WebView, нужно вызвать функцию JS, когда она прокручивается до конца, но в режиме прокрутки веб-страница window.onscroll = functionXXX() {} никогда не вызывается.

Наконец, я должен установить OnScrollListener к ScrollView и вызвать мою функцию JS вручную кодом ниже

@Override 
public void onScroll(int scrollY) { 
    if (!scrollView.canScrollVertically(scrollY)) { 
     mWebView.loadUrl("javascript:functionXXX();"); 
    } 
} 

Может быть, наши ситуации бывают разные, но я надеюсь, что это будет дать и вдохновение :)

+0

У меня был другой случай, но спасибо за обновление. вам следует, скорее всего, называть javascript() вместо loadUrl. поскольку loadUrl запускает некоторые прослушиватели событий –