之前在WP8的时候做过WebBrowser相关的笔记,在WP8.1的WebView和WebBrowser有些不一样,在这里做一些笔记

下面分为几个部分

  1、禁止缩放

  2、JS通知后台C#代码(notify)

  3、C#调用JS方法

    动态加载JS文件,动态注册事件方法(eval)

  4、WebView导航

  5、手势(WinJS)

  6、常见问题

1、禁用缩放  

body {
/* Block area from manipulation actions (zoom, pan) */
touch-action: pan-y;
}

  这个值可以禁用掉缩放和横向手势

  关于touch-action参见:https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh767313.aspx?f=255&MSPPError=-2147217396

2、JS通知后台C#代码(notify) 

window.external.notify(msg);

注意:这里的方法名是小写的,在WP8上后面的Notify方法的首字母是大小写都可以

3、C#调用JS方法(InvokeScriptAsync)

  通过后台代码动态加载css,js,动态绑定事件和方法

  3.1、先定义传输的数据格式

/// <summary>
/// JS消息格式
/// </summary>
public class JsInvokeModel
{
[JsonProperty("type")]
public string Type { get; set; } [JsonProperty("content1")]
public string Content1 { get; set; } [JsonProperty("content2")]
public string Content2 { get; set; } [JsonProperty("content3")]
public string Content3 { get; set; }
}

  3.2、XAML

<WebView x:Name="WebView" DOMContentLoaded="WebView_OnDOMContentLoaded" ScriptNotify="WebView_OnScriptNotify" />

  3.3、下面是事件方法

//DOM树加载完成后执行
private async void WebView_OnDOMContentLoaded(WebView sender, WebViewDOMContentLoadedEventArgs args)
{
//1、动态加载css
var js = @"var myCss = document.createElement(""link"");
myCss.rel = ""stylesheet"";
myCss.type = ""text/css"";
myCss.href = ""ms-appx-web:///Assets/Html/css/default.css"";
document.body.appendChild(myCss);";
await sender.InvokeScriptAsync("eval", new[] { js }); //2、动态加载js库(json2)
js = @"var myScript = document.createElement(""script"");
myScript.type = ""text/javascript"";
myScript.src = ""ms-appx-web:///Scripts/json2.min.js"";
document.body.appendChild(myScript);";
await sender.InvokeScriptAsync("eval", new[] {js}); //3、调用js执行自定义代码(为图片添加点击事件,并通知)
js = @"var imgs = document.getElementsByTagName(""img"");
for (var i = 0, len = imgs.length; i < len; i++) {
imgs[i].onclick = function (e) {
var jsonObj = { type: 'image', content1: this.src };
window.external.notify(JSON.stringify(jsonObj));
};
}";
await sender.InvokeScriptAsync("eval", new[] {js}); //4、动态加载手势
js = @"var myScript = document.createElement(""script"");
myScript.type = ""text/javascript"";
myScript.src = ""ms-appx-web:///Assets/Html/js/gesture.js"";
document.body.appendChild(myScript);
window.external.notify(myScript.src+"""");";
await sender.InvokeScriptAsync("eval", new[] { js }); //5、为body添加手势监听
js = @"var target = document.getElementsByTagName(""body"")[0];
prepareTarget(target, eventListener);";
await sender.InvokeScriptAsync("eval", new[] { js });
}

  3.4、Notify监听

private void WebView_OnScriptNotify(object sender, NotifyEventArgs e)
{
//这个事件函数可以监听到JS通知的消息,消息类型为文本
//这里统一消息格式为:JsInvokeModel
var model = JsonConvert.DeserializeObject<JsInvokeModel>(e.Value);
switch (model.Type)
{
case "image":
Info.Text = e.Value;
break;
case "swiperight":
//右滑
Info.Text = e.Value;
break;
case "swipeleft":
//左滑
Info.Text = e.Value;
break;
case "text":
Info.Text = e.Value;
break;
}
}

  WebView虽然提供了同步方法InvokeScript,但是在WP8.1没有实现

   通过InvokeScriptAsync,可以做更多操作,例如,相信对于更换颜色(夜间模式),修改字体大小等

4、WebView导航

两种方式
//后退
//WebView.GoBack();
await WebView.InvokeScriptAsync("eval", new []{"history.go(-1)"}); //刷新
//WebView.Refresh();
await WebView.InvokeScriptAsync("eval", new[] { "history.go()" }); //前进
//WebView.GoForward();
await WebView.InvokeScriptAsync("eval", new[] { "history.go(1)" });

5、手势

  由于WebView的内部结构与WebBrowser不同,WebView无法监听到Manipulation事件

  场景:当我们需要在PivotItem中放置WebView的时候,左右滑动无法切换PivotItem,下面通过JS手势监听WebView上面的手势操作,然后传到后台代码进行处理,这里没有做实时处理,只是监听了手势离开时的速度判断左右滑动

  5.1、定义手势监听事件方法

var gesture;
//记录手势操作开始位置
var gestureStartX; //触发Id,防止重复触发,触发Id与手势Id
var gestureId = 1;
var lastGestureId = 0; //速度触发
var gestureVector = 1.5; //注册手势事件
function prepareTarget(target, eventListener) {
//var target = document.getElementById(targetId);
target.addEventListener("MSGestureStart", eventListener, false);
target.addEventListener("MSGestureEnd", eventListener, false);
target.addEventListener("MSGestureChange", eventListener, false);
target.addEventListener("MSInertiaStart", eventListener, false);
//target.addEventListener("MSGestureTap", eventListener, false);
//target.addEventListener("MSGestureHold", eventListener, false);
target.addEventListener("pointerdown", onPointDown, false);
target.addEventListener("pointerup", onPointUp, false); gesture = new MSGesture();
gesture.target = target;
} function onPointUp(e) {
//把触发时间参数传到gesture
gesture.addPointer(e.pointerId);
} function onPointDown(e) {
//把触发时间参数传到gesture
gesture.addPointer(e.pointerId);
} //手势事件
//具体的属性参见:https://msdn.microsoft.com/zh-cn/library/ie/hh772076%28v=vs.85%29.aspx
function eventListener(evt) {
var myGesture = evt.gestureObject;
if (evt.type == "MSGestureStart") {
//开始触发,记录初始位置
gestureStartX = evt.clientX;
}
else if (evt.type == "MSInertiaStart") {
if (lastGestureId == gestureId || evt.velocityX == "undefined") {
return;
} else {
//释放时触发惯性事件,判断手势释放时的速度
if (evt.velocityX > gestureVector) {
var jsonObj = { type: "swiperight" };
window.external.notify(JSON.stringify(jsonObj));
lastGestureId = gestureId;
} else if (evt.velocityX < -gestureVector) {
jsonObj = { type: "swipeleft" };
window.external.notify(JSON.stringify(jsonObj));
lastGestureId = gestureId;
}
}
}
else if (evt.type == "MSGestureChange") {
//if (lastGestureId == gestureId) {
// return;
//} else {
// var change = evt.clientX - gestureStartX;
// window.external.notify("clientX:" + change);
//}
} else if (evt.type == "MSGestureEnd") {
//手势结束,Id+1
gestureId = gestureId + 1;
myGesture.reset();
}
}

gesture.js

  5.2、在WebView加载完成后,动态加载改JS文件,获取body标签,然后监听事件(参见3.3)

  5.3、当事件触发的时候改变Pivot.SelectedIndex,这样就能实现在WebView上滑动切换PivotItem

private void WebView_OnScriptNotify(object sender, NotifyEventArgs e)
{
//这个事件函数可以监听到JS通知的消息,消息类型为文本
//这里统一消息格式为:JsInvokeModel
var model = JsonConvert.DeserializeObject<JsInvokeModel>(e.Value);
switch (model.Type)
{
case "image":
Info.Text = e.Value;
break;
case "swiperight":
Info.Text = e.Value;
if (pivot.Items != null)
{
if (pivot.SelectedIndex > )
{
pivot.SelectedIndex--;
}
else
{
pivot.SelectedIndex = pivot.Items.Count - ;
}
}
break;
case "swipeleft":
Info.Text = e.Value;
if (pivot.Items != null)
{
if (pivot.SelectedIndex < pivot.Items.Count - )
{
pivot.SelectedIndex++;
}
else
{
pivot.SelectedIndex = ;
}
}
break;
case "text":
Info.Text = e.Value;
break;
}
}

6、常见问题

  6.1、alert和prompt方法在WebView失效,如果需要,可以使用 window.external.notify('message');然后再后台代码进行处理

   6.2、如果是导航到本地路径(ms-appdata:///local/),需要注意

    6.2.1、必须要将html需要的资源和html文件放在同一个文件夹下,html的资源路径不管是不是”/”开头,webview都认为是相对路径

    6.2.2、如果html中要的本地文件,如果在对应目录中不存在,wp上会直接跳出应用,大概过1分钟左右崩溃,且捕获不到异常。Windows上没有这现象

    6.2.3、不支持js的window.exteranl.notify功能

webView1.Navigate(new Uri("ms-appdata:///local/data/html/sample.htm"));

    不知道为什么WebView在导航到本地路径的时候  window.external.notify 会失效,如果需要可以考虑使用 内容流的方式加载本地文件

    下面做简单的演示

      1、定义内容留转换器

    public class HtmlStreamUriResolver : IUriToStreamResolver
{
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
{
string path = uri.AbsolutePath;
return GetContent(path).AsAsyncOperation(); } // 根据 uri 返回对应的内容流
private async Task<IInputStream> GetContent(string path)
{
if (path.StartsWith("http"))
{
// http 方式获取内容数据
var client = new HttpClient();
var response = await client.GetAsync(new Uri(path), HttpCompletionOption.ResponseHeadersRead);
return (await response.Content.ReadAsStreamAsync()).AsInputStream();
}
else if (path.StartsWith("/local/cachedata/html/"))
{
path = string.Format("ms-appdata://{0}", path);
// 获取本地数据
var fileRead = await StorageFile.GetFileFromApplicationUriAsync(new Uri(path));
return await fileRead.OpenAsync(FileAccessMode.Read);
}
else
{
// 获取本地数据
var fileRead = await StorageFile.GetFileFromApplicationUriAsync(new Uri(path, UriKind.Absolute));
return await fileRead.OpenAsync(FileAccessMode.Read);
}
}
}

HtmlStreamUriResolver

      2、生成,导航,html中的所有引用都通过HtmlStreamUriResolver返回,具体逻辑在里面处理,通过这样导航的页面可以使用 window.external.notify 方法

  //生成内容流
var htmlStreamUriResolver = new HtmlStreamUriResolver();
var uri = webView.BuildLocalStreamUri("tag", "/local/cachedata/html/sample.html");
webView.NavigateToLocalStreamUri(uri, htmlStreamUriResolver);

7、Demo

  http://files.cnblogs.com/files/bomo/WebViewDemo.zip

8、参考链接

  手势事件参数说明:https://msdn.microsoft.com/zh-cn/library/ie/hh772076%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

  WinJS手势:https://msdn.microsoft.com/zh-cn/library/ie/hh968249(v=vs.85).aspx

  Win8.1和WP8.1在UniversalAPP中WebView的研究:http://blog.csdn.net/hzdinglai/article/details/41073739

  重新想象 Windows 8.1 Store Apps (81) : WebView:http://www.cnblogs.com/webabcd/p/3803384.html

关于WP8的WebBrowser,请移步:http://www.cnblogs.com/bomo/p/3949994.html

个人能力有限,如果上文有误或者您有更好的实现,可以给我留言

转载请注明出处:http://www.cnblogs.com/bomo/p/4320077.html

【WP8.1】WebView笔记的更多相关文章

  1. webview笔记

    1. 用户上传文件 webChromeClient的onShowFileChooser这个方法,这将打开一个文件选择器,如果要取消这个请求则是调用filePathCallback.onReceiveV ...

  2. Android WebView 笔记

    WebView(网络视图)能载入显示载入网页.将网页内容载入到手机client,它使用了WebKit渲染引擎载入显示网页,实现WebView有下面方法: 首先要实如今手机client显示必需要求注冊一 ...

  3. Android SDK组件:webview笔记

    1.安卓手机中内置了一款webkit内核的浏览器,在SDK中封装为WebView组件. 2.该组件可以在自己的应用程序中显示本地或者Internet上的网页,也可以把它当作一个浏览器来时用. 3.We ...

  4. <WP8开发学习笔记>获取手机的常用型号(如Lumia920,而非RM-822)

    之前WP7时代可以用API获得WP手机的型号如lumia510,但是到了WP8后用APi只能获得硬件版本号了如RM-822,这种型号可以让我们更详细的了解具体的硬件版本,比如国行和港行,设备版本号不一 ...

  5. 1. WP8.1学习笔记

    数据绑定 含义:将对象绑定到控件上 2.基本名词 控件:绑定目标 对象:绑定源(数据源) 控件与对象属性的联系:路径 如何绑定 创建对象,设置控件 在控件需要数据绑定的地方使用拓展语法 <But ...

  6. 0. WP8.1学习笔记

    应用程序生命周期: 运行: 在程序NotRunning状态下点击图标,应用将处于Running状态,这会触发一个Actived事件 挂起: 在程序Running状态下, 点击返回键或win键会触发一个 ...

  7. wp8.1 学习笔记 001 动态生成图片 并更改图片位置

    1.在xaml中划分表格 <Grid Name="gr"> <Grid.ColumnDefinitions> <ColumnDefinition> ...

  8. <WP8开发学习笔记>ApplicationBar(任务栏)的切换以及“黑条问题”

    ApplicationBar(以下简称AppBar)是WP应用相当常见的控件,也很方便.常见的做法是pivot或者panorama的页面切换的时候,AppBar跟随切换对应的按钮或者不显示按钮,如下图 ...

  9. <WP8开发学习笔记>动态修改启动时导航的第一个页面(如登录前启动页为LoginPage,登录后变为MainPage)

    很多时候我们需要在启动程序的时候根据状态改变初始导航页面,比如程序在启动的时候判断用户是否登录, 如果未登录则跳转到LoginPage.xaml否则跳转到MainPage界面. 这时候就要分析程序的启 ...

随机推荐

  1. 接口--interface

    “interface”(接口)关键字使抽象的概念更深入了一层.我们可将其想象为一个“纯”抽象类.它允许创建者规定一个类的基本形式:方法名.自变量列表以及返回类型,但不规定方法主体.接口也包含了基本数据 ...

  2. [内核笔记1]内核文件结构与缓存——inode和对应描述

    由来:公司内部外网记录日志的方式现在都是通过Nginx模块收到数据发送到系统消息队列,然后由另外一个进程来从消息队列读取然后写回磁盘这样的操作,尽量的减少Nginx的阻塞. 但是由于System/V消 ...

  3. 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)

    前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...

  4. scanf类型不匹配造成死循环

        int i = 0; while (flag) { printf("please input a number >>> "); scanf("% ...

  5. 简单酷炫的canvas动画

    作为一个新人怀着激动而紧张的心情写了第一篇帖子还请大家多多支持,小弟在次拜谢. 驯鹿拉圣诞老人动画效果图如下 html如下: <div style="width:400px;heigh ...

  6. React Native 之 Text的使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  7. atitit.attilax的软件 架构 理念.docx

    atitit.attilax的软件 架构 理念.docx 1. 预先规划.1 2. 全体系化1 3. 跨平台2 4. 跨语言2 5. Dsl化2 5.1. 界面ui h5化2 6. 跨架构化2 7. ...

  8. OpenGL ES: Array Texture初体验

    [TOC] Array Texture这个东西的意思是,一个纹理对象,可以存储不止一张图片信息,就是说是是一个数组,每个元素都是一张图片.这样免了频繁地去切换当前需要bind的纹理,而且可以节省系统资 ...

  9. Linux CentOS7通过yum命令安装Mono(尝先安装模式)

    前言 经过尝试网上各种安装mono的技术贴,这个安装过程经历了大约2周,尝试了各个版本,几目前博客所描述的所有安装方式.以下内容的安装方式可以为你尝试不同版本的mono.并非正式环境安装标准方式安装. ...

  10. 酷酷的CSS3三角形运用

    概述 在早期的前端Web设计开发年代,完成一些页面元素时,我们必须要有专业的PS美工爸爸,由PS美工爸爸来切图,做一些圆角.阴影.锯齿或者一些小图标. 在CSS3出现后,借助一些具有魔力的CSS3属性 ...