我有一个看起来像这样的页面*:
<ScrollView>
<WebView/>
<WebView/>
<WebView/>
</Scrollview>
*不是实际布局,但足以解决问题并使问题更加清晰。
我不知道WebView
看起来到底是怎样的,因为它可能变化很大。 WebView
可以包含可滚动列表。
我想实现这种滚动行为:
这是两个WebView(带有蓝色标题的WebView和带有绿色标题的WebView)。我只想在列表中拖动时在蓝色WebView
中滚动列表。如果我在其他地方触摸(例如在蓝色或绿色标题上),我想滚动ScrollView
。
我尝试解决这个问题的CustomRenderer
为WebView
,我在this thread in the Xamarin forums中找到了这个问题:
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
Control.Touch -= Control_Touch;
}
if (e.NewElement != null)
{
Control.Touch += Control_Touch;
}
}
void Control_Touch(object sender, TouchEventArgs e)
{
// Executing this will prevent the Scrolling to be intercepted by parent views
switch (e.Event.Action)
{
case MotionEventActions.Down:
Control.Parent.RequestDisallowInterceptTouchEvent(true);
break;
case MotionEventActions.Up:
Control.Parent.RequestDisallowInterceptTouchEvent(false);
break;
}
// Calling this will allow the scrolling event to be executed in the WebView
Control.OnTouchEvent(e.Event);
}
这几乎完成了这项工作,我现在可以在WebView
内的列表中滚动,但如果我点击ScrollView
中的任何其他位置,它就不会再滚动WebView
1}}。
所以我试着检查内部列表的高度:
case MotionEventActions.Down:
if (ComputeVerticalScrollRange() > MeasuredHeight)
Control.Parent.RequestDisallowInterceptTouchEvent(true);
break;
case MotionEventActions.Up:
if (ComputeVerticalScrollRange() > MeasuredHeight)
Control.Parent.RequestDisallowInterceptTouchEvent(false);
break;
MeasuredHeight
是WebView
的高度。 ComputeVerticalScrollRange()
将始终返回与MeasuredHeight
tho相同的高度。因此,一个可能的解决方案是在WebView
中获取内部列表的高度,但我不知道如何得到它(我是Android的新手)。也许,甚至还有其他解决方案。
答案 0 :(得分:1)
对于代码Control.Parent.RequestDisallowInterceptTouchEvent(true);
,您需要确保此Control.Parent
确实是ScrollViewer
。
AFAIK,为了实现每个平台的视图,它使用渲染器,Control.Parent
这里是WebViewRenderer
,所以我认为你需要的是这样的:
Control.Parent.Parent.Parent.Parent.RequestDisallowInterceptTouchEvent(true);
真正的问题是何时将其设置为true或false,您可以修改Control_Touch
事件,例如:
private void Control_Touch(object sender, TouchEventArgs e)
{
var viewheight = Control.MeasuredHeight;
var height = (int)Math.Floor(Control.ContentHeight * Control.Scale);
switch (e.Event.Action)
{
case MotionEventActions.Down:
downY = e.Event.GetY();
mAction = ActionState.None;
Control.Parent.Parent.Parent.Parent.RequestDisallowInterceptTouchEvent(true);
break;
case MotionEventActions.Move:
upY = e.Event.GetY();
var delta = downY - upY;
if (Math.Abs(delta) > MIN_DISTANCE)
{
if (delta < 0)
{
mAction = ActionState.TB;
//top reached
if (Control.ScrollY == 0)
{
Control.Parent.Parent.Parent.Parent.RequestDisallowInterceptTouchEvent(false);
}
}
else if (delta > 0)
{
mAction = ActionState.BT;
//bottom reached
if (Control.ScrollY + viewheight + 5 >= height)
{
Control.Parent.Parent.Parent.Parent.RequestDisallowInterceptTouchEvent(false);
}
}
}
break;
case MotionEventActions.Up:
Control.Parent.Parent.Parent.Parent.RequestDisallowInterceptTouchEvent(true);
break;
}
Control.OnTouchEvent(e.Event);
}
我使用了两个自定义WebView
来测试我的演示,其目的是在WebView
到达顶部并且从上到下滚动时禁用滚动,反之亦然。你可以尝试一下。