programacion - Compruebe si Android WebView consume eventos táctiles
manual de programacion android pdf (4)
Este código manejará sus eventos de desplazamiento en una vista web. Esto captura los eventos de clic y clic arriba, y compara las posiciones de cada uno. No importa que el contenido dentro de la vista web sea desplazable, solo compare las coordenadas en el área de la vista web.
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;
}
}
También puede intentar controlar la velocidad del deslizamiento, para detectarlo como un deslizamiento o desplazamiento real.
Espero que eso te ayude.
Version corta
¿Cómo puedo detectar si Android WebView consumió un evento táctil?
onTouchEvent
siempre devuelve verdadero y
WebViewClient
de
onUnhandledInputEvent
nunca se activa.
Versión detallada
Tengo múltiples WebViews dentro de TwoDScrollView. Como su nombre lo indica, TwoDScrollView se puede desplazar tanto vertical como horizontalmente. El contenido de TwoDScrollView se puede acercar / alejar. Cuando el usuario arrastra su dedo o usa pellizcar para hacer zoom, quiero enviar el evento táctil para:
- WebView si su contenido es desplazable / ampliable (es decir, solo el interior de WebView se desplazará / ampliará)
- TwoDScrollView si la condición anterior es falsa (todo el contenido de TwoDScrollView se desplazará / ampliará)
Lo he logrado parcialmente mediante el uso de los métodos
canScrollHorizontally
y
canScrollVertically
.
Pero estos métodos solo funcionan para el "desplazamiento nativo".
Sin embargo, en algunos casos, algunos JavaScript dentro de WebView consumen el evento táctil, por ejemplo, Google Maps.
En este caso, los métodos devuelven falso.
¿Hay alguna forma de averiguar si el contenido de WebView consume los eventos táctiles, es decir, es desplazable / ampliable?
No puedo cambiar el contenido de WebView, por lo tanto, mi pregunta es diferente de
esta
.
He considerado verificar los controladores táctiles ejecutando algo de JavaScript dentro de la vista web mediante el método evalJavaScript, pero de acuerdo con esta respuesta no hay una manera fácil de lograr esto y también la página puede tener otros iframes anidados. Cualquier ayuda será apreciada.
Lo que ya he probado
-
onTouchEvent
de WebView y leísuper.onTouchEvent()
que siempre devuelve verdadero, sin importar qué. -
canScrollHorizontally
ycanScrollVertically
solo resuelven parcialmente este problema, como se mencionó anteriormente -
onScrollChanged
tampoco es útil -
WebViewClient.onUnhandledInputEvent
nunca se activa -
Pensé en usar JavaScript a través de
evaluateJavaScript
, pero es una solución muy complicada y fea. -
Traté de rastrear el MotionEvent por
Debug.startMethodTracing
. Descubrí que se propaga de la siguiente manera:-
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
-
Según
el código fuente de ContentViewCore,
el evento táctil termina en un método nativo
nativeOnTouchEvent
y no sé qué más sucede con él. De todos modos,onTouchEvent
siempre devuelve verdadero e incluso si fuera posible averiguar en algún lugar si el evento se consumió o no, requeriría el uso de métodos privados que también es bastante feo.
-
Nota
No necesito saber cómo interceptar eventos táctiles enviados a WebView, sino si WebView los está consumiendo, es decir, si los está utilizando para hacer algo, como desplazarse, arrastrar, etc.
Intente configurar
android:isClickable="true"
en el XML y cree un
onClickListener
en el código Java.
Puede pasar todos los eventos
touch
a
GestureDetector
anulando
onTouchEvent
de
WebView
, para que pueda saber
cuándo Android WebView está consumiendo eventos táctiles en cualquier lugar, en cualquier momento
al escuchar
GestureDetector
.
Intenta así:
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();
}
}
Espero que te inspires.
Según este informe de problema , no es posible. Si el código web está bajo su control, puede implementar alguna interfaz JavaScript para solucionar esto. Si no, me temo que no hay solución aquí.