MVVM Cross android orientation issue - xamarin

i need to change the orientation as per tablet (both orientations) for Phone (only portriat) , kindly let me know the ways to do it in MVVM Cross in Android
[Activity(ScreenOrientation = ScreenOrientation.Portrait, Theme = "#style/AppTheme")]

Put this bool resource in res/values as devices_config.xml or whatever (file names don't matter here):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
Put this one in res/values-sw600dp and res/values-xlarge:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
Then, in the OnCreate method of your Activities you can do this:
if (Resources.GetBoolean(Resource.Boolean.portrait_only))
{
RequestedOrientation = ScreenOrientation.Portrait;
}
Devices that are more than 600 dp in the smallest width direction, or x-large on pre-Android 3.2 devices (tablets, basically) will behave like normal, based on sensor and user-locked rotation, etc. Everything else (phones, pretty much) will be portrait only.
Based on this answer
Just in case, it's possible that you see some autorotations when changing activities, so if that's the case you can check this answer to fix it
HIH

Related

Animation while playing media with ExoPlayer

so im trying to make a video player that plays media on a fraction of the screen while the remaining fraction of the screen shows different images. I am trying to tackle this using animation list:
<?xml version="1.0" encoding="utf-8"?>
<animation-list android:id="#+id/sequence"
android:oneshot="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/folder_icon" android:duration="200" />
<item android:drawable="#drawable/play_icon" android:duration="200" />
</animation-list>
I was able to set the layout so that I can see a single image and the exoplayer view, but im not being able to play the animation. Im not sure where (and how) should I put the command
animation.start()
and where should I declare the variable
sequenceanimation: AnimationDrawable
I´ve tried declaring the variable as a companion object and as a private lateinit var in my activity. Also I tried setting the animation.start() command in onCreate but it's not working.
When I try something along the lines, it messes up my entire code, it stops showing you the list of videos in your local storage and it jumps directly to the exoplayer/animation activity without working.
I don´t know if someone is having the same problem but I was able to solve it by placing the line animation.start() on onStart
override fun onStart() {
super.onStart()
val rocketImage = findViewById<ImageView>(R.id.animacion).apply {
setBackgroundResource(R.drawable.prueba_animacion)
secuenciaAnimation = background as AnimationDrawable
}
secuenciaAnimation.start()
}

Setting process DPI awareness so that the system compensates for scaling factors

I have the following mouse hook procedure (simplified for the explanation).
SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, GetModuleHandle(NULL), 0) ;
LRESULT mouseHookProc(int code, WPARAM wParam, LPARAM lParam){
if(code==HC_ACTION){
const auto& data = *(MSLLHOOKSTRUCT*)lParam ;
data.pt ; //This point gives physical coordinates. It ignores the monitor's scaling factor.
//https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msllhookstruct
}
return CallNextHookEx(NULL, code, wParam, lParam) ;
}
The mouse coordinates I get from the hook are not adjusted by the monitor's scaling factor.
Whether I set my monitor's scaling factor to 100% or 200%, the mouse hook always gives me physical pixels.
On the other hand, the GetCursorPos winapi function gives the coordinates in logical pixels. i.e. If the scaling factor is 200%, GetCursorPos will give the coordinates divided by 2, whereas the mouse hook will give the numbers unadjusted.
According to this:
https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-process_dpi_awareness
if a program is NOT DPI-aware, the system compensates the scaling factor so that the program keeps working as if nothing happened.
That's exactly what's happening with the returned value of GetCursorPos. It's giving logical pixels rather than physical ones.
The mouse hook procedure, on the other hand, is not being adjusted by the system.
I tried setting my program as DPI-unaware in the manifest, with this:
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">unaware</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
But it makes no difference.
I also tried declaring it as DPI-aware, with this:
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<dpiAware>True/PM</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
And that, also, made no difference.
Is there any setting I can add to my program, either via the manifest or otherwise, that will make the mouse hook procedure to give logical coordinates as GetCursorPos does?
I'm testing all this in Windows 10.
FOLLOW UP:
I found the problem. My manifest file was incorrect. The XML namespaces were not set properly.
Here is the one that works.
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity version="1.0.0.0" name="AppName" type="win32"/>
<asmv3:application>
<asmv3:windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
In order for the system to give logical coordinates to a program, the program has to be DPI-aware.
Programs that don't manifest DPI-awareness will handle coordinates inconsistently all over, not just in the mouse hook, also in BitBlt, IAccesibility, UIAutomation, etc.
I don't understand why Microsoft decided to do it backwards. Programs that don't manifest DPI-awareness should behave as usual, not the other way around.
This means that whenever a scaling factor is set on a monitor, most programs will break by default. In order to unbreak them, they have to become DPI-aware and... just like that... they will work again.
I don't understand why Microsoft decided to do it backwards. Programs that don't manifest DPI-awareness should behave as usual, not the other way around.
In fact, Microsoft's doc explains this problem.
From High DPI Desktop Application Development on Windows,
Desktop applications using older Windows programming technologies (raw
Win32 programming, Windows Forms, Windows Presentation Framework
(WPF), etc.) are unable to automatically handle DPI scaling without
additional developer work. Without such work, applications will appear
blurry or incorrectly-sized in many common usage scenarios.
If you want to avoid DPI awareness problems, please create a UWP application.
To start, if you're creating a new Windows app from scratch, it is
highly recommended that you create a Universal Windows Platform (UWP)
application. UWP applications automatically—and dynamically—scale for
each display that they're running on.

Should I use different sized icons for iOS and Android in a forms application?

I have a forms application with a tab bar. For the iOS I created these icons:
ionicons_2-0-1_ios-pause-outline_25.png
ionicons_2-0-1_ios-pause-outline_25#2x.png
ionicons_2-0-1_ios-pause-outline_2523x.png
They are sized 25*25, 50*50 and 75*75
From what I have read I believe these to be the correct sizes.
However can someone give me advice on the sizes and naming conventions for the Android side of the application.
I was told that the filenames might need to be different. Also how can it work if I want to use one icon for iOS and another for Android. Currently I specify icons like this:
var homePage = new NavigationPage(new HomePage())
{
Title = "Home",
Icon = "ionicons_2-0-1_ios-home-outline_25.png"
};
Yes, you probably want to seperate those.
You can read everything on working with different images on the documentation page. Each platform has very specific guidelines on the right image sizes, also depending on the controls you use them on. Just Google for 'icon sizes' or 'human interface guidelines' in conjunction with Android or iOS. Also, you might want to look into the MFractor plugin, which has a (paid) function to generate the right sizes for you which really saves you time.
For Android you might want to avoid using hyphens, since they are known to cause trouble.
To distinquish platforms, you can use constructions like this, for XAML:
<ContentPage>
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="Android, UWP">0</On>
<On Platform="iOS">0,20,0,0</On>
</OnPlatform>
</ContentPage.Padding>
</ContentPage>
And in code:
switch(Device.RuntimePlatform)
{
case Device.iOS:
this.Padding = new Thickness(0,20,0,0);
break;
case Device.Android:
case Device.UWP:
case Device.macOS:
default:
// This is just an example. You wouldn't actually need to do this, since Padding is already 0 by default.
this.Padding = new Thickness(0);
break;
}
(Code samples from xamarinhelp.com)
While this shows it for Padding you can apply it on strings and apply it to your situation. However, you do not have to use different filenames. You can name them identically but just use different icons. Also the platform will figure out which resolution to get or postfix it with #2x, etc.

react-native: creating image from base64 string for iOS and Android (in react-native-elements list)

I'm trying to display icons in a dynamic (react-native-elements) list from a DB via REST call which delivers the icon as base64 encoded string (i.e. here done with jHipster/swagger).
It has to work for both iOS and Android.
I thought this should be a quite common use case, but it turns out somewhat challenging...
What I tried so far:
using static addImageFromBase64(base64ImageData, success, failure) see here
works for iOS only (#platform ios)
using 'data:' uri scheme like this example (as discussed here):
var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANS ...
<Image source={{uri: base64Icon}} ... />
the PR mentioned in that discussion was closed later, but somehow it seems that 'data:' scheme still was introduced, see RCTConvert.m, although it is not documented in Image
but again it seems it was implemented only for iOS (only in the .m file)
Looking at Image for Android, it seems that rendering is delegated to the native side and this could be the reason why it was not implemented for Android (at least it does not work for me in Android).
So is there any good way to get a base64 image string into an Android react-native app?
Or is there a good practice or library to solve this (getting icons dynamically from a DB via REST API into a react-native app) in a complete different way?
In fact it works, I was just always combining some different flaws and also added React native elements to increase confusion...
Thanks to martwetzels for leading me in the right direction with the height/width hint.
If someone else has problems with images and the 'data:' scheme, these are the main obstacles I was stumbling over:
For React Native <Image>:
if you use 'data:' in an <Image>, at least you have to provide width and height in style
this is mentioned for Network images in the Guide for Images:
Unlike with static resources, you will need to manually specify the dimensions of your image.
but unfortunately it is not in the reference for Image component nor the 'data:' scheme is mentioned anywhere
So this is a working example for a React Native <Image>:
var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANS ...
<Image style={{width: 50, height: 50}} source={{uri: base64Icon}}/>
For images in a react-native-elements <List>
only the avatar prop will take an url - the leftIcon prop is for icons from an included library like material-icons only - OR for a separate React Native element
the avatar prop can have an optional separate avatarStyle, but will by default scale the image automatically
the leftIcon prop with a nested <Image> will again need a style for the picture to appear, with at least width & height
A working example for React Native Elements <List> with leftIcon prop with an <Image> as element (style mandatory!):
<List>
{
myItems.map((item, i) => (
<ListItem
key={i}
title={item.name}
leftIcon={<Image style={{width: 35, height: 35}} source={{uri: item.base64Icon}}/>}
/>
))
}
</List>
A working example for React Native Elements <List> with avatar prop (no style, but optional avatarStyle):
<List>
{
myItems.map((item, i) => (
<ListItem
key={i}
title={item.name}
avatar={{uri: item.base64Icon}}
// optional: avatarStyle={{width: 50, height: 50}}
/>
))
}
</List>
So far this is all pretty ovious, once understood... Sorry for asking this dumb question ;-)
As a result, because all my confusion was related to documentation, I will propose some PRs for both React Native and Elements docs.
Edit: PR is now merged and doc changes regarding images with "data:" uri schema and the need to specify size are public meanwhile! Search for "data:" in:
http://facebook.github.io/react-native/docs/images.html
http://facebook.github.io/react-native/docs/image.html

GetSystemMetrics() returns wrong value for SM_CXSCREEN

I've run into an interesting problem. At least in Vista, getSystemMetrics(SM_CXSCREEN) returns an incorrect value when the desktop DPI settings aren't set at 100%. For example, I tried 150% in a 1366x768 screen and getSystemMetrics() returns 911 instead of 1366 (and 1366 / 1.5 ~ 911)
According to the MSDN, getSystemMetrics(SM_CXSCREEN) returns pixels, so I thought this value wouldn't be affected by the DPI settings - but it is. So is there a safer way to find out the true, unscaled screen resolution?
A program must tell the operating system that it is DPI-aware to get the true resolution when you go past 125%. That's best done with a manifest, as explained in this MSDN Library article.
To make you application aware of dpi make and manifest file and put the following text in it.
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
Before getting the correct pixel metrics from functions like GetSystemMetrics, or GetClientRect, your app must declare to the OS that it knows about DPI and therefore won't screw everything up.
There have been several changes to how this is recommended. See the MSDN docs for more details.
From Windows 10 onwards:
::SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
Or from Windows 8.1 onwards:
::SetProcessDpiAwareness(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
Or from Vista onwards:
::SetProcessDPIAware();
After calling this, the function GetSystemMetrics etc. should return the correct values to your app in pixels.

Resources