How to preview Compose layouts in landscape mode - android-jetpack-compose

I'm using Android Studio Bumblebee 2021.1.1 Canary 3 + Compose 1.0-rc02, and there seems to be no easy way to force landscape mode for a preview, which includes using resources (in particular dimensions) from -land/ resource folders.
I know that this behaviour is possible in theory, because using #Preview(device = Devices.AUTOMOTIVE_1024p) will use the correct resource values. However, this is not a viable preview option as the pixel density is off compared to the default preview device. (Even when tweaking the preview width, height and font scale, the icons are still the wrong size.)
I was able to make it so that my UI code detects the landscape orientation using the following wrapper
val lanscapeConfig = LocalConfiguration.current.apply {
orientation = Configuration.ORIENTATION_LANDSCAPE
}
CompositionLocalProvider(LocalConfiguration provides lanscapeConfig) {
// actual preview code
}
However this doesn't fix the aforementioned issue with not getting landscape resources using dimensionResource().
Any ideas?

Current workaround is to use a separate file for the landscape preview and specify device = Devices.AUTOMOTIVE_1024p, and tweak the height and width (but not the font scale).
But I hope someone can come up with a better approach which works with different device types.
#Preview(device = Devices.AUTOMOTIVE_1024p, widthDp = 720, heightDp = 360)
#Composable
fun PreviewLandscape() {
PreviewHelper() // common preview code to all modes
}
Update 2023-02-13
Looks like some relevant features have been added to Android Studio 2022.1 Electric Eel: Use Compose Preview with different devices.
For now, the interactive mode feature has to be enabled manually (File > Settings > Experimental > Jetpack Compose > Check 'Enable #Preview picker').

Based on the new specs this can be done with:
#Preview(
showSystemUi = true,
device = "spec:width=411dp,height=891dp,dpi=420,isRound=false,chinSize=0dp,orientation=landscape"
)

Related

iOS Swift: maximumContentSizeCategory not working on UILabel

According to this article:
https://useyourloaf.com/blog/restricting-dynamic-type-sizes/
And this WWDC 2021 video:
https://developer.apple.com/videos/play/wwdc2021/10059/?time=879
The minimumContentSizeCategory and maximumContentSizeCategory can limit the min and max font size when user uplevel/downlevel the font sizes in System Accessibility settings.
However I tried it out, and from the debugging info these two settings are properly set, but in view rendering, the font size still goes to very large if accessibility font size is very large.
// before setting
print(label.appliedContentSizeCategoryLimitsDescription)
label.minimumContentSizeCategory = .small
label.maximumContentSizeCategory = .accessibilityMedium
// after setting
print(label.appliedContentSizeCategoryLimitsDescription)
print results:
UILabel:0x7fd610a414a0: AX-L
--> AX-L
UILabel:0x7fd610a414a0: S <= (none->)AX-M <= AX-M
--> AX-M
How can I properly use these two settings?
Any ideas on how to properly use these two settings?
I hope that's the proper way because I use them as you did (and it works).
I created a blank project in Interface Builder (Xcode 13.4.1) as follows:
... and the Dynamic Type feature is blocked within the specified thresholds I defined like you (in the viewDidLoad of the view controller).
I think you should check out the way you created your label because, with the above one, it works like a charm.

swift ios macCatalyst app does not load some views on startup on macOS Monterey

since the release of the new macOS Moterey operating system (12) my MacCatalyst application does not load some views at startup until I resize the window or change focus.
If I look at XCode's Debug View Hierarchy these views are not present.
If, on the other hand, I use the classic debug (while they are not shown) it turns out that they have the correct frame (origin and size), superviews and window.
To show them I have to resize the window (manually, using the mouse) or remove the focus from the app (for example by clicking on another window and then clicking the app window again).
Only after doing one of these two things are the views loaded.
Has anyone experienced the same behavior?
The application is developed in Swift only with UIKit and various Storyboards (without SwiftUI).
Thanks a lot to everyone.
I understand what happens. 
If it can be useful to anyone ... 
I use custom margins for my UIViewControllers. To calculate a margin, I use the minimum width of a scene as a variable.
I take this value in this way: 
var minSceneWidth:CGFloat = 400
scenes.forEach { windowScene in
if let w = windowScene.sizeRestrictions?.minimumSize.width {
if minSceneWidth > w {
minSceneWidth = w
}
}
}
Since the latest version of macOS the value "minimumSize.width" seems to be also "0" and this is not good for the calculation of my margins. 
Thank you all.

Fullscreen Exclusive: How to change the native resolution?

I can successfully control the native refresh-rate by specifying the refresh rate in DXGI_SWAP_CHAIN_FULLSCREEN_DESC which is passed to CreateSwapChainForHwnd.
I was expecting native resolution to change to that specified by the hight and width of the swapchain. However, I was not this lucky.
Moreover, the CreateSwapChainForHwnd suggests that you cant control the native resolution of the monitor since you can specify DXGI_SWAP_CHAIN_FULLSCREEN_DESC has a scaling parameter
typedef enum DXGI_MODE_SCALING {
DXGI_MODE_SCALING_UNSPECIFIED = 0,
DXGI_MODE_SCALING_CENTERED = 1,
DXGI_MODE_SCALING_STRETCHED = 2
} DXGI_MODE_SCALING;
But, video games are clearly trigging a mode change (temporary black screen) when they change resolution in fullscreen exclusive. So they must be able to change the native resolution. How are they doing this?
Also, I was wondering why DXGI_MODE_SCALING_STRETCHED only fills a sub-rectangle of screen (DXGI_MODE_SCALING_CENTERED centres on this sub-rectangle, and DXGI_MODE_SCALING_UNSPECIFIED aligns the swapchain's top right corner with the top-right of this sub-rectangle). This sub-rectangle also changes as the hight and width passed to CreateSwapChainForHwnd changes. Maybe it's that I'm really in Fullscreen Optimizations rather than Fullscreen Exclusive and this sub-rectangle is the same size of my window(changing the window size didn't affect the observed behaviour).
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
Set this flag to enable an application to switch modes by calling IDXGISwapChain::ResizeTarget.
When switching from windowed to full-screen mode, the display mode (or monitor resolution) will be changed to match the dimensions of the application window.
https://learn.microsoft.com/en-us/windows/win32/api/dxgi/ne-dxgi-dxgi_swap_chain_flag
Interestingly, the mode switch works correctly without the flag when changing refresh-rates but will not when changing resolutions

Ios webview with capacitor, set safe areas

Using capacitor to build an app in ios. In ios the webview covers the whole screen, for iphone-x that means the notch will be included and content will go behind it, like the picture on the right. But i want the picture on the left, black bars on 'no go areas'.
The expected solution (html/css) for this would be to set correct viewport and use the 'safe-area'insert-?', se: https://css-tricks.com/the-notch-and-css/
But for the webview in ios the 'safe-area'insert' will always be 0, that is how it works => this solution is useless.
How can i solve this? Can i change the webview to not cover the whole screen, without changing in the capacitor-framework?
You can use a compatible Cordova plugin cordova-plugin-safearea
npm i -D cordova-plugin-safearea
npx cap sync
With this installed, you can request the safe margin area over the cordova/capacitor bridge:
// Types for clarity
type SafeArea = {
top: string,
bottom: string,
}
window.plugins.safearea.get(
(result: SafeArea) => {
// elegantly set the result somewhere in app state
},
(error: any) => {
// maybe set some sensible fallbacks?
}
);
You could use these values to specify extra padding on the body, or on your header / bottom-menu components
The docs say it returns the values as Numbers, but it seems to me they are actually strings (consider parseFloat before doing math with them).
I have just implemented this in React (running the getter in React.useLayoutEffect); the project is wrapped in Capacitor and have tested on two iOS devices with different ingenious Apple notch screen formats (iPhone 8 and iPhone 11 Pro).
Refer to the documentation for more at https://github.com/rickgbw/cordova-plugin-safearea
There is a CSS variable preset by capacitor you can use to set the padding or a margin for example.
html {
--ion-safe-area-top: env(safe-area-inset-top);
--ion-safe-area-bottom: env(safe-area-inset-bottom);
--ion-safe-area-left: env(safe-area-inset-left);
--ion-safe-area-right: env(safe-area-inset-right);
}

D3D10 (DirectX10) fullscreen performance issue

I have a bit of a problem setting up my DirectX10 (Win32/c++) application for fullscreen mode. The problem is that I want to have my app running in fullscreen right from the start. This can be done by taking the DXGISwapChain::SetFullScreenState function. This works, but i get a small notice in my Visualc++ 2008 debugger which states:
"DXGI Warning: IDXGISwapChain::Present: Fullscreen presentation inefficiencies incurred due to application not using IDXGISwapChain::ResizeBuffers appropriately, specifying a DXGI_MODE_DESC not available in IDXGIOutput::GetDisplayModeList, or not using DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH."
What this means is that DirectX will not take full ownership of the graphicscard and flip the images from front to backbuffer but instead blit them which is much slower.
Now, i do have the DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH enabled and i did try to resize my buffers but i have absolutely no idea what would be the best way to go into fullscreen mode. I have looked on MSDN but there they mostly assume you will only go into Fullscreen by pressing Alt+Enter which lest DXGI do all the work. If someone please could post a bit of code which takes DirectX10 into fullscreen mode and takes full advantage of the "flipping" it would be greatly appriciated!
For anybody interested in the code used on resize:
ReleaseCOM(m_pD3DRenderTargetView);
ReleaseCOM(m_pD3DDepthStencilView);
ReleaseCOM(m_pD3DDepthStencilBuffer);
DXGI_MODE_DESC* mod = new DXGI_MODE_DESC;
mod->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
mod->Height = m_ScreenHeight;
mod->Width = m_ScreenWidth;
mod->RefreshRate.Denominator = 0;
mod->RefreshRate.Numerator = 0;
mod->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
mod->Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
delete mod; mod = 0;
m_pSwapChain->ResizeTarget(mod);
HR(m_pSwapChain->ResizeBuffers(1, m_ScreenWidth, m_ScreenHeight, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH))
throw(Exception(GET_BUFFER_FAIL, AT));
//problem area
m_pSwapChain->SetFullscreenState(TRUE, NULL);
ID3D10Texture2D* pBackBuffer;
HR( m_pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer))
throw(Exception(GET_BUFFER_FAIL, AT)); //continues as usual
Is there any reason you delete your mode desc?
Have you also tried putting your mode desc through "FindClosestMatchingMode"?
Check out http://msdn.microsoft.com/en-us/library/cc627095(VS.85).aspx The "Full-Screen issues" section contains a lot of useful information.
There are some prerequisites for enabling flipping in DXGI (which is the most efficient fullscreen presentation mode):
1) You should go into fullscreen state specifying a mode that exists in the system (you could do that either by using mode from IDXGIOutput::GetDisplayModeList or finding it using IDXGIOutput::FindClosestMatchingMode). Your code just specifies screen resolution, so most likely mode is set correctly.
2) After SetFullscreenState, you should call ResizeBuffers with the right buffer size matching mode, this is where DXGI would setup flipping mode.
Typically, it should happen naturally as reaction to WM_SIZE message send by SetFullscreenState transition, so if your app doesn't call ResizeBuffers on WM_SIZE, it probably should.
You can call ResizeBuffers manually after SetFullscreenState and that should work as well.
And yeah, MSDN has a good article about DXGI practices, including fullscreen transition:
http://msdn.microsoft.com/en-us/library/cc627095(VS.85).aspx#Full_Screen_Issues

Resources