一 说几点

当下移动开发主要实现方式有传统的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. 开源框架ViewPagerIndicator的使用——TabPageIndicator

    1.导入Android-ViewPagerIndicator库文件 下载地址:https://github.com/JakeWharton/ViewPagerIndicator 2.布局文件     ...

  2. 网页制作之JavaScript部分 1 - 语法(复制教材内容)

    一.简介 1.JavaScript它是个什么东西? 它是个脚本语言,需要有宿主文件,他的宿主文件是html文件. 2.它与Java有什么关系? 没有什么直接联系,java是Sun公司(已经没有了,被O ...

  3. 从 Qt 的 delete 说开来

    原地址:http://blog.csdn.net/dbzhang800/article/details/6300025 在C++中学习过程中,我们都知道: delete 和 new 必须 配对使用(一 ...

  4. C++中用rand()和srand()产生随机数方法介绍

    标准库<cstdlib>(被包含于<iostream>中)提供两个帮助生成伪随机数的函数:   函数一:int rand(void): 从srand (seed)中指定的see ...

  5. POJ 1700 cross river (数学模拟)

                                                                                                       ...

  6. Codeforces Beta Round #10 B. Cinema Cashier (树状数组)

    题目大意: n波人去k*k的电影院看电影. 要尽量往中间坐,往前坐. 直接枚举,贪心,能坐就坐,坐在离中心近期的地方. #include <cstdio> #include <ios ...

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

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

  8. Oracle cloud control 12c 怎样改动sysmanpassword

        前阵子在虚拟机部署了Oracle Cloud Control 12c.事别几日,居然忘记了登录password. 主要是由于如今的Oracle有关的Software比之前提供更强的安全机制.什 ...

  9. Linux内核-系统调用

    Linux内核-系统调用 1.与内核通信 #系统调用在用户空间进程和硬件设备之间添加了一个中间层 作用:1.为用户空间提供了一种硬件的抽象接口 2.系统调用保证了系统的稳定和安全 3.出于每一个进程都 ...

  10. C# - 线程操作

    代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syst ...