一 说几点

当下移动开发主要实现方式有传统的Native以及新的混合开发想Rect.js,nodejs这些前段框架,其本质要么是原生控件来实现UI,要么html来实现UI。Xamarin其实也只是取巧而已,目的在于方便net开发者再学习java以及蛋疼的oc和不成熟的swift,好了废话不多说了。

二 xamarin地图实现及其问题

gis作为软件领域基础性存在,比之传统表格列表等图形化展现数据优势。在app中由于国内国外墙原因一般都使用三方api,百度,高德,腾讯之类,其中高德自然是国内做得最专业的在线地图服务商,他们的api都很简单,所要注意一点就是坐标系,因为坐标系的原因常常标注一些地物要素对不上号。像传统老牌arcgis在移动领域其实也只是刷存在感。在xamarin中要开发地图应用自然的不得不使用三方,原因嘛android绑定了谷歌,ios嘛绑定了高德地图api功能又不够强大。怎么办的用高德,百度,腾讯,那么问题来了,xamarin使用三方库,这地方非常蛋疼,原因嘛xamarin其实将原生库元素据提取出来与c#语法映射,什么jar,.a ,.framework用很不成熟的sharpie工具反射,其实在这个过程中千丝万缕的牵涉到原生的oc姿势,不得不说非常蛋疼。即使你能够看懂官方英文,demo各种类型对应,问题还是会不少,不是缺个类就是函数签名对不上号,要么就是即使能is某个类型但as却编译不过。

三 面对问题怎么办?

问题自然是要解决的,随着h5的完善webview不失为更好一种办法,说白了就是把网页嵌入到页面中用c#与js交互,在这里以百度js api为例。

在xamarin.android中由于4.4版本以下浏览器内核存在天生渲染慢加载慢等不足,在xamarin.ios自8.0后增强优化wkwebview控件。

四 需求与实现

1 怎样把地图html页面嵌入到app页面,在这里xamarin为我们提供了很好的demo

android实现代码

 using System;
using Android.Net.Http;
using Android.OS;
using Android.Webkit;
using MobileOperation.Droid.Web;
using MobileOperation.Views;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using View = Android.Views.View;
using WebView = Android.Webkit.WebView; [assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace MobileOperation.Droid.Web
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>, IDownloadListener, View.IOnLongClickListener
{
const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}"; protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e); if (Control == null)
{
var webView = new Android.Webkit.WebView(Forms.Context);
webView.Settings.JavaScriptEnabled = true;
webView.SetDownloadListener(this);
SetNativeControl(webView);
}
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
var hybridWebView = e.OldElement as HybridWebView; }
if (e.NewElement != null)
{ Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
//Control.LoadUrl(string.Format("file:///android_asset/Web/{0}", Element.Uri));
InjectJS(JavaScriptFunction); Control.Settings.JavaScriptEnabled = true;
Control.SetWebChromeClient(new GeoWebChromeClient());
Control.SetWebViewClient(new MyWebViewClient());
Control.SetNetworkAvailable(true);
Control.Settings.SetGeolocationEnabled(true);
Control.Settings.JavaScriptCanOpenWindowsAutomatically = (true); Control.Settings.SetAppCacheEnabled(true);
Control.Settings.AllowFileAccess=(true);
Control.Settings.DomStorageEnabled=(true);
Control.Settings.SetSupportZoom(false);
Control.Settings.SetSupportMultipleWindows(false);
Control.Settings.BuiltInZoomControls=(false);
Control.Settings.SetRenderPriority(WebSettings.RenderPriority.High); Control.SetOnLongClickListener(this);
Control.ClearCache(true);
if ((int)Build.VERSION.SdkInt >= )
{
Control.Settings.LoadsImagesAutomatically=(true);
}
else
{
Control.Settings.LoadsImagesAutomatically=(false);
} var hybirdWebView = e.NewElement;
hybirdWebView.RegisterInvokeJsFunctionAgent((s, action) =>
{
string jsInvokeStr = string.Format("javascript: {0}", s); // 如果android运行版本高于4.4则调用该版本及其以上所支持的函数
if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
{
Control.EvaluateJavascript(jsInvokeStr, new ValueCallback(Control));
}
else
{
// todo 此处调用本身并不支持有返回值
Control.LoadUrl(jsInvokeStr);
} //res http://droidyue.com/blog/2014/09/20/interaction-between-java-and-javascript-in-android/ // todo 目前在android还无法实现有返回值
if (action != null)
{
action(string.Empty);
}
});
//Control.LoadUrl(string.Format("http://map.baidu.com/mobile/webapp/index.html"));
Control.LoadUrl(string.Format("http://192.168.50.148/baidu/index.html"));
//Control.LoadUrl(string.Format("http://192.168.50.254"));
//Control.LoadUrl(string.Format("http://map.baidu.com/mobile/webapp/search/search/qt=s&wd=atm&c=75&searchFlag=bigBox&version=5&exptype=dep&src_from=webapp_all_bigBox&src=0&nb_x=11577553.94&nb_y=3541989.14&center_rank=1/vt=map")); }
} void InjectJS(string script)
{
if (Control != null)
{
Control.LoadUrl(string.Format("javascript: {0}", script));
}
} public void OnDownloadStart(string url, string userAgent, string contentDisposition, string mimetype, long contentLength)
{ } public bool OnLongClick(View v)
{
return true; }
} public class GeoWebChromeClient : WebChromeClient
{
public override void OnGeolocationPermissionsShowPrompt(string origin, GeolocationPermissions.ICallback callback)
{
//允许通过权限询问访问
callback.Invoke(origin, true, false);
} } public class MyWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
view.LoadUrl(url);
return true;
}
public override void OnPageFinished(WebView view, String url)
{
if (!view.Settings.LoadsImagesAutomatically)
{
view.Settings.LoadsImagesAutomatically=(true);
}
} public override void OnReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
{
handler.Proceed();
} public override void OnReceivedError(WebView view, ClientError errorCode, string description, string failingUrl)
{
base.OnReceivedError(view, errorCode, description, failingUrl); } } public class ValueCallback : IValueCallback
{ private Android.Webkit.WebView webView; public ValueCallback(Android.Webkit.WebView wbView)
{
webView = wbView;
} public void OnReceiveValue(Java.Lang.Object value)
{ } public System.IntPtr Handle
{
get { return new IntPtr(); }
} public void Dispose()
{ }
} }

ios实现代码

 using System;
using System.IO;
using Foundation;
using MobileOperation.iOS.WebCS;
using MobileOperation.Views;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS; [assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace MobileOperation.iOS.WebCS
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
WKUserContentController _userController; protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e); if (Control == null)
{
_userController = new WKUserContentController();
var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
_userController.AddUserScript(script);
_userController.AddScriptMessageHandler(this, "invokeAction"); var config = new WKWebViewConfiguration { UserContentController = _userController };
var webView = new WKWebView(Frame, config);
SetNativeControl(webView);
}
if (e.OldElement != null)
{
_userController.RemoveAllUserScripts();
_userController.RemoveScriptMessageHandler("invokeAction");
var hybridWebView = e.OldElement as HybridWebView;
}
if (e.NewElement != null)
{
string fileName = Path.Combine(NSBundle.MainBundle.BundlePath, string.Format("Web/{0}", Element.Uri));
Control.LoadRequest(new NSUrlRequest(new NSUrl(fileName, false))); Control.LoadRequest(new NSUrlRequest(new NSUrl(string.Format("http://192.168.50.148/baidu/index.html"))));
var hybirdWebView = e.NewElement;
//Control.UIDelegate = new MyWKUIDelegate();
hybirdWebView.RegisterInvokeJsFunctionAgent((s,action) =>
{
string jsInvokeStr = string.Format("javascript: {0}", s);
Control.EvaluateJavaScript(jsInvokeStr, (rs, error) =>
{
if (action!=null)
action(rs.ToString());
});
}); }
} public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
Element.InvokeAction(message.Body.ToString());
}
} public class MyWKUIDelegate : WKUIDelegate
{
public override void RunJavaScriptAlertPanel(WKWebView webView, string message, WKFrameInfo frame, Action completionHandler)
{
base.RunJavaScriptAlertPanel(webView, message, frame, completionHandler);
} public override void RunJavaScriptTextInputPanel(WKWebView webView, string prompt, string defaultText, WKFrameInfo frame,
Action<string> completionHandler)
{
base.RunJavaScriptTextInputPanel(webView, prompt, defaultText, frame, completionHandler);
} public override void RunJavaScriptConfirmPanel(WKWebView webView, string message, WKFrameInfo frame, Action<bool> completionHandler)
{
base.RunJavaScriptConfirmPanel(webView, message, frame, completionHandler);
}
} }

2 c#与js如何交互:

c#调用js  android实现:

由于android api问题在4.4以下只能传参而没有返回值,4.4以上使用相应方法(但是我试过了是没有返回值的,原因未知)

  hybirdWebView.RegisterInvokeJsFunctionAgent((s, action) =>
{
string jsInvokeStr = string.Format("javascript: {0}", s); // 如果android运行版本高于4.4则调用该版本及其以上所支持的函数
if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
{
Control.EvaluateJavascript(jsInvokeStr, new ValueCallback(Control));
}
else
{
// todo 此处调用本身并不支持有返回值
Control.LoadUrl(jsInvokeStr);
} //res http://droidyue.com/blog/2014/09/20/interaction-between-java-and-javascript-in-android/ // todo 目前在android还无法实现有返回值
if (action != null)
{
action(string.Empty);
}
});

IOS实现:亲测ios是有返回值

hybirdWebView.RegisterInvokeJsFunctionAgent((s,action) =>
{
string jsInvokeStr = string.Format("javascript: {0}", s);
Control.EvaluateJavaScript(jsInvokeStr, (rs, error) =>
{
if (action!=null)
action(rs.ToString());
});
});

js调用c#在demo里面已经实现了

3 粗线的问题

在2.0版本的百度地图由于其js与移动端双指缩放处理bug当地图添加一些标注后缩放到一定时候地图卡死,解决办法将地图版本降低到1.5版本,对于百度地图嘛自然是无语的,下面请看

 <script type="text/javascript" src="http://api.map.baidu.com/api?v=1.5&ak=ak"></script>

链接:http://tieba.baidu.com/p/1724327638

4 定位

在代码里面已经实现自然的需要添加权限,重写webclient控件,由于移动手机的浏览器内核一般都支持h5,所以只需要调用百度地图的定位api即可通过本质上调用浏览器定位api轻松实现定位

链接:http://developer.baidu.com/map/jsdemo.htm#i8_1

5 性能

android webview的性能不咋个好,但是组织好html的渲染过程还是可以接受的

6截图

Xamainr 地图之webview初探的更多相关文章

  1. [OC][地图] 高德地图之定位初探(一)

    使用前的说明 高德地图开放平台的iOS定位模块网址-->http://lbs.amap.com/api/ios-location-sdk/summary/ 高德地图有Web端.android平台 ...

  2. 微信小程序室内地图导航开发-微信小程序JS加载esmap地图

    一.在微信小程序里显示室内三维地图 需要满足的两个条件 调用ESMap室内地图需要用到小程序web-view组件,想要通过 web-view 调用ESMap室内地图需要满足以下 2 个条件: 1. 小 ...

  3. 支付宝小程序室内地图导航开发-支付宝小程序JS加载esmap地图

    如果是微信小程序开发,请参考微信小程序室内地图导航开发-微信小程序JS加载esmap地图文章 一.在支付宝小程序里显示室内三维地图 需要满足的两个条件 调用ESMap室内地图需要用到小程序web-vi ...

  4. Android网络:开发浏览器(二)——功能完善之长按网页图片菜单

    上述的历史和书签的功能已经实现.不过如果我们长时间按住图片,并不会出现如同UC中的一系列选项,我们可以来看看UC中的长按图片出现的菜单. 图10.2.9    UC中的长按图片菜单 我们可以看到UC中 ...

  5. Google Earth数据存储、管理、表现及开发机制

    Google Earth数据存储.管理.表现及开发机制 一.    Google Earth(Map)介绍 1.1    Google Earth介绍 在众多的地理信息服务提供商中,Google是较早 ...

  6. 前端笔记之微信小程序(一)初识微信小程序&WXSS与CSS|WXML与HTML的差异&像素和DPR

    一.小程序概述 2017 年 1 月 9 日小程序正式上线,腾讯开放了个人开发者开发小程序,小程序从此就开始火爆,这一年,小程序狂揽 4 亿用户.1.7 亿的日常活跃,上线 58 万个.这是一个巨大的 ...

  7. Android中通过WebView控件实现与JavaScript方法相互调用的地图应用

    在Android中通过WebView控件,可以实现要加载的页面与Android方法相互调用,我们要实现WebView中的addJavascriptInterface方法,这样html才能调用andro ...

  8. UE4高级功能--初探超大无缝地图的实现LevelStream

    转自:http://blog.csdn.net/u011707076/article/details/44903223 LevelStream 实现超大无缝地图--官方文档学习 The Level S ...

  9. Baidu与Google地图API初探

    前天周六,有个好友过来玩,他说想在他的站点中加入地图导航模块,但不知道选择哪个第三方Map API 在网上查了下Baidu.Google.QQ和MapBar等4种Map API(都是採用JS开放API ...

随机推荐

  1. javascript语言精粹:继承

    继承提供了2个有用的任务: 1.代码重用 2.引入了一套类型系统的规范,因为程序员无需编写显示类型转换的代码,他们的工作量将大大减轻.这是一件很好的事情,应为类型转换会丧失类型系统在安全上的优势. 在 ...

  2. YARN & HDFS2 安装和配置Kerberos

    今天尝试在Hadoop 2.x开发集群上配置Kerberos,遇到一些问题,记录一下 设置hadoop security core-site.xml <property> <name ...

  3. 基于visual Studio2013解决C语言竞赛题之0523魔方阵

     题目

  4. redhat6.0 安装ORACLE11GR2过程记录

    vawaretools安装 我的是8.0vm 1,vm=>install vmtools 2,会在redhat里出现一个虚拟光驱图标. 3,复制里面的文件到root目录下. 4,解压缩文件 ta ...

  5. BZOJ 2318: Spoj4060 game with probability Problem( 概率dp )

    概率dp... http://blog.csdn.net/Vmurder/article/details/46467899 ( from : [辗转山河弋流歌 by 空灰冰魂] ) 这个讲得很好 , ...

  6. 基于visual Studio2013解决C语言竞赛题之0612递归

     题目

  7. CairoSVG - Convert SVG to PNG or PDF - Contents

    CairoSVG - Convert SVG to PNG or PDF - Contents User Documentation Author Guillaume Ayoub Date 2011- ...

  8. Swift - 使用UI Dynamics给UIKit组件添加移动吸附行为

    UI Dynamics是UIKit的一个新组成部分,它向iOS中的视图提供了与物理学有关的功能和动画.可以让你向视图中引入力和物理属性,可以让你的视图弹跳,舞动,受重力影响等等. 下面通过样例,演示使 ...

  9. linux head命令

    head 与 tail 就像它的名字一样的浅显易懂,它是用来显示开头或结尾某个数量的文字区块,head 用来显示档案的开头至标准输出中,而 tail 想当然尔就是看档案的结尾. 1.命令格式: hea ...

  10. 用Photoshop做圆角图片

    如果图片被锁定,请“双击”图层中“背景”解锁,如果没有图层菜单,在最上面导航栏中:窗口—图层. 选用“圆角矩形工具“ 设置圆角弧度大小,设置“半径” 19 同时按Ctrl+回车(Enter)选区,再C ...