Getting system theme setting of Android in Xamarin.Forms - xamarin

I have three radio buttons for selecting my app's theme: Default, which should apply whichever theme is selected in Android's system settings, Light and Dark.
The problem is that whenever I select the Default radio button it doesn't return a standard value as I am expecting, but either OSAppTheme.Light or OSAppTheme.Dark, whichever the previous setting was. In other words it reapplies the previous setting.
Here is my code:
private void DarkMode(object sender, CheckedChangedEventArgs e)
{
if (defaultRadioButton.IsChecked == true)
{
if (Application.Current.RequestedTheme != OSAppTheme.Unspecified)
{
Application.Current.UserAppTheme = Application.Current.RequestedTheme;
}
else
{
Application.Current.UserAppTheme = OSAppTheme.Light;
}
}
else if (lightRadioButton.IsChecked == true)
{
Application.Current.UserAppTheme = OSAppTheme.Light;
}
else if (darkRadioButton.IsChecked == true)
{
Application.Current.UserAppTheme = OSAppTheme.Dark;
}
}
I had the impression that Application.Current.RequestedTheme always carried the system's setting, which I guess from the behavior I'm encountering isn't true.
If Application.Current.RequestedTheme doesn't get the system's theme setting, then which is the correct way to detect if a user has enabled Dark Mode at the OS level?

According to this case about Manually apply dark theme in Xamarin.Forms, the Application.Current.UserAppTheme only applys for the theme defined with AppThemeBinding.
So if you want to change the UI's theme with this property, you need to use the AppThemeBinding in your control such as the example code in the official document.
In addition, the Application.Current.RequestedTheme can really get the device's system's current theme. But you can also try to get the android device's current theme with the following code in the MainActivity:
var theme = this.Resources.Configuration.UiMode & Android.Content.Res.UiMode.NightMask;
//if the value is Android.Content.Res.UiMode.NightNo means the device is using light mode
//if the value is Android.Content.Res.UiMode.NightYes means the device is using dark mode
And then you can declare a dark theme in the Project.Droid/Resource/values/style.xml and use it or just use the AppThemeBinding as the official document does to apply the dark theme in your application.
Update
Set the device's theme as dark
Call the code above:
Application.Current.UserAppTheme = OSAppTheme.Light;
var theme = Application.Current.RequestedTheme;
The value will be dark. It should be a bug, you can report it on the github.

Related

p5.js global and instance mode confusion

I have two p5 sketches, and I want to use them in the same space of a website. So that after clicking a button, the sketches switch. So I made three different files. The first two, are the sketches, and they are wrapped in a function (instance mode). The third sketch is a code written in global mode, because It has the information that loads a button right when the website is first accesed, and it has the information containing what the button is supposed to do: call the other sketches.
The code looks like this:
var playing = false;
var button;
function setup() {
var col = color(185,185,185,150);
button = createButton('Play');
button.position(20,20);
button.parent('black');
button.style("background-color", col);
button.style("padding", "10px 20px");
button.style("font-size", "14px");
button.mousePressed(toggleCanvas); // attach button listener
}
function mousePressed() {
}
function toggleCanvas() {
if (playing) {
if(myp5r){
myp5r.remove();
runSketch();
button.html('Stop');
}else{
runSketch();
button.html('Stop');
}
}else {
if(myp5){myp5.remove();
stopSketch();
button.html('Play');
}else{
stopSketch();
button.html('Play');}
}
playing = !playing;
}
I have been warned, to not mix global and instance mode, although my "common sense" says that it is ok to use a global mode for the button. Because I want it to be loading first, along with the page.
I noticed that weird things happen, though. Like, I get a blank space added beneath the footer, it looks horrible. And, even more worse, button is not appearing in the correct spot in the site. I already ckecked that css has position:relative for example. And the design works in localhost, but not in the site.

LightSwitch Tabbed screen in Browse template

I have a screen where we have 4 tabs, each tab should be displayed as per the login priority.
Ex:Department,Role,Employee,Screen are the tabs.
Each tab is having buttons to add,edit,remove the data.
by default when i log with any user its going to the first tab, but not all the users are having the first tab as their requirement.
how can i resolve this to do it dynamically in html client application
As covered towards the end of the following LightSwitch Team blog post, you can programmatically change the tab by using the screen.showTab method:
Creating a wizard-like experience for HTML client (Andy Kung)
However, in order to use this showTab API command when your screen is loading, its use needs to be delayed until the screen has fully displayed. This can be achieved in your screen's created method by using a combination of the jQuery mobile pagechange event (as the LightSwitch HTML Client uses jQuery mobile) and a setTimeout with a zero timeout (to delay the showTab until the loading screen is rendered).
The following shows a brief example of how you can use this approach to dynamically set the initial screen tab:
myapp.BrowseScreen.created = function (screen) {
var initialTabName = localStorage.getItem("Rolename") + "Tab";
$(window).one("pagechange", function (e, data) {
setTimeout(function () {
screen.showTab(initialTabName);
});
});
};
Based on your earlier post it appears that you're using LocalStorage to track your logged in user and their role.
On this basis, the above example assumes that the user's role will be the factor dictating the tab they are shown when the screen loads (the screen is named BrowseScreen in the above example).
It also assumes that your tabs are named after each employee role (suffixed with the text 'Tab') e.g. a user who is assigned the role 'DepartmentManager' would be directed to a tab called 'DepartmentManagerTab'.
Whilst slightly more involved, if you'd prefer to avoid the pagechange and setTimeout it's possible to customise the LightSwitch library to introduce a new navigationComplete screen event. This new event is ideal for executing any operations dependent upon the screen having fully rendered (such as navigating to a different tab using the showTab function).
If you'd like to introduce this additional event, you'll need to reference the un-minified version of the LightSwitch library by making the following change in your HTML client's default.htm file (to remove the .min from the end of the library script reference):
<!--<script type="text/javascript" src="Scripts/msls-?.?.?.min.js"></script>-->
<script type="text/javascript" src="Scripts/msls-?.?.?.js"></script>
The question marks in the line above will relate to the version of LightSwitch you're using.
You'll then need to locate the section of code in your Scripts/msls-?.?.?.js file that declares the completeNavigation function and change it as follows:
function completeNavigation(targetUnit) {
msls_notify(msls_shell_NavigationComplete, { navigationUnit: targetUnit });
var screen = targetUnit.screen;
var intialNavigation = !screen.activeTab;
var selectedTab = targetUnit.__pageName;
if (screen.activeTab !== selectedTab) {
callNavigationUnitScreenFunction(targetUnit, "navigationComplete", [intialNavigation, selectedTab]);
screen.activeTab = selectedTab; // Set at the end of the process to allow the previous selection to be referenced (activeTab)
}
}
function callNavigationUnitScreenFunction(navigationUnit, functionName, additionalParameters) {
var screenObject = navigationUnit.screen;
var constructorName = "constructor";
var _ScreenType = screenObject[constructorName];
if (!!_ScreenType) {
var fn = _ScreenType[functionName];
if (!!fn) {
return fn.apply(null, [screenObject, navigationUnit].concat(additionalParameters));
}
}
}
You can then use this new event in your screens as follows:
myapp.BrowseScreen.navigationComplete = function (screen, navigationUnit, intialNavigation, selectedTab) {
if (intialNavigation) {
var initialTabName = localStorage.getItem("Rolename") + "Tab";
screen.showTab(initialTabName);
}
};
This event fires whenever a navigation event completes (including a change of tab) with the initialNavigation parameter being set to true upon the initial load of the screen and the selectedTab parameter reflecting the selected tab.
Although modification to the LightSwitch library aren't uncommon with some of the more seasoned LightSwitch developers, if you decide to go down this path you'll need to thoroughly test the change for any adverse side effects. Also, if you upgrade your version of LightSwitch, you'll need to repeat the library modification in the new version.

titanium alloy set view visibility

i have a question on what the object.visible property in titanium alloy actually means.
in the profile.js controller file of the app there is a check if the user is logged in (state = null) and depending on this either (a) a "not logged in" a text label message (id = not_logged_in_message) shows up or (b) the profile data is visible.
now when the user is logged in, the text label (or rather its content) does not show up but it seems that the xml label tag (marked in darkred rectangle) is still there pushing everything lower.
if (state === null) {
$.topBar.setTitle(L('Please login'));
$.profile.visible=false;
$.not_logged_in_message=true;
} else {
$.topBar.setTitle(L('Profile'));
$.profile.visible=true;
$.not_logged_in_message=false;
get_profile();
}
thx for any suggestion!
Check this out at the appcelerator forum:
http://developer.appcelerator.com/question/161936/vertical-layout-visible--false-but-controls-still-occupying-space
Visible means: its hidden from the view but not removed from the structure.
You could try the suggestions from the answer over there, like removing the label or alter the width and height.

Adding functionality to wicket palette button

I want to add some functionality to the right arrow button, the one that puts the user selection into the selected elements panel. Specifically, when the user selects an element from the avaliable choices, I don't want the element to be taken to the selected elements panel if there are elements at the right panel of another palette. So basically, what I need is to execute custom java code when the button is pressed, and alter the default behavior of the palette when a condition occurs.
I found the solution somewhere else. Just in case someone needs it, here is what you have to do.
myPalette = new Palette<MyClass>(...) {
#Override
protected Recorder newRecorderComponent() {
Recorder<MyClass> recorder = super.newRecorderComponent();
recorder.add(new AjaxFormComponentUpdatingBehavior("onchange") {
protected void onUpdate(AjaxRequestTarget target) {
// Custom code
...
if (target != null)
// Update another component
target.add(anotherComponent);
}
}
);
return recorder;
}
};

How to tell if the user has selected a Light or Dark theme

Is there a way to tell if the user has selected a Light or Dark theme?
Thanks!
There is a property to test for this, rather that comparing the actual resource color.
Visibility v = (Visibility)Resources["PhoneLightThemeVisibility"];
if (v == System.Windows.Visibility.Visible)
{
// Is light theme
}
else
{
// Is dark theme
}
If you intend to detect the theme in code, then here is a solution -
var backColor = Resources["PhoneBackgroundColor"];
if (backColor.ToString() == "#FF000000")
// Dark theme selected => do something
else
// Light theme selected => do something
HTH,
indyfromoz

Resources