I made a Activity using Titanium Mobile Module, and it has simple white background.
Can I pass a window (Titanium object) from this Activity to another js files to add (draw) new objects (like buttons) ?
Yes, you can.
If you are using Alloy for it, just do anything similar as
//index.js
function doClick(e) {
require('utils').createButton($.index);
}
And
//utils.js inside /lib
exports.createButton = function createButton(window){
var button = Ti.UI.createButton({
height:'20dp',
width:'20dp',
title:'Test'
});
window.add(button);
}
However, keep in mind, to your memory consumption, because you are sending a big object $.index as a local variable.
Related
I have integrated Unity in an Android activity (similar to this).
I now need to dynamically load a scene depending on user input.
I've tried replicating how Unity loads a scene, in the only way that I know an Android Activity is able to communicate with the UnityPlayer, but obviously doesn't work:
UnityPlayer.UnitySendMessage("Application", "LoadLevel", "9");
I know there are other ways of loading a scene in Unity, but I don't know how to call those from Android itself (also consider that UnitySendMessage only allows one parameter).
If you plan to load Unity activity from Android, you should create an empty scene. Call this this Main Menu, then make it the default scene that loads through the Build Settings. Make it index 0.
The goal of this empty scene is to load specific scene when script attached to it is called.
In this Main Menu scene, create a GameObject called SceneLoader then attach the script below to it:
public class SceneLoader : MonoBehaviour
{
public void loadScene(string sceneIndex)
{
UnityEngine.SceneManagement.SceneManager.LoadScene(Convert.ToInt16(sceneIndex));
}
}
You should also create a GameObject called SceneLoader in every other scene and attach the script above to all of them.
Now, load Unity Activity which automatically loads the default/empty scene. Since there is only one GameObject/SceneLoader in it, it will load very fast.
You can now load other scenes from Java with:
UnityPlayer.UnitySendMessage("SceneLoader", "loadScene", "9");
I'm using asset manager to generate my font using object
FreeTypeFontGeneratorLoader, specifically I'm using this current parameter
FreeTypeFontLoaderParameter parameter = new FreeTypeFontLoaderParameter();
parameter.fontFileName = "fonts/myFont.ttf";
parameter.fontParameters.size = size;
parameter.fontParameters.minFilter = Texture.TextureFilter.Linear;
parameter.fontParameters.magFilter = Texture.TextureFilter.Linear;
if(withStroke) {
parameter.fontParameters.borderStraight = true;
parameter.fontParameters.borderColor = Color.BLACK;
parameter.fontParameters.borderWidth = 1.5f;
}
parameter.fontParameters.color = Assets.fontColor;
(then I load my font in static variable in Assets class)
everything is normal if the app runs for the first time,
here is the generated text with outline screenshot:
screenshot
but after I close my app using this line
Gdx.app.exit();
and then open my app again, the outline is now starting to acting weird
here is the screenshot of weird generated font:
screenshot
I'm already trying to dispose my asset manager in event dispose of ApplicationListener in Gdx, but sometime my font still acting weird.
if I clear my processing run in all task android, then the font is normal again.
Can you tell me possible solutions of why it is happening, and do you have any suggestions?
Thx
Android sometimes keeps static (final) variables even when the app lost its context.
When using static variables: make sure you dispose when required and set them to null afterwards. Or do not use static for assets.
Since this problem happen because my app not closed completely because this line :
Gdx.app.exit();
is just doing this :
Schedule an exit from the application. On android, this will cause a call to pause() and dispose() some time in the future, it will not immediately finish your application"
that's why I change my way to close my app using this line:
System.exit(0);
then my app is loading and generating new font when user open my app again.
I need to get current window in the tabbed application.
I tried with
var win = Ti.UI.currentTab.window();
and with
var win = Ti.UI.currentWindow;
but get the Uncaught TypeError: Cannot call method 'window' of undefined error in both cases.
If you are using TabGroup, you can access current window through activeTab property. It's not global function, so you have to have keep reference to TabGroup object in your code:
var tabGroup = Ti.UI.createTabGroup({ tabs: createTabs() });
tabGroup.activeTab.window
currentTab and currentWindow are holdovers from when you could spin off multiple JavaScript contexts from a Ti.UI.createWindow({ url: 'foo.js' }). I'd recommend you don't use them.
There are a couple of patterns to choose from when you need to communicate from one part of your app to the UI at another part.
1st option: listen for and fire events a la Ti.App.addEventListener('foo', function(data){}) and Ti.App.fireEvent('foo', { }). This decouples the code nicely, so you can move the UI handling code around without changing the firing code.
2nd option: expose the UI objects through modules. In your controller, exports.win = $.win;.
3rd option: set a global object: Alloy.Globals.win = $.win;.
ok so in alloy framework, we just use $ sign to get all the controls which are created in .xml file...
so if you set id of your window tag in .xml file then you can get current window with below example...
.xml file
<Alloy>
<Window id="win">
</Window>
</Alloy>
.js file
var win = $.win
so from above code you can get your current window.
Hope you get it.
I have an app which works in IOS 6. I am trying to get it to work on basically any andriod version.
I have an index controller and view which load fine.
I can load the register page but when I bypass the register page. It works fine in IOS but not Android. I am not using tabgroups just windows.
Any ideas ? NOTE I can't get the full xml tags to load in code view which is why there are no brackets.
I get this error:
new Error("Cannot add window/tabGroup to another window/tabGroup.");
Index Controller
if (!isRegistered) {
var register = Alloy.createController( 'register' );
register.getView().open();
}
else {
var main = Alloy.createController( 'main' );
Alloy.Globals.mainController = main;
}
index view
Alloy
Window id="index"
Require type="view" src="slider" id="slider"
Window
Alloy
main js controller
// code above
$.main.open();
// code below
main view
Alloy
Window id="index"
View id="loadingOverlay" /
View id="main"
ImageView id="background" image="/images/background.jpg"/
Require type="view" src="slider" id="slider" /
/OptionDialog
/View
/Window
/Alloy
Thanks,
the error messag explains it
new Error("Cannot add window/tabGroup to another window/tabGroup.");
hard to tell what is going on here, you might need to add a gist or pastebin, but a window cannot contain another window
I have been trying to create a single codebase for both Iphone & Android for a intermediate level app. ( 4 tabs, multiple windows, maps etc.) using itanium 2.1 API.
However, I have found that things on Android platform dont work as smoothly or willingly as on Iphone epsecially tableviews & UI elemnts. The UI responsiveness on Android is also sluggish.
The kitchen sink examples are pretty straightforward. I am looking at an enterprise ready app which has to be maintained for atleast next couple of years.
Has anybody worked on similar lines with platform quirks and been successful in creating fully functional iOS & Android apps from SAME codebase?
I'm having a lot of success using the compile-time CommonJS mechanism for having a root view that then has os-specific capabilities.
For instance, my os-independent view might be ui/MyView.js :
var createAddButton = require("ui/MyView.AddButton");
var MyView = function() {
var self = Ti.UI.createWindow();
createAddButton(self, function() { alert('ADD!'); });
return self;
};
module.exports = MyView;
Then, I create os-specific functions to handle it:
iphone/ui/MyView.AddButton.js
module.exports = function(view, addHandler) {
var addButton = Titanium.UI.createButton({
systemButton: Titanium.UI.iPhone.SystemButton.ADD
});
addButton.addEventListener("click", addHandler);
view.rightNavButton = addButton;
};
android/ui/MyView.AddButton.js
module.exports = function(view, addHandler) {
view.activity.onCreateOptionsMenu = function(e){
var menuItem = e.menu.add({ title: "Add" });
menuItem.addEventListener("click", addHandler);
};
};
The CommonJS system they have implemented will pick the appropriate version of MyView.AddButton.js so that the button is added to the right place. It allows for the majority of the view to be the same, but the os-specific things to be separated properly.
Titanium is not meant for 1 codebase for all. You do need to rewrite stuff for every OS. However, some app developers claim to have reused 95% of its code. So only 5% of the code is OS specific. But I am sure their code is full with if-elses.
What I recommend doing, to be able to maintain it properly, without thousands of if-else constructions, is build a single backend core, and write code specifically for UI related matters per OS. This way, you have some UI related code for Android, UI related code for iOS and 1 core working for both.
Since Android and iOS differ a lot, writing a single codebase will make sure you can never use OS specific features (like android hardware menu button, or iOS NavigationGroup), and will let the UI look non-intuitive.