A fully Immersive fragment doesn't always hide the StatusBar when first launched - xamarin.android

Since Android 11 the correct way of displaying a fully immersive fragment is by hiding and showing StatusBar and NavigationBars via the following code which fully supports all devices with a camera notch, at any API level. Note the WindowCompat version replaces the framework version, so you don’t need to check for a particular API level as you did when using the framework version.
Hide
WindowCompat.SetDecorFitsSystemWindows(Activity.Window, false);
WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.GetInsetsController(Activity.Window, Activity.Window.DecorView);
windowInsetsControllerCompat.SystemBarsBehavior = WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
windowInsetsControllerCompat.Hide(WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars());
Show
WindowCompat.SetDecorFitsSystemWindows(Activity.Window, true);
WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.GetInsetsController(Activity.Window, Activity.Window.DecorView);
windowInsetsControllerCompat.Show(WindowInsetsCompat.Type.StatusBars() | WindowInsetsCompat.Type.NavigationBars());
This eliminated the overly complex, very poorly documented and potentially error-prone code like below, which was used prior to Android 11.
Window.DecorView.SystemUiVisibility = (StatusBarVisibility) (SystemUiFlags.Fullscreen |
SystemUiFlags.HideNavigation |
SystemUiFlags.Immersive |
SystemUiFlags.ImmersiveSticky |
SystemUiFlags.LayoutHideNavigation |
SystemUiFlags.LayoutStable |
SystemUiFlags.LowProfile);
I was attempting to provide a choice of either displaying all fragments fully immersive or allowing some fragments to display as “letterboxed” i.e. not allowing the window to render into the DisplayCutout area. So my existing preference choice Devices with Notches/Cutouts allow full screen display would have to change to support multiple choice.
The problem I hit was that code I had used (like the WindowCompat code above since Android 11) was failing to display the fragment fullscreen when first launched. When it opened for the first time the window would attempt to go full screen, but only the NavigationBar would be removed. The StatusBar area was left as a black rectangle. You could see the animation of the time on the left and the icons on the right side of the StatusBar disappearing, (statusBar contents removed) but the window didn’t render into the StatusBar area. Immediately when rotated, the fragment became full screen and when rotated back to Portrait it corrected itself and was full screen again.
So in frustration, I went hunting on StackOverFlow looking for a solution but everything I found suggested that my ImmersiveFragment class was coded correctly. Then because this was my first attempt at using Material 3, I then started to suspect Material3, so I went backwards to my NavigationGraph6 project (Material2) and after much testing, I was able to reproduce the same problem, which eliminated Material3.
More searching on StackOverflow and I came across a Kotlin post that was the same as all the others, except that it had the following line – equivalent to this C# line.
Activity.Window.AddFlags(WindowManagerFlags.LayoutNoLimits)
So I added that line before the WindowCompat.SetDecorFitsSystemWindows(Activity.Window, false) in the HideSystemUi() and then cleared the flags before the WindowCompat.SetDecorFitsSystemWindows(Activity.Window, true) line in the ShowSystemUi with
Activity.Window.ClearFlags(WindowManagerFlags.LayoutNoLimits)
and immediately it worked.
So my question is why is this required and has anyone come across the same problem with immersive fragments?
Definition of LayoutNoLimits – Allow window to extend outside of the screen ???.
Does anyone have a clue what this definition actually means?
To test the code (comment out the new lines in ImmersiveFragment.cs). You can find the project NavigationGraph7 at https://github.com/gmck/NavigationGraph7. The immersiveFragment is the RaceResultsFragment (inherits from ImmersiveFragment) accessed by the BottomNavigationBar on the SlideShowFragment.

I referred to the official doc both Android and Microsoft too. As you said that: "Allow window to extend outside of the screen". There are few official definitions of it...
You can check Can I set FLAG_LAYOUT_NO_LIMITS only for status bar?, it talks about usage of LayoutNoLimit. Wish it could be helpful to you.

Related

Avalonia : Hiding titlebar window on Linux does not work

I'm using avalonia (version 0.10.3 - but the same happened with 0.10.0 - on Net5.0 project) as the UI for a project and when I create for instance a splash or an about screen, the title bar must be invisible.
On windows this works just fine with these parameters in the window section :
CanResize="False"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
ExtendClientAreaTitleBarHeightHint="0"
Unfortunately, on Linux (mint - latest version with latest updates), the title bar remains visible (also if I set ExtendClientAreaTitleBarHeightHint="-1").
Is this a known issue or am I doing something wrong ?
I do not have a mac, but is that also the case for mac ?
X11 uses so-called "server decorations". Window frame is drawn by a window manager in a separate process, so it's not really possible to extend into that area.
You can still disable the frame completely and draw your own, but in general it's not really recommended since you will break advanced window interactions in basically every non-GNOME based Linux distro (GNOME doesn't care because it doesn't have any advanced window interactions).
In some future version Avalonia would use a custom-drawn frame for GNOME with a configuration option to ignore your user's preferences in favor of a fancy looking window border for other desktop environments as well, but it's not implemented yet.
I had a similar problem but I "solve it" by defining the window property as:
WindowState = WindowState.FullScreen;
Comparing with Normal or Maximized, with title bar in fullscreen remains hidden.

Larger search bar in iOS 11? How to opt-into new style?

I noticed that in the App Store app, the UISearchBar they're using is larger. (see attached) — Currently when I compile for iOS 11b9 using Xcode 9b6, it still uses the old style, which is too small and is clipped by the status bar.
Is there some clean way to enable/mimic this larger variant of UISearchBar, while still maintaining backwards compatibility with older iOS versions?
I did find after the iPhone X announcement (and subsequent video additions to the Developer site) that there is a bit of a workaround necessarily: https://developer.apple.com/videos/play/fall2017/201
For iOS 11+ only:
Apply the UISearchController to the "navigationItem" not the UIViewController itself. Then set it to be "active" (= true).
Ensure this hidesNavigationBarDuringPresentation is true.
Monitor the delegate callback to track when it was dismissed, and then remove it from the "navigationItem" until it's needed again.
... Honestly it seems like this was a bit of an afterthought, but it does work and is good enough for now.

WatchKit reloadRootControllersWithNames causing error, with pageController or after push/pop

I have a basic watchkit app that loads a page based navigation of 3 interface controllers. This works well, but I'd then like to trigger an action to remove the page-control and essentially revert back to the original InterfaceController that was present when the app first loads.
// load page based control, with 3 views. this works ok
[WKInterfaceController reloadRootControllersWithNames:#[#"pageController1",#"pageController2",#"pageController3"]
contexts:#[#"data1",#"data2",#"data3"]];
// attempt to reload original interface controller, identified by storyboard id
[WKInterfaceController reloadRootControllersWithNames:#[#"myInterfaceController"] contexts:#[#{}]];
The page based navigation remove, the original navigation loads after a short spinner. However it fails to function correctly and original Actions result in this error.
Extension[6766:123665] *********** ERROR
-[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:(null) not found
Is there a better way to cleanly reload the original InterfaceController?
EDIT, 2/19
It seems there are some other actions that are causing this error too. For instance, if segue to a second InterfaceController and then popController to get back, the error often appears. It is always related to a secondary call to this function.
[WKInterfaceController reloadRootControllersWithNames: contexts:]
EDIT2, 3/18
As previously mentioned, this is reproducible 100% of the time by doing the seguePush, the popController, then attempting to reloadRootControllersWithNames.
If the seguePush/popController is not done beforehand, then the reloadRootControllersWithNames will work fine.
This situation seems to be in addition to the multi->single-multi instance of this bug.
This is actually not a bug because according to Apple:
You cannot combine hierarchical and page-based interface styles. At design time, you must choose the style that best suits your app’s content and design for that style.
So unfortunately, we can't mix Hierarchical and Page-based navigation patterns within the same Watch app.
Just one of many limitations we have to deal with when developing apps for  Watch
This is a bug in WatchKit in Xcode 6.2 Beta 5. Please dupe the following radar on Apple's Bug Reporting System to help raise the priority to get this fixed.
In the meantime, a workaround that I've found can be found on the dev forums. What you can do is add a dummy interface controller to any single interface controller page set so you always have two. This will fix the error until Apple get's the bug fixed (hopefully in Beta 6). Please dupe!
I was able to solve my instance of this problem by not using popController on a pushed view controller. Instead I use a reloadRootControllersWithNames in place of the popController.
How this allows both push and paging, via an example:
Push a view controller
reloadRootControllersWithNames to return to the original controller. (The transition is not quite as animated, but is sufficient)
Create page based view controller.
reloadRootControllersWithNames to return to the original controller
Repeat 1 or 3 as needed.
This eliminates the error at the cost of non-animated popControllers, and allows partial pushing and paging. It would not allow more complex push navigation though.
There may be a better method of navigating to a sub interface controller without a push call, but I'm not aware of it on the watch yet.
None or the answers above worked for me. This problem began when I changed the icon names for the app and the watch app name. I solved it like this:
1) Click on your Watch app Target > Capabilities > make sure app Group
is in ON.
2) Make sure the App Group is selected.
3) Clic on the circled arrow Refresh icon (this will apparently just
refresh this thing if you already had it)
4-Repeat steps 1-3, but for your Watch App EXTENSION target too.
5-Click on the Scheme button (on the right side of the STOP button),
and clic on Edit Schemes.
6-Click Run > Info 7-In executable select your target (Actually it
should already be selecting but opening this window seems to
refresh the option, and wipe the error)
Apparently all these things above are not updated automatically when you change the icon name (Target names) and you have to go to those menus and open them to refresh them manually. Shame on Apple perhaps?

Open Flash Chart - tooltip #x_label# not showing

I'm currently playing with a bar chart implemented through Open Flash Charts (I believe version 1, might be version 2...) with PHP. Unfortunately, we're having real trouble with the tooltip not showing the correct thing. I am trying to get it to show the x-axis label for the hovered-over column, then a ":", then the value of the bar. The code is as follows:
$Colour = '#3465A4';
$BarChart= new bar();
$BarChart->set_values($Bar);
$BarChart->set_colour($Colour);
$BarChart->set_tooltip('#x_label#:#val#');
$x_labels = new x_axis_labels();
$x_labels->set_labels($Roles);
$x_labels->rotate(-60);
$x = new x_axis();
$x->set_labels($x_labels);
$chart = new open_flash_chart();
$chart->add_element($BarChart);
$chart->set_bg_colour( '#FFFFFF' );
$chart->set_x_axis($x);
$tooltip = new tooltip();
$tooltip->set_hover();
$chart->set_tooltip($tooltip);
$JSONArray['my_chart_1'] = $chart->toPrettyString();
As far as I can tell, this should be correct - the bar chart appears, with the correct values (populated from $bar, whose generation is not shown above). However, the hover-over tool-tip for a column only shows ":value" - the label name is missing!
Does anyone know where we might have gone wrong, and how I can fix it?
EDIT:
An update for any Bounty Hunters coming in to try and answer this question. The reason I have not accepted the below answer is that it only provides a work-around, and does not explain why the work-around is necessary. I am looking either for an answer to my original question (how to make the labels show in a normal bar-chart), or a reasonable explanation regarding why one must use a stacked bar chart (including sources makes your answer so much better!). If the latter, example code or an explanation of how stacked charts are created would be much appreciated as well!
If you are happy with the simple bar visuals then use stacked bar (using it with an array of one element will draw it just like the simple bar). That one will replace #x_label# correctly.
Alternatively you can copy the missing code from Bars/Stack.as to other bar types and recompile the code.
As per: http://forums.openflashchart.com/viewtopic.php?p=7433#p7433
It's a bug in OFC2 in the latest versions (at least). I've found what is causing the issue with #x_label#, but my understanding of the code/Flash isn't good enough to know why it's happened/broken.
I've done a quick fix that I need to test some more, but it now works on bar charts. Assuming I've not broken anything else beyond repair, it'll make it's way into the next community release.
If anyone wants the source code changes before the next release let me know.
(I am currently maintaining the community releases)

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