2012-11-06 20 views
23

W mojej aplikacji mam ScrollView, który zawiera liniowe widoki, niektóre widoki tekstu i jeden widok Web, a następnie inne układy liniowe itp. Problem polega na tym, że WebView nie przewija. Przewijanie nasłuchuje tylko w ScrollView. Jakieś sugestie?Android WebView wewnątrz ScrollView przewija tylko scrollview


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

Odpowiedz

63

Oto rozwiązanie. Znaleziono online. Poddałem podklasę WebView i używam metody requestDisallowInterceptTouchEvent(true);, aby umożliwić mojej przeglądarce obsługę zdarzenia przewijania.

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); 
    }   
} 

I layout.xml

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

+1 ... Działa. –

+2

To powoduje zerwanie po dotknięciu poza 'WebView'. – theblang

+0

@mattblang Dotknij raz ponownie webview, a następnie spróbuj ponownie przewinąć. – Panos

-9

można zmienić na 3 układy:

  1. Pierwszy TextView - Nagłówek
  2. WebView - układ główny
  3. drugie TextView - stopka


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); 
+0

Mój widok przewijania jest dostępny, ponieważ elementy te nie mieszczą się na ekranie. W moim przykładzie dodałem tylko jeden widok tekstowy powyżej i jeden widok tekstowy poniżej. Ale w rzeczywistości istnieją inne względne układy, są tam widoki, widok jest gdzieś pośrodku, a inne ... Potrzebuję więc widoku przewijania, żeby zobaczyć wszystko. – Panos

+0

Spróbuj tego [rozwiązanie] (http://stackoverflow.com/questions/9718245/webview-in-scrollview) –

+4

WebView nie ma metod "addHeaderView" ani "addFooterView", ListView ma te metody. To nie jest rozwiązanie. – ismailarilik

6

Rozwiązanie dostarczone przez @panos prac, ale nadal ma problemy w przypadku korzystania z Scrollview. Następująca ulepszona wersja rozwiązuje ten problem.

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); 


} 

    } 

Dodatkowo, możesz chcieć mieć następujące ustawienia dla TouchyWebView.

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

z twoim rozwiązaniem 'WebView' jest przewijane tylko dwoma palcami, z jednym palcem tylko rodzic przewija ... nie jest tak intuicyjny: / – snachmsm

2

Panos rozwiązanie jest wystarczające dla mnie z jednym wyjątkiem ... Mój stałej wysokości (200dp) WebView może być pusta lub mogła załadować dużo treści. Więc może być lub może nie być przewijane "samo w sobie". Rozwiązanie Panos zużywa zawsze MotionEvent s, więc gdy WebView jest puste i użytkownik dotknie WebView i spróbuje przewinąć, WebView nie będzie przewijać (ponieważ nie ma zawartości) i przewijać rodzica również, ponieważ WebView "połknie" MotionEvent - więc nic się nie dzieje. Dodałem mały if oświadczenie dla oczekiwanego zachowania:

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if(computeVerticalScrollRange() > getMeasuredHeight()) 
     requestDisallowInterceptTouchEvent(true); 
    return super.onTouchEvent(event); 
} 
  • gdy WebView jest pusta i nie-pionowym przewijane następnie computeVerticalScrollRange() == getMeasuredHeight()
  • gdy WebView mieć zawartość dłużej niż jego wysokość (jest Przesuwne) następnie computeVerticalScrollRange() > getMeasuredHeight()
0

Praca nad rozwiązaniami @Panos i @Dipendra Nadal miałem pewne problemy z widokiem mapy wewnątrz przewijania. Nie byłby spójny w pionie, a metody były przestarzałe, więc opracowałem tę sztuczkę, której używam w widoku mapy wewnątrz przewijania i działa świetnie. Mam nadzieję, że to pomoże kilku z was.

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); 


} 

}

ja również po @Dipendra informacje o ustawieniach kontroli.

Powiązane problemy