How to differ between phones and tablets while developing in Flex mobile? - apache-flex

I use applicationDPI in a Flex mobile card game:
<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
firstView="views.Menu"
applicationDPI="160"
initialize="init()">
<fx:Style source="Preferans.css" />
<fx:Script>
<![CDATA[
import spark.core.ContentCache;
public static const AVATAR_CACHE:ContentCache = new ContentCache();
public static var SCALE:Number;
public function init():void {
SCALE = runtimeDPI / applicationDPI;
}
]]>
</fx:Script>
</s:ViewNavigatorApplication>
And provide assets in 3 different resolutions based on it:
<fx:Declarations>
<s:MultiDPIBitmapSource id="BACK"
source160dpi="#Embed('assets/icons/low-res/back.png')"
source240dpi="#Embed('assets/icons/mid-res/back.png')"
source320dpi="#Embed('assets/icons/high-res/back.png')"/>
</fx:Declarations>
And still the result doesn't look good, when I for example select an iPad emulator in the Flash Builder 4.6:
While selecting Google Nexus One produces better result:
What to do here, what to use for detection of a phone vs tablet device?
Checking screen resolution wouldn't help here - see the above iPad example (low resolution, but big screen).

public static function get isTablet():Boolean
{
var deviceWidth:Number = Capabilities.screenResolutionX / Capabilities.screenDPI;
var deviceHeight:Number = Capabilities.screenResolutionY / Capabilities.screenDPI;
var diagonalInches:Number = Math.sqrt((deviceWidth * deviceWidth)+ (deviceHeight * deviceHeight));
if(diagonalInches>=7)
return true;
else
return false;
}

For a project I did for work, I had to evaluate the exact same issue. To do so, I created a new class that was run on app init that would evaluate the device and make some decisions.
Essentially, I did this
var deviceWidth:Number = Capabilities.screenResolutionX / Capabilities.screenDPI;
var deviceHeight:Number = Capabilities.screenResolutionY / Capabilities.screenDPI;
That will give you the device width and height on the majority of devices. The screenDPI property is not always accurate, however, so this will not work 100% of the time. It works often enough, however, that I don't think it is an issue.
From there, I did some research. I found that point where a phone stopped being a phone and started being a tablet. There is no standard approach, so I took the smallest popular tablet I could find (at the time, the Blackberry Playbook or Kindle Fire, can't remember which), and used the dimensions of that screen as the breakpoint between phone and tablet.
if ( deviceWidth >= fireWidth && deviceHeight >= fireHeight ) {
isTablet = true;
}
else {
isPhone = true;
}
That's pseudo code, obviously, but you get the idea. I also threw in some checks to distinguish between each platform (iOS, Android, and Desktop) and, if it was iOS, I manually set whether it was a tablet or phone because there is a limited field of devices there.
From there, I had two interfaces. One for phones, one for tablets. In the addedToStage function for my Application class, I used the isPhone and isTablet checks to choose which interface to load.
Probably not how it is supposed to be done, nor is it fool proof. Unfortunately, though, that is the closest we can get to a universal application with device-specific interfaces in Adobe AIR, as far as I am aware.

Related

Xamarin Forms app not changing orientation on iOS

I have a Xam.Forms app which is working fine on iOS and Android with one exception. All screens except one are portrait. When this one screen shows, it show rotate to landscape. It works fine on android.
On iOS, it fails to change. The info.plist file has all orientations enabled. As I want only this one screen to be portrait, I have in the AppDelegate class an override that ensures everytrhing is portrait except one.
The override is this
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
{
var mainPage = Shell.Current?.CurrentPage;
if (mainPage != null)
{
if (mainPage is IDCardPage)
{
return UIInterfaceOrientationMask.Landscape;
}
}
return UIInterfaceOrientationMask.Portrait;
}
A break point for the landscape is hit, but there is no rotation. According to the Apple docs, this is all I should need to do to rotate a view

Smooth scrolling a Spark List with variable height items using the mouse wheel

We have a list of variable height items that we display in a Spark List control. When the user clicks and drags the vertical scrollbar the list scrolls smoothly. When the up/down arrows are used it moves in small and discrete steps. When the mouse wheel is used the list scrolls in very large discrete steps that is problematic for the user.
We would like to enable smooth scrolling for the mouse wheel. The height of our items vary significantly and it is easy to get lost when you scroll with the moouse due to the discrete scrolling.
Our implementation is fairly simple:
<s:List id="chartList"
dataProvider="{pm.charts}"
itemRenderer="charts.ChartItemRenderer"
horizontalScrollPolicy="off"
verticalScrollPolicy="on"
useVirtualLayout="false"
cachePolicy="auto">
</s:List>
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="false"
xmlns:charts="charts.*"
>
<fx:Script>
<![CDATA[
private var _canvas:BitmapData;
public function set canvas(value:BitmapData):void
{
_canvas = value;
}
[Bindable]
public function get canvas():BitmapData
{
return _canvas;
}
public function render(x:int,y:int, data:int):void
{
_canvas.draw(this);
}
]]>
</fx:Script>
<charts:DefaultChartContainer
chart="{data}"
cachePolicy="on"/>
</s:ItemRenderer>
There does not appear to be an out of the box method for implementing smooth scrolling in a Spark List. How would one go about implementing smooth scrolling in a spark list for variable height items?
Edit:
Here is another way to do this:
http://forums.adobe.com/message/3844410#3844410
Ok, so this wont be easy, but it is doable.
1) Create a custom skin for your list
2) In the custom skin, replace the scroller with a custom scroller (MyScroller)
3) Create a new class that extends Scroller, called MyScroller
4) Adobe in their infinite wisdom made skin_mouseWheelHandler private - which they seem to do all over the place, so you would have to override something higher up, maybe attachSkin and detachSkin. Or you could try adding your own skin_mouseWheelHandler with a higher priority in attachSkin and prevent default on it so the default does not get called.
5) Replicate the code in skin_mouseWheelHandler, and modify it to suit your requirements.
Like #Sunil_D. suggested, listening the mousewheel event and manually adjusting the HorizontalScrollPosition is an easy way to handle this. Add the EventListener for your component
chartList.addEventListener(MouseEvent.MOUSE_WHEEL, chartList_mouseWheelHandler);
and increase/decrease the horizontalScrollPosition with, for example, multiples of event.delta
protected function chartList_mouseWheelHandler(event:MouseEvent):void
{
chartList.verticalScrollPosition -= (event.delta * SOME_CORRECT_VALUE);
}
Finding the proper SOME_CORRECT_VALUE might need some experimenting, but it shouldn't be to hard to find.

How to set resolution higher on Flex desktop native (Air) app?

I'm trying to change the resolution for a flex native app (air) app running on a retina macbook. Flex apps in the browser render everything smoothly at 160dpi automatically but if I build the same app as Air install app, it renders at 72dpi and doesn't look as good. I know you can set a resolution in the application descriptor file for a mobile app but this isn't one. Also, I've tried setting the applicationDPI property on the WindowedApplication tag as well with no luck. Any ideas? Thanks...
For the record, to enable high resolution rendering in AIR desktop apps running on e.g. Retina Macbook Pros, set <requestedDisplayResolution>high</requestedDisplayResolution> in the <initialWindow> part of your app descriptor XML. Requires Adobe AIR 3.6 or newer.
http://help.adobe.com/en_US/air/build/WSfffb011ac560372f2fea1812938a6e463-8000.html#WSfffb011ac560372f-4cb7055d12d779150e8-8000
http://gregsramblings.com/2010/05/06/scaling-an-adobe-air-application-to-fit-multiple-resolutions-and-netbooks/
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" width="1019" height="680" scaleX="0.8" scaleY="0.8" applicationComplete="init()" ...>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" width="1019" height="680" preinitialize="initScreenSize()" applicationComplete="init()" ...>
...
...
private function initScreenSize():void{
var thisScreen:Screen = Screen.mainScreen;
var newScaleX:Number = thisScreen.visibleBounds.width / 1019 * 0.98;
var newScaleY:Number = thisScreen.visibleBounds.height / 680 * 0.98;
var newScale:Number = Math.min(newScaleX,newScaleY,1);
this.scaleX = newScale;
this.scaleY = newScale;
this.height = this.height * newScale;
this.width = this.width * newScale;
}
to scale the app based on the user’s resolution. Here’s the code:

Set window size for standalone application

I want to set the default window size for a flex application that runs with a standalone player.
I set width and height to 100% to be able to get the ResizeEvent and being able to adjust the layout if the user changes the window size. But I'd like to also define a default size.
There's two ways to set the default size of a swf:
1) add a compiler argument:
-default-size=800,600
2) use metadata in your flex main mxml or class
mxml:
<mx:Metadata>
[SWF(width='800', height='600')]
</mx:Metadata>
class:
[SWF(width='800', height='600')]
public class Main extends Application {}
This will tell the compiler what values to put in the header tag of the swf.
I solved it this way:
setting the application to a fixed size on startup, and adjusting it when the stage (here: the window) is resized
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="900" height="600"
applicationComplete="appComplete();">
<mx:Script>
<![CDATA[
private function appComplete():void {
stage.addEventListener(Event.RESIZE, onStageResize);
}
private function onStageResize(e:Event):void
{
this.width = this.stage.stageWidth;
this.height = this.stage.stageHeight;
validateNow();
}
I'm not sure you can. You can do it with air though. Why would you want a standalone flex app that isn't air? The setting is the air xml file

movie does not start in full screen in flash video player

We have this legacy code of a flash video player that functions well enough but still has some loose ends I need to tighten up. It can do the basic "switch to full screen and back to normal size" stunts, however with one exception.
On the first fresh load of the app, if I switch to full screen mode first, and then click to play the movie, the player would be in full screen, yet the movie itself would remain in it's original size.
//trigger
if (stage.displayState == StageDisplayState.NORMAL) {
stage.addEventListener('fullScreen', procFullScreen);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.displayState = StageDisplayState.FULL_SCREEN;
//mv:VideoDisplay
mv.percentHeight = 100;
mv.percentWidth = 100;
mv.x = 0;
mv.y = 0;
}
// event handler
if (event.fullScreen) {
mv.smoothing = true;
this.height = stage.height;
this.width = stage.width;
//videoCanvas:Canvas
videoCanvas.height = Application.application.height;
videoCanvas.width = Application.application.width;
fullScreenViewStack.selectedIndex = 1;
}
The VideoDisplay object even returns the expected width/height, but the movie just plays in it's original size. If I switch screen sizes during movie playback, then the movie size will shrink or stretch as it should. I'm running out of ideas, any suggestions? Thanks in advance!
Seems like a bug... What version of sdk are you using?
Have you tried calling validateNow() in the VideoDisplay after switching to fullscreen?

Resources