我正在使用适用于 iOS 和 Android 的 VS2015 TACO 开发适用于 iOS、Android 和 Windows 商店的 JavaScript 应用程序。我刚刚安装了 Ace 插件,并且正在研究Javascript/Ace 代码示例。对于 iOS 和 Android,我想将本机 UI 用于:1)底部标签栏和 2)带有图标和文本的滚动选择器列表(基本上是 WinJS.UI ListView)。Ace Intro YouTube Video在 XAML 标记中显示了一个示例选项卡栏,但我不熟悉 XAML。谁能指出我的 Ace Plugin Javascript 示例,用于 iOS 和 Android 的标签栏 UI 和表格视图 UI?我将不胜感激。
更新 #1 感谢亚当·内森。使用他的代码,我在我的 Mac iPad 模拟器中获得了一个停靠的标签栏。它在纵向和横向视图中都能很好地捕捉。我正在使用此代码打开和关闭它:
TEST_ACE.dockTabs = function () {
if (TEST_ACE.pageTabBar == null) {
// Surround the WebView with native UI
TEST_ACE.pageTabBar = TEST_ACE.buildDockedTabsWithoutXaml();
// Replace the WebView with the loaded native page
// (For the title setting in XAML to work on Android, ShowTitle must be
// set to true in the Android section of config.xml.)
ace.getHostPage().setContent(TEST_ACE.pageTabBar);
// Reparent the WebView inside the native page
TEST_ACE.pageTabBar.setContent(ace.getHostWebView());
// Save the native page so we can set its title as tabs are clicked
_nativePage = TEST_ACE.pageTabBar;
}
else {
ace.getHostPage().setContent(ace.getHostWebView());
TEST_ACE.pageTabBar = null;
}
}
当我关闭标签栏时,我仍然看到图标曾经所在的底部块 - 但它现在是空的。也就是说,当我尝试同时关闭上部标题栏和底部标签栏时,我只关闭上部标题栏,但底部块(现在为空白)仍然存在。如果我改变方向(纵向/横向),那么底部块将消失。在将其重置为 HostWebView 之前,是否有更好的方法使用标签栏清除 HostPage?
对于 Android,我更新了 config.xml 文件以将 ShowTitle 设置为 true:
<name>AcePluginTester</name>
<description>A blank project that uses Apache Cordova to help you build an app that targets multiple mobile platforms: Android, iOS, Windows, and Windows Phone.</description>
<author href="http://cordova.io" email="dev@cordova.apache.org">Apache Cordova Team </author>
<content src="index.html" />
<access origin="*" />
<vs:features />
<preference name="SplashScreen" value="screen" />
<preference name="windows-target-version" value="8.1" />
<!-- Support for Cordova 5.0.0 plugin system -->
<plugin name="cordova-plugin-whitelist" version="1" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
<preference name="ShowTitle" value="true"/>
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
<preference name="orientation" value="all" />
</platform>
<!--blah blah blah-->
但是当我在 VS Android Emulator 中运行该应用程序时,我仍然收到此错误:
Uncaught Error: Native error: java.lang.RuntimeException: Error setting FrameLayout's UserControl.Content to Windows.UI.Xaml.Controls.Page{6b1647a V.E...... ......I. 0,0-0,0}
at run.ace.IncomingMessages.set(IncomingMessages.java:206)
at run.ace.NativeHost$2.run(NativeHost.java:239)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.RuntimeException: Cannot set title on the main page in Android unless you set <preference name="ShowTitle" value="true"/> in config.xml.
at run.ace.TabBar.setTitle(TabBar.java:39)
at Windows.UI.Xaml.Controls.Page.updateTitle(Page.java:63)
at Windows.UI.Xaml.Controls.Page.processBars(Page.java:71)
at Windows.UI.Xaml.Controls.ViewGroupHelper.setProperty(ViewGroupHelper.java:51)
at run.ace.IncomingMessages.set(IncomingMessages.java:191)
... 8 more
See http://ace.run/docs/errors for help.
cordova.js (314,13)
我错过了Android的东西吗?
再次感谢您。这会很棒!
更新#2
我将 ShowTitle 首选项移动到小部件根目录,但仍然出现错误。我得到了 value="True"(大写 True)和 value="true" 的错误。这是我的 config.xml 文件的全部内容:
<?xml version="1.0" encoding="utf-8"?>
<widget xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:vs="http://schemas.microsoft.com/appx/2014/htmlapps" id="io.cordova.myapp740bed" version="1.0.1" xmlns="http://www.w3.org/ns/widgets" defaultlocale="en-US">
<name>AcePluginTester</name>
<description>A blank project that uses Apache Cordova to help you build an app that targets multiple mobile platforms: Android, iOS, Windows, and Windows Phone.</description>
<author href="http://cordova.io" email="dev@cordova.apache.org">Apache Cordova Team </author>
<content src="index.html" />
<access origin="*" />
<vs:features />
<preference name="SplashScreen" value="screen" />
<preference name="windows-target-version" value="8.1" />
<!-- Support for Cordova 5.0.0 plugin system -->
<plugin name="cordova-plugin-whitelist" version="1" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
<preference name="orientation" value="all" />
</platform>
<platform name="android">
<icon src="res/icons/android/icon-36-ldpi.png" density="ldpi" />
<icon src="res/icons/android/icon-48-mdpi.png" density="mdpi" />
<icon src="res/icons/android/icon-72-hdpi.png" density="hdpi" />
<icon src="res/icons/android/icon-96-xhdpi.png" density="xhdpi" />
</platform>
<platform name="ios">
<!-- iOS 8.0+ -->
<!-- iPhone 6 Plus -->
<icon src="res/icons/ios/icon-60-3x.png" width="180" height="180" />
<!-- iOS 7.0+ -->
<!-- iPhone / iPod Touch -->
<icon src="res/icons/ios/icon-60.png" width="60" height="60" />
<icon src="res/icons/ios/icon-60-2x.png" width="120" height="120" />
<!-- iPad -->
<icon src="res/icons/ios/icon-76.png" width="76" height="76" />
<icon src="res/icons/ios/icon-76-2x.png" width="152" height="152" />
<!-- iOS 6.1 -->
<!-- Spotlight Icon -->
<icon src="res/icons/ios/icon-40.png" width="40" height="40" />
<icon src="res/icons/ios/icon-40-2x.png" width="80" height="80" />
<!-- iPhone / iPod Touch -->
<icon src="res/icons/ios/icon-57.png" width="57" height="57" />
<icon src="res/icons/ios/icon-57-2x.png" width="114" height="114" />
<!-- iPad -->
<icon src="res/icons/ios/icon-72.png" width="72" height="72" />
<icon src="res/icons/ios/icon-72-2x.png" width="144" height="144" />
<!-- iPhone Spotlight and Settings Icon -->
<icon src="res/icons/ios/icon-small.png" width="29" height="29" />
<icon src="res/icons/ios/icon-small-2x.png" width="58" height="58" />
<!-- iPad Spotlight and Settings Icon -->
<icon src="res/icons/ios/icon-50.png" width="50" height="50" />
<icon src="res/icons/ios/icon-50-2x.png" width="100" height="100" />
</platform>
<platform name="windows">
<icon src="res/icons/windows/Square150x150Logo.scale-100.png" width="150" height="150" />
<icon src="res/icons/windows/Square150x150Logo.scale-240.png" width="360" height="360" />
<icon src="res/icons/windows/Square30x30Logo.scale-100.png" width="30" height="30" />
<icon src="res/icons/windows/Square310x310Logo.scale-100.png" width="310" height="310" />
<icon src="res/icons/windows/Square44x44Logo.scale-100.png" width="44" height="44" />
<icon src="res/icons/windows/Square44x44Logo.scale-240.png" width="106" height="106" />
<icon src="res/icons/windows/Square70x70Logo.scale-100.png" width="70" height="70" />
<icon src="res/icons/windows/Square71x71Logo.scale-100.png" width="71" height="71" />
<icon src="res/icons/windows/Square71x71Logo.scale-240.png" width="170" height="170" />
<icon src="res/icons/windows/StoreLogo.scale-100.png" width="50" height="50" />
<icon src="res/icons/windows/StoreLogo.scale-240.png" width="120" height="120" />
<icon src="res/icons/windows/Wide310x150Logo.scale-100.png" width="310" height="150" />
<icon src="res/icons/windows/Wide310x150Logo.scale-240.png" width="744" height="360" />
</platform>
<platform name="wp8">
<icon src="res/icons/wp8/ApplicationIcon.png" width="62" height="62" />
<icon src="res/icons/wp8/Background.png" width="173" height="173" />
</platform>
<platform name="android">
<splash src="res/screens/android/screen-hdpi-landscape.png" density="land-hdpi" />
<splash src="res/screens/android/screen-ldpi-landscape.png" density="land-ldpi" />
<splash src="res/screens/android/screen-mdpi-landscape.png" density="land-mdpi" />
<splash src="res/screens/android/screen-xhdpi-landscape.png" density="land-xhdpi" />
<splash src="res/screens/android/screen-hdpi-portrait.png" density="port-hdpi" />
<splash src="res/screens/android/screen-ldpi-portrait.png" density="port-ldpi" />
<splash src="res/screens/android/screen-mdpi-portrait.png" density="port-mdpi" />
<splash src="res/screens/android/screen-xhdpi-portrait.png" density="port-xhdpi" />
</platform>
<platform name="ios">
<splash src="res/screens/ios/screen-iphone-portrait.png" width="320" height="480" />
<splash src="res/screens/ios/screen-iphone-portrait-2x.png" width="640" height="960" />
<splash src="res/screens/ios/screen-ipad-portrait.png" width="768" height="1024" />
<splash src="res/screens/ios/screen-ipad-portrait-2x.png" width="1536" height="2048" />
<splash src="res/screens/ios/screen-ipad-landscape.png" width="1024" height="768" />
<splash src="res/screens/ios/screen-ipad-landscape-2x.png" width="2048" height="1536" />
<splash src="res/screens/ios/screen-iphone-568h-2x.png" width="640" height="1136" />
<splash src="res/screens/ios/screen-iphone-portrait-667h.png" width="750" height="1334" />
<splash src="res/screens/ios/screen-iphone-portrait-736h.png" width="1242" height="2208" />
<splash src="res/screens/ios/screen-iphone-landscape-736h.png" width="2208" height="1242" />
</platform>
<platform name="windows">
<splash src="res/screens/windows/SplashScreen.scale-100.png" width="620" height="300" />
<splash src="res/screens/windows/SplashScreen.scale-240.png" width="1152" height="1920" />
<splash src="res/screens/windows/SplashScreenPhone.scale-240.png" width="1152" height="1920" />
</platform>
<platform name="wp8">
<splash src="res/screens/wp8/SplashScreenImage.jpg" width="480" height="800" />
</platform>
<plugin name="cordova-plugin-crosswalk-webview" version="1.5.0" src="https://github.com/crosswalk-project/cordova-plugin-crosswalk-webview" />
<plugin name="cordova-plugin-ace" version="0.0.12" src="https://github.com/Microsoft/ace" />
<engine name="ios" spec="~3.9.2" />
<engine name="android" spec="~4.1.1" />
<plugin name="cordova-plugin-ace" spec="https://github.com/microsoft/ace.git" />
<preference name="ShowTitle" value="true" />
</widget>
即使在运行“清洁解决方案”和“清除 Cordova 缓存”后,我也会收到错误消息。
我将在单独的更新中发布标签条码。
更新#3 我的应用程序内容是一个 WebGL 画布。当我的 Mac iPad2 模拟器(纵向)第一次绘制时,窗口大小为 768(宽度)x 1004(高度),如下面的 JavaScript 控制台日志输出所示:
Window size: 768 x 1004
debug.js (29,24)
Window size: 768 x 960
debug.js (29,24)
Window size: 768 x 960
debug.js (29,24)
当我打开标签栏时,它会调整到 960 的高度。当我关闭标签栏(保持纵向)时,窗口高度不会返回到 1004。所以看起来窗口在标签时没有调整大小栏切换关闭。一旦我将设备旋转到横向,整个窗口就会重新绘制并且底部栏消失,同样,当我旋转回纵向时,整个窗口大小会恢复到 768 x 1004 并且空白底部栏也不存在。这是我的测试代码(正在进行中):
在 index.js 中,当 onDeviceReady 触发时,我的代码调用 GAME.initialize():
function onDeviceReady() {
// Handle the Cordova pause and resume events
document.addEventListener( 'pause', onPause.bind( this ), false );
document.addEventListener( 'resume', onResume.bind( this ), false );
// TODO: Cordova has been loaded. Perform any initialization that requires Cordova here.
GAME.initialize();
};
这是game.js中的代码:
//game.js
var GAME = { NAME: "hiio", VERMAJOR: 0, VERMINOR: 9, DEBUG: true, BUILD: 1, CLASSNAME: "GAME" };
GAME.initialize = function () {
"use strict";
//log if debug
loginit();
log(GAME.NAME + " " + GAME.VERMAJOR + "." + GAME.VERMINOR + (GAME.DEBUG ? " (Debug)" : " (Release)"));
//renderer
var testcanvas = document.getElementById("idcanvas");
if (!GAME.renderer) GAME.renderer = new THREE.WebGLRenderer( { canvas: testcanvas } );
//scene
if (!GAME.scene) GAME.scene = new THREE.Scene();
//camera
GAME.setcamera();
//orbitcontrols
GAME.orbctls = new THREE.OrbitControls(GAME.camera);
// ambient
var al = new THREE.AmbientLight(0x222222, 0.5);
GAME.scene.add(al);
// light
var dl = new THREE.DirectionalLight(0xffffff, 1.0);
dl.position.set(2000, 2000, 500);
GAME.scene.add(dl);
// axes
GAME.scene.add(new THREE.AxisHelper(4000));
// Sphere
var geometry = new THREE.SphereGeometry(500, 24, 8);
var material = new THREE.MeshPhongMaterial({
color: 0x00ffff,
transparent: true,
opacity: 0.7,
});
var mesh = new THREE.Mesh(geometry, material);
GAME.scene.add(mesh);
//FPS
GAME.stats = initStats();
//events
window.addEventListener("resize", GAME.setcamera, false);
//Ace
TEST_ACE.initialize();
animate(); //run
}
//camera
GAME.setcamera = function () {
"use strict";
var c = document.getElementById("idcanvas");
var h = window.innerHeight;
var w = window.innerWidth;
if (!GAME.camera) { //new
GAME.camera = new THREE.PerspectiveCamera(45, w / h, 1, 16000);
GAME.camera.position.set(50, 100, 3000);
GAME.scene.add(GAME.camera);
}
else { //change
GAME.camera.aspect = (w / h);
}
if (GAME.renderer) { //onsize
GAME.renderer.setSize(w, h); //this sets the height of the canvas.
log("Window size: " + window.innerWidth + " x " + window.innerHeight);
}
if (GAME.orbctls) {
GAME.target = new THREE.Vector3(0, 0, 0);
GAME.orbctls.target0 = GAME.target.clone();
GAME.orbctls.reset();
}
GAME.camera.updateProjectionMatrix();
}
function initStats() {
"use strict";
var stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
//animate loop
var banimate = false;
function animate() {
"use strict";
requestAnimationFrame(animate);
if (banimate) { loge("animate re-entry."); return; }
banimate = true;
GAME.renderer.render(GAME.scene, GAME.camera);
GAME.stats.update();
banimate = false;
};
//end
这是 test_act.js 代码(有点混乱抱歉):
//test_ace.js
var TEST_ACE = { CLASSNAME: "TEST_ACE" };
TEST_ACE.popupSegCtrl = null;
TEST_ACE.pageTabBar = null;
TEST_ACE.initialize = function () {
"use strict";
var abutton1 = document.getElementById("idbutton1"); //Tab Bar
abutton1.addEventListener("click", TEST_ACE.dockTabs, false);
return;
}
TEST_ACE.buildDockedTabsWithoutXaml = function () {
var page = new ace.Page();
page.setTitle("Docked");
var tabBar = new ace.TabBar();
var b1 = new ace.AppBarButton();
var b2 = new ace.AppBarButton();
var b3 = new ace.AppBarButton();
var b4 = new ace.AppBarButton();
var b5 = new ace.AppBarButton();
b1.setLabel("Docked");
b1.setIcon("www/images/info-{platform}.png");
b1.addEventListener("click", function () { onTabClick(b1, 0); });
b2.setLabel("Overlay");
b2.setIcon("www/images/info-{platform}.png");
b2.addEventListener("click", function () { onTabClick(b2, 1); });
b3.setLabel("Fullscreen");
b3.setIcon("www/images/info-{platform}.png");
b3.addEventListener("click", function () { onTabClick(b3, 2); });
b4.setLabel("Code");
b4.setIcon("www/images/info-{platform}.png");
b4.addEventListener("click", function () { onTabClick(b4, 3); });
b5.setLabel("Plat-Specific UI");
b5.setIcon("www/images/info-{platform}.png");
b5.addEventListener("click", function () { onTabClick(b5, 4); });
// TabBar's "content property" maps to a PrimaryCommands property.
// Therefore, to add children, we get the PrimaryCommands collection:
tabBar.getPrimaryCommands().add(b1);
tabBar.getPrimaryCommands().add(b2);
tabBar.getPrimaryCommands().add(b3);
tabBar.getPrimaryCommands().add(b4);
tabBar.getPrimaryCommands().add(b5);
page.setBottomAppBar(tabBar);
return page;
}
function onTabClick(a, b) {
return;
}
TEST_ACE.dockTabs = function () {
if (TEST_ACE.pageTabBar == null) {
// Surround the WebView with native UI
TEST_ACE.pageTabBar = TEST_ACE.buildDockedTabsWithoutXaml();
// Replace the WebView with the loaded native page
// (For the title setting in XAML to work on Android, ShowTitle must be
// set to true in the Android section of config.xml.)
ace.getHostPage().setContent(TEST_ACE.pageTabBar);
// Reparent the WebView inside the native page
TEST_ACE.pageTabBar.setContent(ace.getHostWebView());
// Save the native page so we can set its title as tabs are clicked
_nativePage = TEST_ACE.pageTabBar;
}
else {
ace.getHostPage().setContent(ace.getHostWebView());
TEST_ACE.pageTabBar = null;
GAME.setcamera();
}
}
//end