I am looking to make my cross platform mobile application more native-feeling and I was wondering if there was a way to modify the way the Spark Scroller behaves on overscroll (when the user scrolls beyond the bounds of the viewport). Basically, the current implementation matches iOS almost exactly but feels out of place on Android (iOS "bounces", showing area not in the viewport. Android stops at the bounds of the viewport and the edges glow).
Is there a built in way to modify this behavior? I have not come across any options yet, but I would like to make sure that is the case before I go and extend Scroller to try to add such functionality.
You can kill the pull and bounce effects pretty easily with this:
scroller.mx_internal::bounceEnabled = false;
scroller.mx_internal::pullEnabled = false;
I do not think you can prevent the user from scrolling past the edges very easily though. It looks like you'll want to extend Scroller and override the method:
mx_internal function performDrag(dragX:Number, dragY:Number):void
Let the super.performDrag() run and then check to see if viewport.horizontalScrollPosition or viewport.verticalScrollPosition are out of bounds (< 0 or > (height/width - contentWidth/Height)).
Related
I am only using the desktop Application, no mobile.
I am experimenting with letting the user set the screen resolution during run time. I give him the Display Modes available and he applies one. This part actually works. The problem occurs when i save this mode and try to set this display mode the next time they launch the game.
I am using preferences to store the mode the user selected. I am unable to access preferences before the Create method in my Game class, or in the DesktopLauncher Object, where you normally set up the config file and pass it into the application. So my DesktopLauncher looks like this.
val config = Lwjgl3ApplicationConfiguration()
config.setFullscreenMode(Lwjgl3ApplicationConfiguration.getDisplayMode())
Lwjgl3Application(MainGame(), config)
I use the current screen resolution on the creation of the application. Then in my Create method in my MainGame class i get the mode they set from preferences and i set it like so...
override fun create() {
var modes = Gdx.graphics.displayModes.toList()
val mode = Gdx.graphics.displayMode
val preference: Preferences = Gdx.app.getPreferences("screenPreference")
val screenWidth = preference.getInteger("width", mode.width)
val screenHeight = preference.getInteger("height", mode.height)
val refreshRate = preference.getInteger("refreshRate", mode.refreshRate)
modes = modes.filter { it.width == screenWidth }
modes = modes.filter { it.height == screenHeight }
modes = modes.filter { it.refreshRate == refreshRate }
if (modes.isNotEmpty()) {
Gdx.graphics.setFullscreenMode(modes[0])
}
....
}
To summarize i get the list of modes, i pull from preferences what was set last, and i filter the list according to what was in preferences. This should leave one item left in the list and i apply it. If for some reason the list is empty, then i don't set it, or there is no preference set i just apply the current mode again.
This is where the weird stuff happens. I have checked all the numbers when creating my screens and cameras, and they are all correct. I do receive the correct resolution, but the application doesn't render correctly. Below are a couple examples of what happens.
In the first image you see the bounds of the application to the screen. My application only renders in the bottom corner, and the rest is black. What happened to achieve this effect is i started the application with a smaller resolution than my native resolution, so 1280x1024, then in my create method i set the application full screen mode to 1920x1080 before building the rest of my application. I have checked my cameras and my viewports, and they all have the resolution 1920x1080, but the image is not filling the entire screen.
And a second.
This one is what happens when i reverse the settings. So i start at native resolution 1920x1080, and in my create method i set it to 1280x1024, again before creating the rest of my application. This gives me black bars on both sides of the image like id expect, but the application is HUGE, and only a portion of it fits in the window, the rest goes out of bounds, as depicted by the dotted lines.
It will remain like this the entire time, unless i change the resolution while the application is running, it will then correct itself for the rest of the applications life.
I am confounded by this effect i am getting, and am looking for an answer as to why, or how to fix it.
I found the issue that was causing the image to render incorrectly. I was setting the display mode in the create() function in my main game class. This function is not run on the rendering thread, and you do not want to use Gdx.graphics on anything other than the rendering thread, as described in the libgdx wiki https://github.com/libgdx/libgdx/wiki/Threading
There is a function where you can pass in a lambda to be run on the rendering thread.
Gdx.app.postRunnable {
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode(modes[0]))
}
After passing that into postRunnable the game renders correctly on launch.
I'm building a simple eBook for tablets in Flash Pro. All the pages are images (Bitmaps in library) and there's about 80 of them. To maintain good quality for large tablets, bitmaps are quite big (3999x2999).
This eBook has vertical and horizontal scrolling and these are working fine, but; due to huge amount and size of these images, I can't add all of them to stage when app starts, so I ended up adding only the closest pages to current page always after scrolling tween.
This works ok, but causes always a delay after page scroll (even several seconds with older tablet, and with new iMac it's almost 1s, so it's notable). This is basicly what I do per image/page:
var bitmapdata:BitmapData = new bitmapArray[i](); //linkage name
var hRatio:Number = stage.stageHeight / bitmapdata.height;
var bitmap:Bitmap = BitmapScaled(bitmapdata, bitmapdata.width * hRatio, bitmapData.height * hRatio);
target.addChild(bitmap); //target is a MovieClip (I have one Mc for each vertical pile of pages)
And BitmapScaled function:
function BitmapScaled(source0:BitmapData, width0:Number, height0:Number):Bitmap{
var mat:Matrix = new Matrix();
mat.scale(width0/source0.width, height0/source0.height);
var bmpd_draw:BitmapData = new BitmapData(width0,height0,false);
bmpd_draw.drawWithQuality(source0,mat,null,null,null,true,StageQuality.BEST);
return new Bitmap(bmpd_draw);
}
Also, after scrolling I clean up the ones that aren't next to new current page:
function clear(targetArray:Array):void{
for(var i:int = 0; i<targetArray.length; i++){
targetArray[i].bitmapData.dispose();
targetArray[i].bitmapData = null;
targetArray[i].parent.removeChild(targetArray[i]);
targetArray[i] = null;
}
if(targetArrays[targetArrays.indexOf(targetArray)] = new Array();
}
How often:
After horizontal scroll I add one new horizontal page and one new vertical page, and remove one horizontal and at least one vertical page.
After vertical scroll I add only one new vertical page (if next vertical page is one that I already haven't added), so vertical pages I keep in stage untill next horizontal scroll happens. This takes a smaller delay, but also notable.
I know Flash/AIR is not the best way for this, but it's all I have now. How could I get rid of the addChild-delay? Yeah you can't, so any better ways to do all this?
I'm pretty sure I'm using the hard way with something here, but just can't figure out what and how I should do it.
BitmapData drawing on mobile device is too slow to be used on the fly, if you must use it do your drawing on app start (still slow though). BitmapData blitting is a little bit faster but still too slow to be used on mobile device.
With large amount of assets like in your case, Stage3D frameworks like Starling might not be the best solution either as texture uploading is also slow and limited in memory amount (when limit is reached the app crashes).
Best might just be to copy what typical Android/Ios development use: Few different resolutions for all assets with a minimum of 1x and 2x.
I personally use 0.5x, 1x, 2x, 3x and developed a framework that switches resolution according to different settings (very much like XCode does). But still you can keep things simple without a framework and just set at app start the asset resolution you'll use for the app. I would also make sure to remove and add those assets on screen as they are needed.
don't use that "new BitmapData" in conjunction with the "dispose". when you load your bytes load it directly into the already existing bitmaps on the stage. try to have as little modification of the allocated memory as possible through your load-resize-display pipe.
removing and dumping pixels onto the renderer is far slower than changing already existing ones.
I'm sure a lot of people need this, but so far I have not been able to find a good solution.
Environment: AIR app for iOS and Android created with Flash CS6.
What I'm trying to do: Display a table (5 columns, 200 rows). Nothing fancy, just text data. The table should be sortable and scroll smoothly in response to swipe gesture.
The DataGrid component is too "heavy" and not recommended for mobile. Is there a simple solution for this?
For table display (even fancy) I would use the StageWebView, of course if you can afford to not be able to overlay anything over it.
Quick Sample below:
webView = new StageWebView();
webView.viewPort = new Rectangle(0, 44, 480, 756);
webView.loadString('<html><head><style type="text/css">tr:nth-child(odd) { background-color:#eee; } tr:nth-child(even) { background-color:#fff; } .header_button { width:100%;}</style></head><body><table width="200" border="1"><tr><td><input name="Name" type="button" value="Name" class="header_button"></td><td>Id</td></tr><tr><td>Mark</td><td>0</td></tr><tr><td>Bob</td><td>1</td></tr></table></body></html>');
webView.stage = stage;
you should read through documentation as loadString is pretty limiting:) to see all possible ways of using this class, but the idea should by planted in you by now:) e.g. CSS, JQuery etc. can be used, and scrolling is really fast:)
I haven't tried them yet, but Mad Components (technically it's the Extended Mad Components lib) has a UIDataGrid class.
Other than that, since your grid/table is only intending to display text, you might want to give the components from Adobe a try. Their grids are flexible, and as a result can be "heavy".
Since you only want to render text, you won't pay the price of trying to render heavier objects (check boxes, buttons, etc) inside the grid. The performance (when only rendering text inside the grid) may be acceptable.
Forget the Flex DataGrid, even with static text you won't get acceptable scrolling performance (I got about 5fps for a real time data grid).
The way to go is a normal List with a custom LabelItemRenderer and a button group for the header. You can make the renderer look like a grid very easily.
I haven't tested Alex Harui's list based grid, but it should work out of the box. If not, you should get the idea. Just roll your own AS3 based renderer and performance should be over 25fps even with fast scrolling. I get around 30 on an iPad2.
I developed a mobile app inside Adobe Flex (4.6) and it includes using pinch-to-zoom functionality to zoom in on pictures to make it easier to read words in the pictures. In previous android versions (2.1 to 2.3.3 and 2.3.4 if you're running cyanogenmod) the pinch-to-zoom works fine. But if the app is run on an ICS (Android 4.x) device, the axes seem to handle the enlargement of the picture individually. i.e. when you move your fingers apart horizontally, the image gets very wide, but stays the same vertical size, and vice versa.
First, does anyone know why this is happening?
And second, does anyone know of a way to fix it to work as it did before?
I will update to include screenshots.
Update: I have confirmed this is also an issue with Honeycomb. i.e., 3.x OS acts the same as 4.x ICS.
Sense, running the latest HTC update:
ICS, on AOKP, but verified this is an issue with standard ICS distros as well:
Solved this. Code was previously:
protected function onZoom(e:TransformGestureEvent, img:Image):void
{
DynamicRegistration.scale(img, new Point(e.localX, e.localY), img.scaleX*e.scaleX, img.scaleY*e.scaleY);
}
change the final e.scaleY to e.scaleX. This makes it scale based on only one portion of the zoom (in the x direction) and scales both X and Y accordingly. Not exactly perfect, but it works very well in practice.
Final code is this:
protected function onZoom(e:TransformGestureEvent, img:Image):void
{
DynamicRegistration.scale(img, new Point(e.localX, e.localY), img.scaleX*e.scaleX, img.scaleY*e.scaleX);
}
I have a large html5 canvas (much larger than the screen), and I want to implement a "google-maps" dragging.
I want the canvas to be dragable by mouse, and I want it to render only the part we can see on the screen each time I drag it.
Does someone have a good idea?
I solved this problem by using the jQuery UI draggable component on the canvas element.
I enclosed it in a div - with overflow set to hidden, and made the canvas as large as I need it to be. Works a charm
http://jqueryui.com/demos/draggable/
To render your canvas only on the part of the screen that we can see you could use the drawImage function :
drawImage(image, x, y, width, height)
With "image" as your original entire canvas, "x" and "y" representing the offset that move when dragging and "width/height" the size of the actual windows.
See documentation :
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage
and a great tutorial from mdc :
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images