Problems with Xamarin Essentials - xamarin

Im now working on my third beginner program in xamarin forms and want to programm an accelerometer
We know that the API Xamarin Essentials is doing the job with the calculation and all but when i insert something like Accelerometer.IsMonitoring it doesnt know about the IsMonitoring even it has to know about it what im doing wrong here is an eventhandler i defined in the xaml data and it doesnt recognize IsMonitoring and Start and gives me the error: the type or namespace name 'Start' doesnt exist in the namespace:Accelerometer
Here is the code:
private void ButtonStart_Clicked(object sender, EventArgs e)
{
if (Accelerometer.IsMonitoring)
return;
Accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
Accelerometer.Start(SensorSpeed.UI);
}
And this is the xaml code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.ColumnSpan="2" x:Name="LabelX"/>
<Label Grid.Row="1" Grid.ColumnSpan="2" x:Name="LabelY"/>
<Label Grid.Row="2" Grid.ColumnSpan="2" x:Name="LabelZ"/>
<Button Grid.Row="3" Grid.ColumnSpan="0" x:Name="ButtonStart" Text="Start" Clicked="ButtonStart_Clicked"/>
<Button Grid.Row="3" Grid.ColumnSpan="1" x:Name="ButtonStop" Text="Stop" Clicked="ButtonStop_Clicked"/>
</Grid>
What im doing wrong or what is missing

because your project is named Accelerometer it cannot differentiate between your main App namespace and the Xamarin.Essentials Accelerometer class
You can fix this by renaming your project, or creating an alias for Xamarin Essentials, or fully qualifying the classname like this
private void ButtonStart_Clicked(object sender, EventArgs e)
{
if (Xamarin.Essentials.Accelerometer.IsMonitoring) return;
Xamarin.Essentials.Accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
Xamarin.Essentials.Accelerometer.Start(SensorSpeed.UI);
}

Related

FindByName control inside another control on ContentPage in Xamarin

I want to set focus on SearchBar when he appears. The problem is that SearchBar is placed inside of popup view and I need to access him from ViewModel.
In standard way I would use
Xamarin.Forms.SearchBar tmp_SearchBar = this.Page.FindByName("fro_SearchBar_NewItem") as Xamarin.Forms.SearchBar;
but that's not working anymore.
Here is XAML
<sfPopup:SfPopupLayout x:Name="fro_Popup_NewItem" Opened="fro_Popup_NewItem_Opened" Grid.Row="1" HorizontalOptions="Center" VerticalOptions="Center" BackgroundColor="Black">
<sfPopup:SfPopupLayout.PopupView>
<sfPopup:PopupView BackgroundColor="Black" WidthRequest ="400" HeightRequest ="100" ShowFooter="False" ShowHeader="False">
<sfPopup:PopupView.ContentTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!--Search bar-->
<Grid Grid.Row="0" HorizontalOptions="Center" VerticalOptions="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<SearchBar x:Name="fro_SearchBar_NewItem"
Grid.Column="0"
Text="{Binding SearchText_Popup, Mode=TwoWay}"
SearchCommand="{Binding SearchCommand}"
Placeholder="Find"
CancelButtonColor="White"
TextColor="White"
PlaceholderColor="Gray"/>
</Grid>
</Grid>
</DataTemplate>
</sfPopup:PopupView.ContentTemplate>
</sfPopup:PopupView>
</sfPopup:SfPopupLayout.PopupView>
</sfPopup:SfPopupLayout>
Nested FindByName doesn't work either.
Syncfusion.XForms.PopupLayout.SfPopupLayout tmp_Popup = _Page.FindByName("fro_Popup_NewItem") as Syncfusion.XForms.PopupLayout.SfPopupLayout;
Xamarin.Forms.SearchBar tmp_SearchBar = tmp_Popup.FindByName("fro_SearchBar_NewItem") as Xamarin.Forms.SearchBar;
Thanks
You can use Task to open a new thread to complete this operation in code-behind.
Xaml:
<SearchBar x:Name="fro_SearchBar_NewItem" Placeholder="...." BackgroundColor="White"/>
Code behind:
public partial class PagePop : Popup
{
public PagePop()
{
InitializeComponent();
Task.Run(() => myTask());//Create and start the thread
}
private void myTask()
{
Thread.Sleep(300);
fro_SearchBar_NewItem.Focus();
}
}
It seems that this wasn't so far from right direction, neither of the comments actually.
Syncfusion.XForms.PopupLayout.SfPopupLayout tmp_Popup = _Page.FindByName("fro_Popup_NewItem") as Syncfusion.XForms.PopupLayout.SfPopupLayout;
Xamarin.Forms.SearchBar tmp_SearchBar = tmp_Popup.FindByName("fro_SearchBar_NewItem") as Xamarin.Forms.SearchBar;
but I found the one which works and I don't have to create separate XAML for Popup.
private void fro_Popup_NewItem_Opened(object sender, EventArgs e)
{
try
{
var nativeObject = (object)fro_Popup_NewItem.GetType().GetRuntimeProperties().FirstOrDefault(x => x.Name.Equals("NativeObject")).GetValue(fro_Popup_NewItem);
var formsPopupviewContentTemplate = nativeObject.GetType().GetRuntimeFields().FirstOrDefault(x => x.Name.Equals("formsPopupViewContentTemplate")).GetValue(nativeObject);
var SearchBar = (formsPopupviewContentTemplate as Grid).FindByName<SearchBar>("fro_SearchBar_NewItem");
SearchBar?.Focus();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Thanks for help, everyone.

How to set the Position of a MediaElement upon button click?

I'm working on a Xamarin Forms application. Right now I'm trying to implement custom video controls into my MediaElement but I'm failing to do so, and googling isn't helping much.
Basic overview, I have a MediaElement playing a video, and I have two buttons on each side of the video that I would like the user to be able to press and rewind or fast forward 5 seconds. The buttons recognize being clicked, but do not do what I want them to, and I'm not sure what I am doing wrong. Here is my code:
Page.xaml
...
<Grid BackgroundColor="#E5EBEE">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<MediaElement x:Name="LessonVideo"
Source="ms-appx:///vid_IntroDemo.mp4"
ShowsPlaybackControls="False"
IsLooping="True"
Aspect="AspectFill"
AutoPlay="True"
KeepScreenOn="True"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Grid.ColumnSpan="3"
/>
<BoxView Opacity="0.0" BackgroundColor="#00C2FF"/>
<Button x:Name="Back" BackgroundColor="Yellow" Grid.Column="0" Opacity="0.2" Clicked="RewindVideo"></Button>
<Button x:Name="Forward" BackgroundColor="Red" Grid.Column="2" Opacity="0.2"></Button>
</Grid>
Page.xaml.cs
...
private void RewindVideo(object sender, EventArgs e)
{
if (LessonVideo.CanSeek)
{
LessonVideo.Position = TimeSpan.FromSeconds(LessonVideo.Position.TotalSeconds - 5);
}
}
I've experimented with stopping and playing the video, but nothing seems to be working. Help me out and point me in the right direction how to solve this. Thank you in advance.

Virtual keyboard not working properly for Entry in TableView - [Android]

Description
I am using Entry in TableView and displaying the formatted value in focus. In this case virtual keyboard not showing while change focus within Entry.
Steps to Reproduce
Run the sample
Focus the 1st Entry
Focus 2nd Entry
Unfocus both views
Focus 2st Entry. See the keyboard not showing.
Sometimes while unfocus both Entry, keyboard not getting collapsed.
Basic Information
Version with issue: 4.8.0.1451
Platform Target Frameworks:
Android: Nexus 6 Marshmallow 6.0 - API 23 emulator.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EntryWithTableView.MainPage">
<TableView>
<TableRoot>
<TableSection >
<ViewCell >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Entry Keyboard="Numeric" Focused="entry1_Focused" Unfocused="entry1_Unfocused"
x:Name="entry1" Grid.Column="1" WidthRequest="100"/>
<Entry Keyboard="Numeric" Focused="entry1_Focused" Unfocused="entry1_Unfocused"
Grid.Column="2" x:Name="entry2" WidthRequest="100"/>
</Grid>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>
</ContentPage>
[C#]:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
double value = 5;
private void entry1_Focused(object sender, FocusEventArgs e)
{
Entry entry = sender as Entry;
if(entry != null)
{
entry.Text = value.ToString();
}
}
private void entry1_Unfocused(object sender, FocusEventArgs e)
{
Entry entry = sender as Entry;
if (entry != null)
{
entry.Text = value.ToString("F");
}
}
}
It caused by the TableView . You could use Grid as the root layout directly .
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Entry Keyboard="Numeric" Focused="entry1_Focused" Unfocused="entry1_Unfocused"
x:Name="entry1" Grid.Column="1" WidthRequest="100" />
<Entry Keyboard="Numeric" Focused="entry1_Focused" Unfocused="entry1_Unfocused"
Grid.Column="2" x:Name="entry2" WidthRequest="100"/>
</Grid>
If you want to display a collection , you could use ListView .

Completed Event on a custom Entry

I have two entries, one for username and the other for password.
<customEntry:EmailEntry Placeholder="Your email address" x:Name="Email" Keyboard="Email" WidthRequest="50" Text="{Binding UserName}"/>
<customEntry:PwdEntry Placeholder="Your password" x:Name="Password" IsPassword="true" Text="{Binding Password}"/>
The two entries (EmailEntry and PwdEntry) are of type ContentView not ContentPage. I am trying to get the Completed event on the EmailEntry but couldn't. Once the user hits the "Next" button on the keyboard, the focus should shift to PwdEntry.
If these were normal entries, I know that I can use,
Email.Completed += (object sender, EventArgs e) => Password.Focus();
As the two entries are ContentViews, I cannot change the focus to next entry as soon as the user hits "Next".
This is my CustomEntry...
<?xml version="1.0" encoding="UTF-8"?><ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Ecommerce.Mobile.Core.EmailEntry"
xmlns:local="clr-namespace:Ecommerce.Mobile.Core.CustomViews"
xmlns:fr="clr-namespace:Ecommerce.Mobile.Core.Controls">
<ContentView.Content>
<fr:MyFrame CornerRadius="5"
OutlineColor="{StaticResource MocoWhite}"
BackgroundColor="Blue"
HasShadow="false" Padding="15,0">
<Grid ColumnSpacing="16">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="1"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Padding="0,10,0,0" HeightRequest="30" WidthRequest="20">
<Image Source="icons_envelope_white1x.png" HorizontalOptions="Start" />
</Grid>
<Grid Grid.Column="1" HeightRequest="65" WidthRequest="20">
<Label x:Name="HiddenLabel" Font="ProximaNovaRegular" FontSize="12" IsVisible="False" Margin="0" FontAttributes="Bold"/>
<fr:MyKeyboardEntry x:Name="EntryField" FontSize="15" TextColor="White" Keyboard="Email" ReturnType="Next" Text="{Binding Text, Mode=TwoWay}" PlaceholderColor="White" Margin="0,12,0,0"/>
</Grid>
</Grid>
</fr:MyFrame>
</ContentView.Content>
How can I achieve this?
As I could see you have a lot of nested components wrapped in your own class (a ViewCell in this case).
I bet eventually you'll have a base component, that provides the events you want to expose in your top-level component.
Let's take the Completed event, for example. Supposing you have the bellow structure:
- EmailEntry _inherites from_
└ MyKeyboardEntry _inherites from_
└ ...
└ Entry (provides the `Completed` event)
So you can subscribe and expose the event on each wrapper:
public class MyKeyboardEntry : View
{
...
// Expose the event
public event EventHandler<TextChangedEventArgs> TextChanged;
...
// Subscribe the original one with your own handler
public MyKeyboardEntry()
{
...
// Its your wrapped Entry object
entry.TextChanged += OnTextChanged;
...
}
...
// Implementing the #EvZ suggestion
public void TakeFocus()
{
entry.Focus();
}
...
// Finally, throw up your event notification
protected virtual void OnTextChanged(object sender, TextChangedEventArgs args)
{
... // Handle something if you need
TextChanged?.Invoke(this, args); // invoking the event this class owns using the C# 6 syntax
/*
// Using the C# <6
var hdlr = TextChanged;
if(hdlr != null)
hdlr.Invoke(this, args);
*/
}
...
}
Now you're able to handle the MyKeyboardEntry.TextChanged event outside the class.
You have to do this to each specific class that wraps another more generic (EmailEntry and so on).
I hope it helps.

Partial text clickable in Xamarin Label

I am looking for a way to make parts of the text of a Label in Xamarin Forms clickable, performing different functions, and ideally have different formatting. I understand that a clickable Label is straightforward and can be done something like this:
Label label = new Label { Text = "Click me" };
label.Click += () => { label.Text = "Clicked"; };
Essentially, I'm looking to mimic behavior in an app that I've done in native Android. My app must work for Android and iOS and ideally UWP. In Android, CharSequence objects can be added to a TextView (the control similar to Label). In Android, I might create a CharSequence object like this:
Runnable doSomething; //equivalent to C# Action; assuming initialized somewhere
String myString = "My Clickable String"; //the clickable string
Spannable span = Spannable.Factory.getInstance().newSpannable(myString); //this is the clickable text to add to TextView
span.setSpan(new ClickableSpan() {
#Override
public void onClick(View v) {
doSomething.run(); //perform the action
}
#Override
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(true); //make underlined
ds.setColor(Color.rgb(color.r, color.g, color.b)); //change the color
ds.setFakeBoldText(true); //make it bold
ds.setTextSize((float) largeFont); //change the text size
}
}, 0, a.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //style and function for the entire string
As you can see, it performs a function and has style attributes. I can then add this to TextView (Spannable implements Spanned which implements CharSequence). I can add multiple CharSequences in addition to non-clickable Strings as I desire.
I'm hoping for a way that I can do this in Xamarin but I haven't found a solution yet. I've considered the possibility of custom renderers though I feel that a cross-platform solution would be preferable, if possible. I'm far less familiar with iOS but it seems that it's possible to add NSMutableAttributedString objects to a UILabel to similar effect. I've also seen the FancyLabel object. I'm not quite sure how I would do this for UWP as I really didn't find much in my research.
Any assistance would be very appreciated!
Just to provide an updated answer to this using Xamarin Forms 3.4 (and over). You can use the FormattedText property of the Label. There is an in-depth overview on how to use it over in the Xamarin Docs.
Fundamentally, it works like so:
<Label
LineBreakMode="WordWrap">
<Label.FormattedText>
<FormattedString>
<Span
Text="Red Bold, "
TextColor="Red"
FontAttributes="Bold" />
<Span
Text="default, "
Style="{DynamicResource BodyStyle}">
<Span.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}" />
</Span.GestureRecognizers>
</Span>
<Span
Text="italic small."
FontAttributes="Italic"
FontSize="Small" />
</FormattedString>
</Label.FormattedText>
</Label>
In the above, tapping on the text default will execute TapCommand.
This answer may be extremely after-the-fact but may help others in the future.
What I've done and tested is to use a grid with your string split up appropriately, say you want to change the behaviour of a word:
In your ViewModel/View:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> //for first few words
<ColumnDefinition Width="Auto"/> //the target word
<ColumnDefinition Width="Auto"/> //the rest of the string
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/> //one row for one line of text
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Text="First part of string"/>
<Label Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="0" Text="TARGET-WORD">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding <YOUR_COMMAND>}"/>
</Label.GestureRecognizers>
</Label>
<Label Grid.Column="2" Grid.ColumnSpan="1" Grid.Row="0" Text="rest of the string"/>
</Grid>
This way you can isolate specific portions of grid and amend behaviour/aethetics (data triggers, styling, gestures). Remember that <Span></Span> tags do not support all the features of a <Label></Label>.
Clearly, in XAML you would need to know the position of the word, or if the string is dynamic, you could dynamically search for it and also construct your Grid in the code behind.
*Tested on Xamarin.Forms 2.3.4.247
Considering an example to answer this question which may help somebody in future,
Eg. i need to write "By signing up, you agree to the Terms of Services and Privacy Policy" with some formatting:
Terms of Services with different color and can be tapped
Privacy Policy with different color and can be tapped
Rest part of the string should be simple.
Code in XAML:
`<Label Text="By signing up, you agree to the " Grid.Row="0"/>
<Label Text="Terms of Services" TextColor="DarkOrange" WidthRequest="150"
HorizontalOptions="End" Grid.Row="0">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_Terms"/>
</Label.GestureRecognizers>
</Label>
<Label Text=" and " HorizontalOptions="End" Grid.Row="0" />
<Label Text="Privacy Policy" TextColor="DarkOrange" HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" Grid.Row="0">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_Policy"/>
</Label.GestureRecognizers>
</Label>
`
Code in C# for tapped callbacks:
private void TapGestureRecognizer_Tapped_Terms(object sender, EventArgs e)
{
Navigation.PushAsync(new TermsofServicesPage());
}
private void TapGestureRecognizer_Tapped_Policy(object sender, EventArgs e)
{
Navigation.PushAsync(new PrivacyPolicyPage());
}
Different formattings of the string can be performed and works fine for cross platforms.

Resources