我读了许多关于在WebViews中缩放主题的门票,并没有找到我的案例的答案。
这是我的设置:
我使用的是自定义网页视图,通常包含以下设置:
getSettings().setBuiltInZoomControls(false);
getSettings().setSupportZoom(false);
getSettings().setUseWideViewPort(true);
getSettings().setLoadWithOverviewMode(true);
让我在这里注意,我依赖于OverviewMode以及WideViewPort来扩展我的WebView。
我也覆盖了我的OnTouchEvent,并将所有合适的事件委托给Gesture探测器:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) return true;
return super.onTouchEvent(event);
}
这是它的侦听器实现,它拦截所有doubleTap事件:
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
// Do nothing!
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
// Do nothing!
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// Do nothing!
return true;
}
此外,我覆盖了与缩放相关的这两个WebView方法:
@Override
public boolean zoomIn() {
return true;
}
@Override
public boolean zoomOut() {
return true;
}
除了所有这些选项之外,某个抽头频率将导致我的webview放大/缩小。 我没有找到一个禁用这种缩放的选项,此Zoom的MotionEvent似乎不适用于GestureDetector,并且覆盖zoomIn()zoomOut()方法也没有效果。
任何人都可以帮助我避免使用WebView的双击缩放行为吗?
答案 0 :(得分:5)
实现目标有两种方法:
方法1
像这样实施GestureDetector.OnDoubleTapListener
:
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return false; //Nothing
}
@Override
public boolean onDoubleTap(MotionEvent e) {
//Indicates that this implementation has handled the double tap.
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
//Indicates that this implementation has handled the double tap.
return true;
}
并将其附加到GestureDetector
,如下所示:
gestureDetector.setOnDoubleTapListener(this);
方法2
您也可以使用WebSettings.setUseWideViewPort(false);
并手动计算视图的大小。
这些方法可以帮助您实现显示所有内容的非可缩放网页视图。
public int getWindowWidth(Activity activity) {
Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
return width;
}
public int getInitialScale(Activity activity, int websiteWidth) {
return (getWindowWidth(activity) / websiteWidth) * 100;
}
答案 1 :(得分:2)
基于Javascript,您的问题有一个很棒的解决方案(因此,如果是这样的话,您必须能够访问远程端的HTML / JS代码)。
使用FastClick library,你需要做的就是添加.js文件,然后调用它:
<script type="application/javascript" src="fastclick.js"></script>
<script language="javascript">
window.addEventListener('load', function() {
FastClick.attach(document.body);
}, false);
</script>
这将摆脱双击变焦,并且仍然(在我看来)一个巨大的奖励:所有水龙头快0.3秒,因为系统不再需要等待双击!在Android上查看此示例以查看差异:Practical Example
嗯,我不知道这个解决方案是否适合您的情况,但它是我的Webview项目的完美解决方案。希望它有所帮助!
ps1:你必须在所有页面和框架中添加上面的代码
ps2:捏拉变焦将继续正常工作
答案 2 :(得分:1)
您需要通过
覆盖WebView上的OnTouchListener wv.setOnTouchListener(this);
和内部方法onTouch只检查是否检测到双选项卡然后忽略webview中的放大以强制返回true
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
onTouchEvent(event);
if (doubletab)
return true;
return false;
}
您可以看到如下所示的完整代码:MainActivity.java
package com.example.testwebview;
import android.os.Bundle;
import android.app.Activity;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.View.OnTouchListener;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.TextView;
public class MainActivity extends Activity implements OnGestureListener, OnTouchListener, GestureDetector.OnDoubleTapListener
{
TextView tv;
WebView wv;
GestureDetector gd;
boolean doubletab = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gd = new GestureDetector(this);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.textView1);
wv = (WebView)findViewById(R.id.webView1);
WebSettings setting = wv.getSettings();
setting.setBuiltInZoomControls(false);
setting.setSupportZoom(false);
setting.setUseWideViewPort(true);
setting.setLoadWithOverviewMode(true);
wv.setOnTouchListener(this);
wv.loadUrl("http://www.sanook.com");
}
@Override
public boolean onDoubleTap(MotionEvent arg0) {
tv.setText("double tap");
doubletab = true;
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent arg0) {
tv.setText("double tap event");
doubletab = true;
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent arg0) {
tv.setText("single tap confirm");
doubletab = false;
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onTouchEvent(MotionEvent me)
{
return gd.onTouchEvent(me);
}
@Override
public boolean onDown(MotionEvent arg0) {
tv.setText("down");
doubletab = false;
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,
float arg3) {
tv.setText("fling");
doubletab = false;
// TODO Auto-generated method stub
return false;
}
@Override
public void onLongPress(MotionEvent arg0) {
tv.setText("long press");
doubletab = false;
// TODO Auto-generated method stub
}
@Override
public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
float arg3) {
tv.setText("scroll");
doubletab = false;
// TODO Auto-generated method stub
return false;
}
@Override
public void onShowPress(MotionEvent arg0) {
// TODO Auto-generated method stub
tv.setText("show press");
doubletab = false;
}
@Override
public boolean onSingleTapUp(MotionEvent arg0) {
// TODO Auto-generated method stub
tv.setText("single tab up");
doubletab = false;
return false;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
onTouchEvent(event);
if (doubletab)
return true;
return false;
}
}
和activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="TextView" />
<WebView
android:id="@+id/webView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_below="@+id/textView1" />
</RelativeLayout>
不要忘记在manifest.xml中添加权限
<uses-permission android:name="android.permission.INTERNET" />
答案 3 :(得分:0)
另一种方法(唯一适用于我的方法)是模拟双击之间的远程中间点击,以便WebView不会将它们作为结果进行识别。负坐标可用于此目的,尽管小于-1的任何东西都会减慢甚至打破过程。所以我们需要至少两个点,比如说(0,-1)和(2 * d + 1,-1),其中 d 是它们被认为是双击的点击之间的最大距离。 / p>
webView.setOnTouchListener(new View.OnTouchListener() {
private long lastUp = -1000;
private float lastDownX = -1000;
private float lastDownY = -1000;
private int dtDistance = 0;
private int dtDistanceSquared = 0;
private long dtTime = 0;
private void performTap(View v, int x, int y, long t) {
MotionEvent e_down = MotionEvent.obtain(t, t, MotionEvent.ACTION_DOWN, x, y, 0);
v.dispatchTouchEvent(e_down);
e_down.recycle();
MotionEvent e_up = MotionEvent.obtain(t, t, MotionEvent.ACTION_UP, x, y, 0);
v.dispatchTouchEvent(e_up);
e_up.recycle();
}
private int getRemoteX(float x) {
return Math.round(x > dtDistance + 0.5 ? 0 : 2 * dtDistance + 1);
}
private boolean inRadius(int x0, int y0, float x1, float y1) {
boolean result = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1) <= dtDistanceSquared;
return result;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getY() >= 0) // Otherwise it's a fake tap we simulated
{
if (dtTime == 0)
{
dtDistance = ViewConfiguration.get(v.getContext()).getScaledDoubleTapSlop(); // Maximum distance between taps for them to be considered double tap
dtDistanceSquared = dtDistance * dtDistance;
dtTime = ViewConfiguration.getDoubleTapTimeout(); // Maximum time elapsed between taps for them to be considered double tap
}
switch (event.getAction())
{
case MotionEvent.ACTION_UP:
lastUp = event.getEventTime();
break;
case MotionEvent.ACTION_DOWN:
long t = event.getEventTime();
if (t - lastUp < dtTime * 4/3) // Very rarely just (t - lastUp <= dtTime) doesn't work
{
int x = getRemoteX(event.getX());
if (inRadius(x, -1, lastDownX, lastDownY))
performTap(v, getRemoteX(lastDownX), -1, t); // Otherwise our fake tap would constitute a double tap with the previous real tap
performTap(v, x, -1, t);
}
lastDownX = event.getX();
lastDownY = event.getY();
break;
}
}
return false;
}
});
答案 4 :(得分:0)
如果可能,请替换html中的静态元标记:
<script>
var meta = document.createElement("meta");
meta.setAttribute('name','viewport');
meta.setAttribute('content','width=device-width, user-scalable=no');
document.getElementsByTagName('head')[0].appendChild(meta);
</script>
此外,您可以使用一个漂亮的脚本:FastClick
它不会等待点击事件,所以它更快。
<script type="application/javascript" src="fastclick.js"></script>
<script language="javascript">
window.addEventListener('load', function() {
FastClick.attach(document.body);
}, false);
</script>
然后为您的手势检测器设置双击侦听器。 (在自定义WebView中)
gestureDetector.setOnDoubleTapListener(new OnDoubleTapListener() {
@Override
public boolean onSingleTapConfirmed( MotionEvent e ) {
return false;
}
@Override
public boolean onDoubleTapEvent( MotionEvent e ) {
return true;
}
@Override
public boolean onDoubleTap( MotionEvent e ) {
return true;
}
});
重写onTouchEvent方法(在自定义WebView中):
@Override
public boolean onTouchEvent( MotionEvent event ) {
boolean gestureHandled = gestureDetector.onTouchEvent(event);
int actionMask = event.getActionMasked() & MotionEvent.ACTION_MASK;
int index = ( event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pointId = event.getPointerId(index);
// ignore move events
if (actionMask == MotionEvent.ACTION_MOVE) {
return super.onTouchEvent(event);
}
// cancel detected double taps
if (gestureDetector.onTouchEvent(event)) {
event.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(event);
return true;
}
// if you want to ignore multi touch events/taps
if (pointId != 0) {
System.out.println("KEY multiple points detected");
return true;
}
// use single taps
if (event.getAction() == MotionEvent.ACTION_UP) {
event.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(event);
event.setAction(MotionEvent.ACTION_DOWN);
super.onTouchEvent(event);
event.setAction(MotionEvent.ACTION_UP);
return true;
}
return super.onTouchEvent(event);
}
答案 5 :(得分:-3)
尝试将onDoubleTapEvent onDoubleTap的返回值设为false ....
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
// Do nothing!
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
// Do nothing!
return false;
}