2015-04-23 9 views
58

Versione corta

Come posso rilevare se Android WebView ha consumato un evento tattile? onTouchEvent restituisce sempre true e WebViewClient 's onUnhandledInputEvent non viene mai attivato.Verificare se Android WebView sta consumando eventi touch

un particolare

ho più WebViews all'interno di un TwoDScrollView. Come suggerisce il nome, il TwoDScrollView può essere fatto scorrere sia verticalmente che orizzontalmente. I contenuti di TwoDScrollView possono essere ingranditi/rimpiccioliti. Quando l'utente trascina il dito o usa pinch-to-zoom, voglio inviare l'evento touch per:

  • WebView se il suo contenuto è scorrevole/stradale (cioè solo l'interno del WebView scorrerà/zoom)
  • TwoDScrollView se la condizione di cui sopra è falsa (tutti i contenuti del TwoDScrollView scorrerà/zoom)

ho parzialmente raggiunto questo in base alle canScrollHorizontally e canScrollVertically metodi. Ma questi metodi funzionano solo per "scrolling nativo". Tuttavia, in alcuni casi, alcuni JavaScript all'interno di WebView consumano l'evento touch, ad esempio Google Maps. In questo caso, i metodi restituiscono false. C'è un modo per scoprire se i contenuti di WebView consumano gli eventi touch, cioè è scorrevole/zoomabile? Non riesco a modificare il contenuto di WebView, quindi la mia domanda è diversa da this one.

Ho considerato il controllo dei gestori di tocco eseguendo alcuni JavaScript nella Webview tramite il metodo evaluateJavaScript, ma in base a this answer non esiste un modo semplice per raggiungere questo obiettivo e anche la pagina può avere altri iframe nidificati. Qualsiasi aiuto sarà apprezzato.

Quello che ho già provato

  1. ho overrode WebView di onTouchEvent e leggere super.onTouchEvent() che restituisce sempre vero, non importa quale.
  2. canScrollHorizontally e canScrollVertically solo in parte risolvere questo problema, come detto sopra
  3. onScrollChanged non è utile né
  4. WebViewClient.onUnhandledInputEvent non è mai attivato
  5. ho considerato utilizzando JavaScript tramite evaluateJavaScript, ma è una soluzione molto complicata e brutta
  6. Ho provato a rintracciare MotionEvent tramite Debug.startMethodTracing. Ho scoperto che si propaga come segue:
    • android.webkit.WebView.onTouchEvent
    • com.android.webview.chromium.WebViewChromium.onTouchEvent
    • com.android.org.chromium.android_webview.AwContents.onTouchEvent
    • com.android.org.chromium.android_webview.AwContents$AwViewMethodsImpl.onTouchEvent
    • com.android.org.chromium.content.browser.ContentViewCore.onTouchEventImpl
    • Secondo ContentViewCore's source code l'evento di tocco finisce in un metodo nativo nativeOnTouchEvent e io don So cosa accadrà di più.Ad ogni modo, onTouchEvent restituisce sempre true e anche se è stato possibile scoprire da qualche parte se l'evento è stato consumato o meno, richiederebbe l'utilizzo di metodi privati ​​che è anche abbastanza brutto.

Nota

Non ho bisogno di sapere come intercettare eventi di tocco inviati a WebView, ma se il WebView li sta consumando, cioè li sta usando per fare qualsiasi cosa, come ad esempio lo scorrimento, trascinando ecc

+0

Hai provato a guardare questo link http://stackoverflow.com/questions/12578895/how-to-detect-a-swipe-gesture-on-webview. – Smashing

+0

attendi che non sono chiaro. hai provato a chiamare semplicemente webview.setOnTouchListener? – dabluck

+0

@Smashing: so come intercettare gli eventi di tocco su WebView, ma ho bisogno di sapere se WebView li ha consumati. Ad esempio, se l'utente sta trascinando il dito e alcuni contenuti in WebView lo stanno utilizzando (ad esempio, la mappa sta scorrendo), ho bisogno di ottenere "true". In caso contrario, se nulla nella WebView utilizza il tocco (nessun contenuto scorrevole ecc.), Ho bisogno di ottenere "false" in modo che io possa utilizzare l'evento di tocco per mio uso personale. –

risposta

0

è possibile passare tutti gli eventi touch a GestureDetector ridefinendo onTouchEvent di WebView, in modo da poter sapere quando Android WebView sta consumando eventi touch, sempre e ovunque da lis tenersi a GestureDetector.

Prova in questo modo:

public class MyWebView extends WebView { 
    private Context context; 
    private GestureDetector gestDetector; 

    public MyWebView(Context context) { 
     super(context); 

     this.context = context; 
     gestDetector = new GestureDetector(context, gestListener); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     return gd.onTouchEvent(event); 
    } 

    GestureDetector.SimpleOnGestureListener gestListener= new GestureDetector.SimpleOnGestureListener() { 
     public boolean onDown(MotionEvent event) { 
      return true; 
     } 

     public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { 
      //if (event1.getRawX() > event2.getRawX()) { 
      // show_toast("swipe left"); 
      //} else { 
      // show_toast("swipe right"); 
      //} 
      //you can trace any touch events here 
      return true; 
     } 
    }; 

    void show_toast(final String text) { 
     Toast t = Toast.makeText(context, text, Toast.LENGTH_SHORT); 
     t.show(); 
    } 
} 

Spero che essere ispirato.

+0

Capisco che GestureDetector mi aiuti a trasformare le serie raw di MotionEvents in alcuni gesti come fling, scroll double tap ecc., Ma non risolve il mio problema, il che sta determinando se WebView utilizzava l'evento touch per una gestione interna. –

+0

Gestione interna? puoi leggere i codici sorgente di 'WebView'. – SilentKnight

-1

Questo codice gestirà gli eventi di scorrimento in una visualizzazione Web. Questo cattura il click down e gli eventi click up, e confronta le posizioni di ciascuno. Non importa che il contenuto all'interno della webview sia scorrevole, basta confrontare le coordinate nell'area della webview.

public class MainActivity extends Activity implements View.OnTouchListener, Handler.Callback { 

    private float x1,x2,y1,y2; //x1, y1 is the start of the event, x2, y2 is the end. 
    static final int MIN_DISTANCE = 150; //min distance for a scroll event 

    private static final int CLICK_ON_WEBVIEW = 1; 
    private static final int CLICK_ON_URL = 2; 
    private static final int UP_ON_WEBVIEW = 3; 


    private final Handler handler = new Handler(this); 

    public WebView webView; 
    private WebViewClient client; 
    private WebAppInterface webAppInt = new WebAppInterface(this); 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 

     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     webView = (WebView)findViewById(R.id.myWebView); 
     webView.setOnTouchListener(this); 

     client = new WebViewClient(); 
     webView.setWebViewClient(client);   
     webView.loadDataWithBaseURL("file:///android_asset/", "myweb.html", "text/html", "UTF-8", ""); 

    } 

//HERE START THE IMPORTANT PART 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     if (v.getId() == R.id.myWebView && event.getAction() == MotionEvent.ACTION_DOWN){ 
      x1 = event.getX(); 
      y1 = event.getY(); 
      handler.sendEmptyMessageDelayed(CLICK_ON_WEBVIEW, 200); 
     } else if (v.getId() == R.id.myWebView && event.getAction() == MotionEvent.ACTION_UP){ 
      x2 = event.getX(); 
      y2 = event.getY(); 

      handler.sendEmptyMessageDelayed(UP_ON_WEBVIEW, 200); 
     } 

     return false; 
    } 

    @Override 
    public boolean handleMessage(Message msg) { 
     if (msg.what == CLICK_ON_URL){ //if you clic a link in the webview, thats not a scroll 
      handler.removeMessages(CLICK_ON_WEBVIEW); 
      handler.removeMessages(UP_ON_WEBVIEW); 
      return true; 
     } 
     if (msg.what == CLICK_ON_WEBVIEW){ 
      //Handle the click in the webview 
      Toast.makeText(this, "WebView clicked", Toast.LENGTH_SHORT).show(); 
      return true; 
     } 
     if (msg.what == UP_ON_WEBVIEW){ 
      float deltaX = x2 - x1; //horizontal move distance 
      float deltaY = y2 - y1; //vertical move distance 
      if ((Math.abs(deltaX) > MIN_DISTANCE) && (Math.abs(deltaX) > Math.abs(deltaY))) 
      { 
       // Left to Right swipe action 
       if (x2 > x1) 
       { 
        //Handle the left to right swipe 
        Toast.makeText(this, "Left to Right swipe", Toast.LENGTH_SHORT).show(); 
       } 

       // Right to left swipe action 
       else 
       { 
        //Handle the right to left swipe 
        Toast.makeText(this, "Right to Left swipe", Toast.LENGTH_SHORT).show(); 
       } 

      } 
      else if ((Math.abs(deltaY) > MIN_DISTANCE) && (Math.abs(deltaY) > Math.abs(deltaX))) 
      { 
       // Top to Bottom swipe action 
       if (y2 > y1) 
       { 
        //Handle the top to bottom swipe 
        Toast.makeText(this, "Top to Bottom swipe", Toast.LENGTH_SHORT).show(); 
       } 

       // Bottom to top swipe action -- I HIDE MY ACTIONBAR ON SCROLLUP 
       else 
       { 
        getActionBar().hide(); 
        Toast.makeText(this, "Bottom to Top swipe [Hide Bar]", Toast.LENGTH_SHORT).show(); 
       } 
      } 
      return true; 
     } 
     return false; 
    } 
} 

Si può anche provare a controllare la velocità del colpo, per rilevarlo come un vero colpo o scorrimento.

Spero che questo ti aiuti.

-1

Provare a impostare android:isClickable="true" nell'XML e creare un codice onClickListener nel codice Java.

1

In base a questo issue report, non possibile. Se il codice web è sotto il tuo controllo, puoi implementare alcuni JavaScriptInterface per risolvere il problema. In caso contrario, temo che non ci sia una soluzione qui.

Problemi correlati