Hide status bar on screen rotation - c#

Is it possible to hide the status bar on screen rotation events in Windows Phone 8.1?

The following code shows the status bar on Portrait orientation, and hides it on Landscape orientation.
First you need to subscribe to the ApplicationView.VisibleBoundsChanged event. You can do this for example in your App.xaml.cs constructor:
ApplicationView.GetForCurrentView().VisibleBoundsChanged += OnVisibleBoundsChanged;
You hide the status bar with the StatusBar.GetForCurrentView() instance.
OnVisibleBoundsChanged method:
private async void OnVisibleBoundsChanged(ApplicationView sender, object args)
{
var currentView = ApplicationView.GetForCurrentView();
if (currentView.Orientation == ApplicationViewOrientation.Portrait)
{
await StatusBar.GetForCurrentView().ShowAsync();
}
else if (currentView.Orientation == ApplicationViewOrientation.Landscape)
{
await StatusBar.GetForCurrentView().HideAsync();
}
}

Related

How can I make a custom renderer for ToolbarItem in Xamarin.Forms?

I am working with Xamarin.Forms app. I am trying to add Speech to Text functionality to Xamarin.Forms through a toolbar item click. When I click the button on tool I want the builtin phone speech service to open and convert my speech to text and add to page's label.
Problem: In order to trigger the speech service which is android specific. I need a custom renderer for the toolbar item. So, I can add the code for speech to text in that custom renderer's OnClick method. but I can't seem to find the renderer class for toolbar item.
Here is code of my current attempt at Toolbar Item renderer
VoiceToolbarItemRenderer.cs
[assembly: ExportRenderer(typeof(VoiceToolbarItem), typeof(VoiceToolbarItemRenderer))]
namespace Xamarin_App.Droid
{
public class VoiceToolbarItemRenderer : PageRenderer, Android.Views.View.IOnClickListene
{
private bool isRecording;
private readonly int VOICE = 10;
private MainActivity activity;
private VoiceToolbarItem sharedToolbarItem;
private Toolbar nativeButton;
private SpeechRecognizer mSpeechRecognizer;
private Intent mSpeechRecognizerIntent;
public VoiceToolbarItemRenderer(Context context) : base(context)
{
isRecording = false;
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
activity = this.Context as MainActivity;
nativeButton = new global::Android.Widget.Toolbar(Context);
if (e.OldElement == null)
{
// perform initial setup
//SetNativeControl();
nativeButton.Clickable = true;
nativeButton.Focusable = true;
nativeButton.SetOnClickListener(this);
}
if (e.OldElement != null)
{
activity.ActivityResult -= HandleActivityResult;
}
if (e.NewElement != null)
{
activity.ActivityResult += HandleActivityResult;
sharedToolbarItem = e.NewElement.ToolbarItems as VoiceToolbarItem;
}
}
public void OnClick(Android.Views.View view)
{
try
{
string rec = Android.Content.PM.PackageManager.FeatureMicrophone;
if (rec != "android.hardware.microphone")
{
// no microphone, no recording. Disable the button and output an alert
var alert = new AlertDialog.Builder(Context);
alert.SetTitle("You don't seem to have a microphone to record with");
alert.SetPositiveButton("OK", (sender, e) => {
return;
});
alert.Show();
}
else
{
// create the intent and start the activity
var voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
// if there is more then 1.5s of silence, consider the speech over
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 15000);
voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults, 1);
// you can specify other languages recognised here, for example
// voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.German);
// if you wish it to recognise the default Locale language and German
// if you do use another locale, regional dialects may not be recognised very well
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.Default);
activity.StartActivityForResult(voiceIntent, VOICE);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void HandleActivityResult(object sender, ActivityResultEventArgs e)
{
if (e.RequestCode == VOICE)
{
if (e.ResultCode == Result.Ok)
{
var matches = e.Data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
if (matches.Count != 0)
{
string textInput = matches[0];
// limit the output to 500 characters
if (textInput.Length > 500)
textInput = textInput.Substring(0, 500);
sharedToolbarItem.OnTextChanged?.Invoke(textInput);
//textBox.Text = textInput;
}
else
sharedToolbarItem.OnTextChanged?.Invoke("No speech was recognised");
}
}
}
}
}
If someone has an Idea of making toolbarItem's custom renderer or any other suggestions please let me know.
By toolbar I suppose you mean the navigation bar (or the bar where you get the Page Title , right? )
If that is the case , then you have two options:
Wait for the next release of Xamarin.Forms they are working on being able to add stuff to the toolbar. (for example you can have your own back button)
You can make your own toolbar , just make sure to not show the Navigation bar on the NavigationPage, and make your own toolbar (e.g. a horizontal stacklayout (or flexlayout) where you place the title and the buttons you need . and has a background color .
I have tried to do custom renderer for the toolbar and it seems that it is not an easy job.

UWP StoreContext provides inaccurate information in RELEASE version

I have an app, published in Windows Store and the app has a trial version. But recently the trial version provides the full version somehow.
When I debugged the code, it shows that the following piece of code gets called twice in the release version and once it says that Trial is true and secondly it says Trial is false.
if (storeContext == null)
{
storeContext = StoreContext.GetDefault();
}
appLicense = await storeContext.GetAppLicenseAsync();
if (appLicense.IsActive)
{
if (appLicense.IsTrial)
{
isTrial = true;
}
else
{
isTrial = false;
}
}
When I debug the code in Release version it appLicense.IsTrial gets evaluated two times and that's how it produces two different results. Is it a bug? Should I tell Microsoft about this? Or is it just related to me somehow? If you try my app from store here you can probably see that it provides full access to the application and that the search is available to use while it's disabled in Trial version. Please help me with this.
Update:
The ExtendedSplash code:
public sealed partial class ExtendedSplash : Page
{
internal Rect splashImageRect; // Rect to store splash screen image coordinates.
private SplashScreen splash; // Variable to hold the splash screen object.
internal bool dismissed = false; // Variable to track splash screen dismissal status.
internal Frame rootFrame;
// Define methods and constructor
public ExtendedSplash(SplashScreen splashscreen, bool loadState)
{
InitializeComponent();
// Listen for window resize events to reposition the extended splash screen image accordingly.
// This ensures that the extended splash screen formats properly in response to window resizing.
Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);
splash = splashscreen;
if (splash != null)
{
// Register an event handler to be executed when the splash screen has been dismissed.
splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);
// Retrieve the window coordinates of the splash screen image.
splashImageRect = splash.ImageLocation;
//PositionImage();
// If applicable, include a method for positioning a progress control.
//PositionRing();
}
// Create a Frame to act as the navigation context
rootFrame = new Frame();
}
void PositionImage()
{
//extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
//extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
//extendedSplashImage.Height = splashImageRect.Height;
//extendedSplashImage.Width = splashImageRect.Width;
}
void PositionRing()
{
splashProgressRing.SetValue(Canvas.LeftProperty, splashImageRect.X);// + (splashImageRect.Width * 0.5) - (splashProgressRing.Width * 0.5));
splashProgressRing.SetValue(Canvas.TopProperty, (splashImageRect.Y + splashImageRect.Height));// + splashImageRect.Height * 0.1));
}
// Include code to be executed when the system has transitioned from the splash screen to the extended splash screen (application's first view).
async void DismissedEventHandler(SplashScreen sender, object e)
{
dismissed = true;
// Complete app setup operations here...
await TrialManager.IsTrialLicense();
// this is the code that gets called to see the Trial / Purchase
DismissExtendedSplash();
}
async void DismissExtendedSplash()
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Navigate to mainpage
rootFrame.Navigate(typeof(IndexPage));
// Place the frame in the current Window
Window.Current.Content = rootFrame;
});
}
void ExtendedSplash_OnResize(Object sender, WindowSizeChangedEventArgs e)
{
// Safely update the extended splash screen image coordinates. This function will be executed when a user resizes the window.
if (splash != null)
{
// Update the coordinates of the splash screen image.
splashImageRect = splash.ImageLocation;
//PositionImage();
// If applicable, include a method for positioning a progress control.
//PositionRing();
}
}
void RestoreStateAsync(bool loadState)
{
if (loadState)
{
// code to load your app's state here
}
}
}

ProgressRing is not showing while the app runs

I am developing a 'Universal App' for Windows 8.1 and Windows Phone 8.1
I need to add a ProgressRing control to my page, because there is a task which takes some time to complete and I should notify the user that the app is loading data. So I followed the instruction on MDSN in the following link:
To create an indeterminate progress ring
and they stated what I exactly need:
4. Adding an indeterminate progress ring
When you can't estimate how much work remains to finish a task and the
task does block user interaction, use an indeterminate progress ring.
An indeterminate progress ring shows an animate sequence of dots
moving in a circle.
The problem is that the ProgressRing doesn't play the animation of "loading", when I insert prog.IsActive = true; before the code that starts the task
If I comment the Task lines of code, it plays.
XAML :
<ProgressRing x:Name="prog" Margin="435,349,388,181" FontFamily="{StaticResource FontFamily6}" FontSize="25" />
C#:
private void LevelTap(object sender, TappedRoutedEventArgs e)
{
prog.IsActive = true;
CheckNav(sender);
}
private void CheckNav(object sender)
{
TextBlock tb = sender as TextBlock;
GameSetter game = new GameSetter();
game.Level = (int)TextDict[tb];
if (!LevelsArr[game.Level]) return;
if (!goToLeader)
{
prog.IsActive = false;
CallNav(true, game);
}
else
{
prog.IsActive = false;
CallNav(false, game);
}
}
private void CallNav(bool b,GameSetter g)
{
if(b) Frame.Navigate(typeof(Game8), g);
else Frame.Navigate(typeof(MainPage), g);
}
Note: The Task that runs uses Dictionary, Windows.Storage.ApplicationData, and Navigation for another page in the end.
You can use this code block in every function too if Progressing inDeterminate mode always open:
#region Progress Ring Start
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Waiter.Visibility = Visibility.Visible; // Progress ring name is Waiter.
});
#endregion
await Task.Delay(1000);
CheckNav(sender); // Your process
#region Progress Ring Finish
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Waiter.Visibility = Visibility.Collapsed; // Progress ring name is Waiter.
});
#endregion
The flaw in your code (except the fact that it's probably nearly instant anyway, as notes #kennyzx), is that you need the LevelTap method to return for the UI to be updated. And when the method returns, you've already set the ProgressRing.IsActive property back to false, which means nothing is displayed at all.
One simple way to fix that is to use the async Task.Yield method to give the UI thread a chance to run:
private async void LevelTap(object sender, TappedRoutedEventArgs e)
{
prog.IsActive = true;
await Task.Yield();
CheckNav(sender);
}
But almost nothing will be shown since your code shouldn't take long to execute. If you really want to force the indicator to be displayed for 0.5 seconds, you can do something like:
private async void LevelTap(object sender, TappedRoutedEventArgs e)
{
prog.IsActive = true;
await Task.Delay(500);
CheckNav(sender);
}

How can I animate a progress indicator in a splash screen of a windows application

I have created a splash screen in my windows application. I want a cycling "ring" progress indicator (like the one shown on the Windows 8 boot screen) to be added on splash screen until the main form is connected. The code in program.cs is:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
logo f = new logo();
f.Shown += new EventHandler((o, e) =>
{
System.Threading.Thread t = new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(4000);
f.Invoke(new Action(() => { f.Close(); }));
});
t.IsBackground = true;
t.Start();
});
}
logo is the start up form or splash screen I want to add progress bar or ring progress indicator to as in windows 8 startup.
There isn't a specific "cycle" progress ring control within the default control set, so I'd say you have two options:
Add a standard horizontal ProgressBar, and set its style to Marquee - this will give you the indeterminate "progress is happening but we're not sure when it's going to finish" look:
myProgressBar.Style = ProgressBarStyle.Marquee;
If you want a ring/circular progress indicator, then you're better off using an animated .gif or similar and the ImageAnimator control.
There is a good example of loading a gif and stepping through the frames on MSDN on the documentation for the ImageAnimator.Animate method:
Create a control, such as "AnimatedProgress":
public partial class AnimatedProgress : UserControl
{
//Create a Bitmpap Object.
Bitmap animatedImage = new Bitmap("circle_progress_animation.gif");
bool currentlyAnimating = false;
//This method begins the animation.
public void AnimateImage()
{
if (!currentlyAnimating)
{
//Begin the animation only once.
ImageAnimator.Animate(animatedImage, new EventHandler(this.OnFrameChanged));
currentlyAnimating = true;
}
}
private void OnFrameChanged(object o, EventArgs e)
{
//Force a call to the Paint event handler.
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
//Begin the animation.
AnimateImage();
//Get the next frame ready for rendering.
ImageAnimator.UpdateFrames();
//Draw the next frame in the animation.
e.Graphics.DrawImage(this.animatedImage, new Point(0, 0));
}
}
Add this control to your logo form:
public Logo()
{
InitializeComponent();
var progressSwirl = new AnimatedProgress();
progressSwirl.Location = new Point(50, 50);
Controls.Add(progressSwirl);
}
(I found adding it via code worked better than using the designer as I'd just referenced the image fairly crudely in my AnimatedProgress control and the VS designer couldn't find the image.)
Your cycling ring will then appear on your splash screen.
In terms of the "simplest" way to show the splash screen props must go to Veldmius for pointing out the SpalshScreen property:
Start by adding a reference to Microsoft.VisualBasic.dll to your project, then update your program.cs to something like:
using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;
namespace WindowsFormsApplication1
{
public class Startup : WindowsFormsApplicationBase
{
protected override void OnCreateSplashScreen()
{
SplashScreen = new logo();
}
protected override void OnCreateMainForm()
{
MainForm = new Form1();
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
new Startup().Run(new string[]{});
}
}
}
To test this, I added a Thread.Sleep(5000) to the loading event of my main form, and there you have it - my logo page displayed with an animated progress for 5 seconds then my main form loaded in.

Keep track of screen change and screen resolution change in Windows Form Application to change form size

I want to change form size depending on Screen and it's resolution.
What I want is a correct event to track these screen changes as well as screen resolution changes at runtime.
In other words,
If user is using two screens and move application to another screen, that should be tracked and change size accordingly, i.e. reduce size if new screen's resolution is low or increase size if resolution is larger.
Also track screen resolution change on the same screen, and make changes to size accordingly.
I know how to change Form size, get current screen and it's resolution, just need these events to keep track of these changes.
Going over this answer I've decided to improve it and add further information to form a more complete solution.
The Challenge
Tracking which screen a Form is currently being rendered on. This can change if a user drags the form to another monitor or unplugs a monitor. The resolution can change if a user manually drags a window to a different display or changes the resolution directly.
Firstly, tracking form location. We need to hook into a Move event for the form context, fortunately the .Net framework provides such an event, and it is named Control.Move Event.
Secondly, we will need to hook into a screen resolution changed event, we can do this with the SystemEvents.DisplaySettingsChanged event.
And putting it together, I got this:
struct Resolution
{
public int Width;
public int Height;
}
int previous = -1;
int current = -1;
private bool CheckScreenChanged()
{
bool changed = false;
current = GetScreenIndex();
if (current != -1 && previous != -1 && current != previous) // form changed screen.
{
changed = true;
}
previous = current;
return changed;
}
private int GetScreenIndex()
{
return Array.IndexOf(Screen.AllScreens, Screen.FromControl(this));
}
private Resolution GetCurrentResolution()
{
Screen screen = Screen.FromControl(this);
Resolution res = new Resolution();
res.Width = screen.Bounds.Width;
res.Height = screen.Bounds.Height;
return res;
}
private void SetResolutionLabel()
{
Resolution res = GetCurrentResolution();
label2.Text = String.Format("Width: {0}, Height: {1}", res.Width, res.Height);
}
private void ScreenChanged()
{
label1.Text = "Screen " + current.ToString();
}
private void Form_Moved(object sender, System.EventArgs e)
{
bool changed = CheckScreenChanged();
if (changed == true)
{
ScreenChanged();
SetResolutionLabel();
}
}
public void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
SetResolutionLabel();
}
public void Initialize()
{
this.Move += Form_Moved;
SystemEvents.DisplaySettingsChanged += new
EventHandler(SystemEvents_DisplaySettingsChanged);
previous = GetScreenIndex();
current = GetScreenIndex();
ScreenChanged();
SetResolutionLabel();
}
The code above is tested on a simple form with two labels called label1 and label2, which are updated when the screen the form is on changes or the resolution changes.
An image of this in action on my primary screen/display
And on my secondary screen/display when the form has been dragged to it:

Categories