how to stop a stopwatch with a button click in Xamarin? - xamarin

Goal is to measure the reaction time of the user. 3-10 seconds after clicking the start button it should start the stopwatch and make the stop button visible. After the user clicks the stop button, it should stop the watch and display the milliseconds the user took to respond.
I am having trouble coming up with a solution as to how to implement a loop that would check if the button has been pressed and to stop the watch without blocking the user from clicking the button.
public partial class Main : ContentPage
{
public Main()
{
InitializeComponent();
}
public void OnStartClicked(object sender,EventArgs args)
{
Stopwatch stopWatch = new Stopwatch();
startButton.IsVisible = false;
BG.BackgroundColor = Color.Red;
status_text.Text = "Get Ready";
Random R = new Random();
Device.StartTimer(TimeSpan.FromSeconds(R.Next(3, 10)), () =>
{
stopWatch.Start();
stopButton.IsVisible = true;
BG.BackgroundColor = Color.Green;
long elapsed = stopWatch.ElapsedMilliseconds;
stopWatch.Stop();
status_text.Text = elapsed.ToString();
return false;
});
}
}}

Use the StopWatch as a member Variable and stop the watch in an OnStopClicked-Event. Read the elapsed time after stopping. Instead of button.IsVisible you could also use button.IsEnabled.
public partial class MainPage : ContentPage
{
Stopwatch mStopWatch = new Stopwatch();
public MainPage()
{
InitializeComponent();
}
private void StartButton_Clicked(object sender, EventArgs e)
{
startButton.IsVisible = false;
BG.BackgroundColor = Color.Red;
status_text.Text = "Get Ready";
Random R = new Random();
Device.StartTimer(TimeSpan.FromSeconds(R.Next(3, 10)), () =>
{
mStopWatch.Start();
stopButton.IsVisible = true;
BG.BackgroundColor = Color.Green;
return false;
});
}
private void StopButton_Clicked(object sender, EventArgs e)
{
mStopWatch.Stop();
long elapsed = mStopWatch.ElapsedMilliseconds;
status_text.Text = elapsed.ToString();
mStopWatch.Reset();
stopButton.IsVisible = false;
startButton.IsVisible = true;
}
}

Related

How to transfer data from one page to another xamarin

I have three pages, I enter the data on the second page and transfer it to page number one, returning to it at the same time, there is no problem with this, I use navigation, like this:
private async void OnSaveTitleButtonCliked(object sender, EventArgs e)
{
var title_data = new LabelViewModel
{
Label = editor.Text,
Date = DateTime.Now
};
var mainpage = new MainPage();
mainpage.BindingContext = title_data;
await Navigation.PushAsync(mainpage);
}
But I also need to transfer this data to page number three, so that I can go there from the first page and see, I tried the mvvm, but so far I have not understood how it works.
Please tell me how to do it better:)
Pass data by constructor:
In Page1:
private async void GoToPage2(object sender, EventArgs e)
{
var title_data = new LabelViewModel
{
Label = editor.Text,
Date = DateTime.Now
};
//Pass the model here
var Page2 = new Page2(title_data);
await Navigation.PushAsync(Page2);
}
In Page2:
public partial class Page2 : ContentPage
{
public LabelViewModel model;
public Page2(LabelViewModel m) {
InitializeComponent();
this.model = m;
//You can use your model here
}
}
Pass data by public property:
In Page1:
private async void GoToPage2(object sender, EventArgs e)
{
var title_data = new LabelViewModel
{
Label = editor.Text,
Date = DateTime.Now
};
var Page2 = new Page2();
//Pass the model here
Page2.model = title_data;
await Navigation.PushAsync(Page2);
}
In Page2:
public partial class Page2 : ContentPage
{
public LabelViewModel model;
public Page2()
{
InitializeComponent();
//You can use your model here
Console.WriteLine(model.Label);
Console.WriteLine(model.Date);
}
}
Let me know if you have any questions.
I'll let some examples here
On the first page (who calls the second one)
private async void MenuLista(object sender, EventArgs e)
{
var item = (ModelosPPP)((Button)sender).BindingContext;
if (PopupRunnning != false)
return;
var page = new MenuListSV(item);
PopupRunnning = true;
page.Action += async (a, b) =>
{
switch (b)
{
case 1:
await DisplayAlert("PDF", null, "ok");
break;
case 2:
await DisplayAlert("Reenviar", null, "ok");
break;
case 3:
await DisplayAlert("Excluir", null, "ok");
break;
}
};
page.Disappearing += (c, d) =>
{
PopupRunnning = false;
};
await PopupNavigation.Instance.PushAsync(page);
}
in Second Page
public partial class MenuListSV : PopupPage
{
public MenuListSV(Models.ModelosPPP obj)
{
InitializeComponent();
BindingContext = obj;
}
public EventHandler<int> Action;
public async void MenuChoice(object sender, EventArgs e)
{
var btn = sender as Button;
switch (btn.Text)
{
case "Abrir PDF":
Action?.Invoke(this, 1);
break;
case "Reenviar":
Action?.Invoke(this, 2);
break;
case "Excluir":
Action?.Invoke(this, 3);
break;
}
await PopupNavigation.Instance.PopAsync();
}
}

AVCaptureMetadataOutputObjectsDelegate, DidOutputMetadataObjects not always called

I trying to scan QR-codes in my app. It works sometimes and sometimes not. The feeling is that it doesn't work when something is loading on another thread. For example, if I press the scan button when nearby stores still are loading. Often it works if I wait.
The video capture is working because I will see the preview.
Here is my code:
private bool resultFound;
public ScannerView()
{
InitializeComponent();
On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(false);
view = new UIView();
ScannerArea.Children.Add(view);
}
void HandleAVRequestAccessStatus(bool accessGranted)
{
if (!accessGranted)
{
MainThread.BeginInvokeOnMainThread(async () =>
{
await NavigationHelper.Current.CloseModalAsync();
});
}
metadataOutput = new AVCaptureMetadataOutput();
var metadataDelegate = new MetadataOutputDelegate();
metadataOutput.SetDelegate(metadataDelegate, DispatchQueue.MainQueue);
session = new AVCaptureSession();
camera = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video).First();
input = AVCaptureDeviceInput.FromDevice(camera);
session.AddInput(input);
session.AddOutput(metadataOutput);
metadataOutput.MetadataObjectTypes = AVMetadataObjectType.QRCode | AVMetadataObjectType.EAN8Code | AVMetadataObjectType.EAN13Code;
metadataDelegate.MetadataFound += MetadataDelegate_MetadataFound;
camera.LockForConfiguration(out var error);
camera.VideoZoomFactor = 2;
camera.UnlockForConfiguration();
layer = new AVCaptureVideoPreviewLayer(session);
layer.VideoGravity = AVLayerVideoGravity.ResizeAspectFill;
layer.MasksToBounds = true;
layer.Frame = UIApplication.SharedApplication.KeyWindow.RootViewController.View.Bounds;
view.Layer.AddSublayer(layer);
session.StartRunning();
}
protected override void OnAppearing()
{
base.OnAppearing();
var status = AVCaptureDevice.GetAuthorizationStatus(AVMediaType.Video);
if (status != AVAuthorizationStatus.Authorized)
{
MainThread.BeginInvokeOnMainThread(() =>
{
AVCaptureDevice.RequestAccessForMediaType(AVMediaType.Video, HandleAVRequestAccessStatus);
});
return;
}
HandleAVRequestAccessStatus(true);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
session.StopRunning();
session.RemoveInput(input);
session = null;
}
void Handle_Clicked(object sender, System.EventArgs e)
{
NavigationHelper.Current.CloseModalAsync();
}
void MetadataDelegate_MetadataFound(object sender, AVMetadataMachineReadableCodeObject e)
{
if (resultFound)
{
return;
}
resultFound = true;
var text = e.StringValue;
Device.BeginInvokeOnMainThread(async () =>
{
Vibration.Vibrate(100);
await NavigationHelper.Current.CloseModalAsync();
TinyPubSub.Publish(NavigationParameter.ToString(), text);
});
}
}
public class MetadataOutputDelegate : AVCaptureMetadataOutputObjectsDelegate
{
public override void DidOutputMetadataObjects(AVCaptureMetadataOutput captureOutput, AVMetadataObject[] metadataObjects, AVCaptureConnection connection)
{
foreach (var m in metadataObjects)
{
if (m is AVMetadataMachineReadableCodeObject)
{
MetadataFound(this, m as AVMetadataMachineReadableCodeObject);
}
}
}
public event EventHandler<AVMetadataMachineReadableCodeObject> MetadataFound = delegate { };
}

Activity Indicator not working in Xamarin.Forms

I have an activity indicator designed inside a absolute layout. Based on a button click event, I try to show and hide the activity indicator alternatively. But due to some reason, I cannot see my activity Indicator.Any help will be greatly appreciated!!! Thanks in advance.
This is my .xaml.cs class:
public partial class PBTestPage : ContentPage
{
private bool _pbIndicator;
public PBTestPage()
{
InitializeComponent();
}
public bool PBIndicator{
get{
return _pbIndicator;
}set{
_pbIndicator = value;
OnPropertyChanged();
}
}
protected override void OnAppearing()
{
base.OnAppearing();
var parentLayout = new AbsoluteLayout();
var stackContent = new StackLayout();
AbsoluteLayout.SetLayoutFlags(stackContent,AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(stackContent,new Rectangle(0f,0f,AbsoluteLayout.AutoSize,AbsoluteLayout.AutoSize));
var activityIndicator = new ActivityIndicator
{
Color = Color.Black,
IsRunning = PBIndicator,
IsVisible = PBIndicator
};
AbsoluteLayout.SetLayoutFlags(activityIndicator, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(activityIndicator, new Rectangle(.5, .5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
var button = new Button
{
Text="Click",
VerticalOptions=LayoutOptions.CenterAndExpand,
HorizontalOptions=LayoutOptions.CenterAndExpand,
};
button.Clicked += OnClicked;
stackContent.Children.Add(button);
parentLayout.Children.Add(stackContent);
parentLayout.Children.Add(activityIndicator);
Content = parentLayout;
}
private void OnClicked(object sender, EventArgs e)
{
if(PBIndicator==false){
PBIndicator = true;
}else{
PBIndicator = false;
}
}
}
I'm inferring you're intending to use bindings by the use of OnPropertyChanged, so it's a good time to start do it.
I've made some changes in your code and I guess it will work properly now. The changes are:
Moved the layout creation to the constructor (I can't see create the whole same layout on every time the page is shown as a good choice );
The OnClicked event just invert the value of the property, no need to check it before with an if;
Using Bindings to handle the ActivityIndicator's properties state;
Set true to PBIndicator property on the OnAppearing event.
This is the changed code:
public partial class PBTestPage : ContentPage
{
private bool _pbIndicator;
public bool PBIndicator
{
get { return _pbIndicator; }
set
{
_pbIndicator = value;
OnPropertyChanged();
}
}
public PBTestPage()
{
InitializeComponent();
var parentLayout = new AbsoluteLayout();
var stackContent = new StackLayout();
AbsoluteLayout.SetLayoutFlags(stackContent, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(stackContent, new Rectangle(0f, 0f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
var activityIndicator = new ActivityIndicator
{
Color = Color.Black
};
activityIndicator.SetBinding(ActivityIndicator.IsRunningProperty, new Binding(nameof(PBIndicator)));
activityIndicator.SetBinding(ActivityIndicator.IsVisibleProperty, new Binding(nameof(PBIndicator)));
activityIndicator.BindingContext = this;
AbsoluteLayout.SetLayoutFlags(activityIndicator, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(activityIndicator, new Rectangle(.5, .5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
var button = new Button
{
Text = "Click",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
button.Clicked += OnClicked;
stackContent.Children.Add(button);
parentLayout.Children.Add(stackContent);
parentLayout.Children.Add(activityIndicator);
Content = parentLayout;
}
protected override void OnAppearing()
{
base.OnAppearing();
PBIndicator = true;
}
private void OnClicked(object sender, EventArgs e)
{
PBIndicator = !PBIndicator;
}
}
Let me know if it works. I hope it helps.
Try this one
private void OnClicked(object sender, EventArgs e)
{
if(PBIndicator==false){
activityIndicator.IsRunning=true;
}else{
activityIndicator.IsRunning=false;
}
}

How to handle list picker in Wp7

I have a list picker which is displayed in my phone application page.I have created list picker in starting of class,and i am adding the list picker in the phoneApplicationPage_loaded() method.When the page is launched the first time, ,the scenario works perfectly and its navigates further to second page.When i navigate back to previous page(containing list picker),it shows Invalid Operation Exception occured stating "Element is already the child of another element."
I want to know how to handle these scenarios?
Code is below
namespace My.Design
{
public partial class myclass : PhoneApplicationPage
{
String[] values = null;
ListPicker picker = new ListPicker();
StackPanel sp;
StackPanel mainFrame;
String statementInfo = "";
public myclass()
{
InitializeComponent();
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Phone Application Page Loaded_>>>>>>");
List<String> source = new List<String>();
displayUI();
}
public void displayUI()
{
Debug.WriteLine("About to display UI in miniStatement");
Debug.WriteLine("<-------------Data--------->");
Debug.WriteLine(statementInfo);
Debug.WriteLine("<-------------Data--------->");
int count = VisualTreeHelper.GetChildrenCount(this);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
UIElement child = (UIElement)VisualTreeHelper.GetChild(this, i);
string childTypeName = child.GetType().ToString();
Debug.WriteLine("Elements in this Child" + childTypeName);
}
}
List<String> source = new List<String>();
String[] allParams = ItemString.Split('#');
source.Add("PleaseSelect");
for (int i = 0; i < allParams.Length; i++)
{
Debug.WriteLine("All Params Length" + allParams[i]);
if (!(allParams[i].Equals("") && (!allParams[i].Equals(null))))
{
if (values != null)
{
Debug.WriteLine("Values length" + values.Length);
values[values.Length] = allParams[i];
}
else
{
Debug.WriteLine("Allparams Length" + allParams[i]);
source.Add(allParams[i]);
}
}
}
//picker = new ListPicker();
this.picker.ItemsSource = source;
mainFrame = new StackPanel();
TextBlock box = new TextBlock();
box.Text = "> DEmoClass";
box.FontSize = 40;
mainFrame.Children.Add(box);
Canvas canvas = new Canvas();
StackPanel sp = new StackPanel();
TextBlock box1 = new TextBlock();
box1.Text = "Number";
box1.HorizontalAlignment = HorizontalAlignment.Center;
box1.FontSize = 40;
SolidColorBrush scb1 = new SolidColorBrush(Colors.Black);
box1.Foreground = scb1;
sp.Children.Add(box1);
picker.Width = 400;
picker.Height = 150;
sp.Children.Add(picker);
Canvas.SetTop(sp, 150);
canvas.Children.Add(sp);
mainFrame.Children.Add(canvas);
this.ContentPanel1.Children.Add(mainFrame);
}
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
/*
Debug.WriteLine("OnNavigatingFrom>>>.>>MainPage");
if (sp != null)
{
sp.Children.Remove(picker);
}*/
base.OnNavigatingFrom(e);
}
}
}
If you are not intending to update the listpicker after navigating back from the second page add the following line in your Loaded event handler
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
this.Loaded -= PhoneApplicationPage_Loaded;
Debug.WriteLine("Phone Application Page Loaded_>>>>>>");
List<String> source = new List<String>();
displayUI();
}
i don't know why you can not use that case when app resume from tombstoned.
error happened because when you back to your page , loaded event runs again.
by the way,
Application_Activated 's argument can tell you app resumes from tombstoned or not--.
if (e.IsApplicationInstancePreserved)
{
IsTombstoning = false;
}
else
{
IsTombstoning = true;
}
I'm curious why you're creating it in code and not leaving it in XAML? Also the error is coming from the fact that you're attempting to add it twice into a location that can probably only have a single content element. What's the higher level problem you're trying to solve?

Is it possible to popup a sigin/up page(pivot) with appbar?

Is it possible to popup a sigin/up page(pivot) with appbar ? And is it possible auto fill the screen(has SystemTray or not)?
It is possible
To open a popup in your Mainpage, using (example popup when page loaded):
public MainPage()
{
InitializeComponent();
Loaded += (obj, args) =>
{
Popup popup = new Popup()
{
IsOpen = true
};
popup.Child = new PivotPage1(this.ActualWidth, this.ActualHeight, this, popup);
};
}
In your PivotPage, create addition constructor:
private PhoneApplicationPage parent = null;
private IApplicationBar parentAppBar = null;
private Popup popup = null;
public PivotPage1(double w, double h, PhoneApplicationPage p, Popup pop) : this()
{
Width = w;
Height = h;
parent = p;
popup = pop;
Loaded += (obj, args) =>
{
parentAppBar = parent.ApplicationBar;
parent.ApplicationBar = this.ApplicationBar;
};
Unloaded += (obj, args) =>
{
parent.ApplicationBar = parentAppBar;
};
}
private void menuItem3_Click(object sender, EventArgs e)
{
popup.IsOpen = false;
}

Resources