How to play text to speech using xamarin.essential - forms

I want to play text to speech but I can't hear anything using Xamarin.essential. I 'm sure I don't have muted smartphone. The code:
using Xamarin.Essential
private void PlayTextMethod()
{
if(do sth)
{
SpeekFrommethodAsync();
}
}
private async SpeekFrommethodAsync()
{
await TextToSpeech.SpeakAsync(Tasklabel.Text, new SpeechOptions
{
Volume = 1f
});
}

If your project's Target Android version is set to Android 11 (R API 30),
Open the AndroidManifest.xml file under the Properties folder and add the following inside of the manifest node:
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
And try this in your method:
public async Task SpeakNow()
{
var locales = await TextToSpeech.GetLocalesAsync();
// Grab the first locale
var locale = locales.FirstOrDefault();
var settings = new SpeechOptions()
{
Volume = .75f,
Pitch = 1.0f,
Locale = locale
};
await TextToSpeech.SpeakAsync("Hello World", settings);
}
Refer: https://learn.microsoft.com/en-us/xamarin/essentials/text-to-speech?context=xamarin%2Fandroid&tabs=android

I made a demo and I tested it on the Android 12 emulator. I found the Text-to-speech function can not speak the words which belong to another country. So I added a picker to choose the country.
Here is the code in MainPage.xaml
<StackLayout>
<Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
<Label Text="Text to speech sample!" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
</Frame>
<Picker x:Name="Languages"></Picker>
<Entry x:Name="TextToSpeak"></Entry>
<Button Text="Speak Please" Clicked="Button_Clicked"></Button>
</StackLayout>
And here is the code in MainPage.xaml.cs.
using Xamarin.Essentials;
public partial class MainPage : ContentPage
{
IEnumerable<Locale> locales;
public MainPage()
{
InitializeComponent();
}
protected async override void OnAppearing()
{
base.OnAppearing();
locales = await TextToSpeech.GetLocalesAsync();
// add the locales to the picker
foreach(var locale in locales)
{
Languages.Items.Add(locale.Name);
}
}
// realize the button
private void Button_Clicked(object sender, EventArgs e)
{
if(Languages.SelectedIndex > 0)
{
// use the TextToSpeech to read the words in the Entry.
TextToSpeech.SpeakAsync(TextToSpeak.Text, new SpeechOptions
{
Locale = locales.Single(locales=> locales.Name == Languages.SelectedItem.ToString())
});
}
}
}
This is the view of the project.

Related

How to share information between pages

Before starting, as is stated in the title, I'm learning .NET MAUI and I'm very new in this.
My problem is that I can't find a way to share information from a page to a previous page.
What I'm trying to do is the following:
In the MainPage, have a button that once pressed, sends the user to another page, let's call it LoginPage, there, ask the user for his name, and after the input, redirect him to the previous page showing an "Hello {Name}, and welcome!"
MainPage code:
string Name = "";
string greetings = "";
async private void LogintBtn_Clicked(object sender, EventArgs e)
{
{
await Navigation.PushAsync(new LoginPage());
}
greetings = $"Welcome {Name}!";
Greetinglbl.Text = greetings;
}
Log in code:
public string name { get; set; }
private void btnRegister_Clicked(object sender, EventArgs e)
{
if (ValidateName()==false) { return; };
Navigation.PopAsync();
}
private bool ValidateName()
{
if (string.IsNullOrWhiteSpace(txtRegistro.Text))
{
return false;
}
else
return true;
}
Beside this, I don't know how to share information between these pages.
I have seen that a lot of devs use MVVM but I can't get a Beginners guide propperly, even watching the .NET MAUI Beginners Guides from James Montemagno doesn't help me.
I've also tried using something like
await Shell.Current.GoToAsync($"LoginPage?Name={Name}");
that, for what I read is used to send data but don't know where to put it, plus triying to navigate with the same line throws an error (null).
Plus, most of the videos only shows how to send Data to the next Page, not the previous, and usually to a collection, and some of them import NuGet Packages that I don't see to be necessary in this project.
In your scenario, you could share the data through Constructor, here's the code snippet below for your reference.
MainPage:
Xaml:
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Label Text="MainPage"></Label>
<Button
Text="To Login Page"
Clicked="OnClicked"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ScrollView>
Code-behind:
      public MainPage()
      {
            InitializeComponent();
      }
public MainPage(string a)
{
InitializeComponent();
      
            App.Current.MainPage.DisplayAlert("Welcome Back",a,"OK");
}
private async void OnClicked(object sender, EventArgs e)
      {
            await Navigation.PushAsync(new LoginPage());
      }
LoginPage:
Xaml:
<VerticalStackLayout>
<Label Text="LoginPage"></Label>
<Entry x:Name="myentry"/>
<Button
Text="ToMain"
Clicked="BackTo"
HorizontalOptions="Center" />
</VerticalStackLayout>
Code-behind:
public LoginPage()
      {
            InitializeComponent();
      }
private async void BackTo(object sender, EventArgs e)
{
await Navigation.PushModalAsync(new MainPage(myentry.Text));
}
Last but not least, in your App.xaml.cs, use it like below:
MainPage = new NaviagtionPage(new MainPage())

Xamarin Forms with Prism - Problem with using WebService

Can anyone help me? I created simply project Xamarin Forms with Prism i VS2017 on Android (screen). I used Prism Template Pack. I would like connect project with my WebService. here is a link to screen of all project
I have two projects PrismCoursApp and PrismCoursApp.Droid. First project contains SecondPageViewModel.cs where I try use connected WebService (wsMES) but I can't add namespace with PrismCoursApp.Droid.
The namespace of project PrismCourseApp.Android is PrismCourseApp.Droid and
PrismCourseApp.Android depends on PrismCourseApp.
I could add reference to Web service only in PrismCoursApp.Android project but I would like to use it in SecondPageViewModel.cs in PrismCourseApp.
Can someone tell me what I'm doing wrong?
Thanks
SecondPageViewModel.cs
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using PrismCourseApp.Models;
using System.Collections.ObjectModel;
namespace PrismCourseApp.ViewModels
{
public class SecondPageViewModel : BindableBase, INavigationAware
{
//zmienna do WebService
//wsMES.WSwitoMES ws = new wsMES.WSwitoMES();
private string _title;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private string _UserCode;
public string UserCode
{
get { return _UserCode; }
set { SetProperty(ref _UserCode, value); }
}
private string _LokalizCode;
public string LokalizCode
{
get { return _LokalizCode; }
set { SetProperty(ref _LokalizCode, value); }
}
public SecondPageViewModel()
{
UserCode = AppStateTest.User;
LokalizCode = AppStateTest.CurrentCode;
Title = "Użytkownik/Lokalizacja";
}
public void OnNavigatedFrom(INavigationParameters parameters)
{
}
public void OnNavigatedTo(INavigationParameters parameters)
{
if (parameters.ContainsKey("par1"))
{
string par1 = (string)parameters["par1"];
string par2 = (string)parameters["par2"];
}
}
public void OnNavigatingTo(INavigationParameters parameters)
{
}
}
}
SecondPage.axml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="PrismCourseApp.Views.SecondPage"
BackgroundColor="White"
Title="{Binding Title}"
xmlns:b="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
xmlns:c="clr-namespace:PrismCourseApp.Converters;assembly=PrismCourseApp">
<ContentPage.Resources>
<ResourceDictionary>
<!--<c:ItemTappedEventArgsConverter x:Key="itemTappedEventArgsConverter" />-->
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout
Spacing="20">
<Label
Text="Zalogowany użytkownik:"
TextColor="Gray"/>
<Label
Text="{Binding UserCode}"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Label
Text="Lokalizacja:"
TextColor="Gray"/>
<Label
Text="{Binding LokalizCode}"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<ListView
x:Name="lstView">
<!--ItemsSource="{Binding MyDatas}">-->
<!--<ListView.Behaviors>
<b:EventToCommandBehavior EventName="ItemTapped"
Command="{Binding ItemTappedCommand}"
EventArgsConverter="{StaticResource itemTappedEventArgsConverter}" />
</ListView.Behaviors>-->
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding name}" Detail="{Binding comment}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
SecondPage.axml.cs
using Xamarin.Forms;
using PrismCourseApp.Models;
using System.Collections.ObjectModel;
namespace PrismCourseApp.Views
{
public partial class SecondPage : ContentPage
{
//Elementy do ListView (klasa MyDate w PrismCourseApp)
private ObservableCollection<MyDate> MyDatas { get; set; }
public SecondPage()
{
InitializeComponent();
MyDatas = new ObservableCollection<MyDate>();
lstView.ItemsSource = MyDatas;
for (int i = 0; i < 30; i++)
{
MyDatas.Add(new MyDate
{
name = "Pozycja " + (i+1).ToString(),
comment = "Miejsce na szczegóły " + (i+1).ToString()
});
}
}
}
}
MainActivity.cs in Android Project
using Android.App;
using Android.Content.PM;
using Android.OS;
using Prism;
using Prism.Ioc;
namespace PrismCourseApp.Droid
{
[Activity(Label = "PrismCourseApp", Icon = "#drawable/ic_launcher", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App(new AndroidInitializer()));
}
}
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IContainerRegistry container)
{
// Register any platform specific implementations
}
}
}
Summarising the discussion in the comments above:
One should not make a web service dependent upon something specific to one of many client platforms. It's preferable to put the service's interface between the server and the part of the client that's shared between the different client implementations.
Say you have a mobile app for Android and IOS. Then you'll have two projects MyApp.Droid and MyApp.IOS for the respective client-specific implementations. Also, there's a project that both of them reference, and that (hopefully) contains most of your app's client-side logic: MyApp.Logic.
Now for the server: you have the MyApp.Server project that implements the service. If you need to define interfaces to communicate between the app and the service (WCF comes to mind), you define a project referenced by both the client-side logic (MyApp.Logic) and the server implementation (MyApp.Server): MyApp.Interface.
MyApp.Droid & MyApp.IOS -ref-> MyApp.Logic -ref-> MyApp.Interface <-ref- MyApp.Server

Bind Plugin.Media fromViewModel

I have a view model that handles the Plugin.Media to take a picture from the phone. The image will not show unless I have the code below (View Model) in the code-behind, then it works fine, which is defeating the object of me learning MVVM. I have also tried 'FileImageSource' and used 'Source' in its various ways.'
Can anyone explain what I am doing wrong?
View Model:
public string FilePath { get => _filepath; set { _filepath = value; OnPropertyChanged(); } }
private string _filepath;
public Command CaptureImage
{
get
{
return new Command(TakePicture);
}
}
//
private async void TakePicture()
{
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
//say something
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "FoodSnap",
Name = GetTimestamp(DateTime.Now),
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Custom,
CustomPhotoSize = 50
});
if (file == null)
return;
FilePath = file.Path;
}
XAML:
<pages:PopupPage
xmlns:pages="clr-
namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:TacticalFitness.ViewModels"
x:Class="TacticalFitness.Views.PopUps.AddFoodSnapPopUp">
<BindableObject.BindingContext>
<vm:AddSnapViewModel/>
</BindableObject.BindingContext>
<StackLayout>
<Image Source="{Binding FilePath}" HeightRequest="150" BackgroundColor="LightGray" >
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding CaptureImage}"
NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
</pages:PopupPage>
If you want to use this from your view model, assign an instance of the view model to the BindingContext of your page, so that is the only line in your code-behind basically.
public YourPage()
{
InitializeComponent();
BindingContext = new YourViewModel();
}
Now it should work.
Update
From your XAML I see:
<Image.Source>
<StreamImageSource Stream="{Binding NewImage}"/>
</Image.Source>
Where Stream is a type of Stream but you are assigning an ImageSource to it. You can simply do this: <Image HeightRequest="150" BackgroundColor="LightGray" Source="{Binding NewImage}">

Xamarin Android Facebook share button disabled

Hope You're all ok.
I have a simple xamarin android application, and trying to integrate facebook share button in it.
I've done all by docs, and other tutorials. App is registered in Facebook.
But the button is showing gray in app, it's disabled.
I don't know what's the problem.
Testing it in Nexus 5, with Android M 6.0.1.
Thanks.
Little update on what I've done so far.
Manifest File
Manifest File
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="#string/app_id" />
<activity android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
android:label="#string/ApplicationName" />
<provider android:authorities="com.facebook.app.FacebookContentProvider266540057101076" android:name="com.facebook.FacebookContentProvider" android:exported="true" />
Activity file code snippet
<com.facebook.share.widget.ShareButton
android:id="#+id/fShareButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal" />
And finally controller.
private ShareButton fShareButton;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
getKeyHashes();
FacebookSdk.SdkInitialize(ApplicationContext);
SetContentView(Resource.Layout.details);
fShareButton = FindViewById<ShareButton>(Resource.Id.fShareButton);
fShareButton.Click += FShareButton_Click;
..........
}
private void FShareButton_Click(object sender, EventArgs e)
{
#region Facebook Share Button
View v1 = Window.DecorView.RootView;
v1.DrawingCacheEnabled = true;
Android.Graphics.Bitmap bitmap = Android.Graphics.Bitmap.CreateBitmap(v1.GetDrawingCache(true));
var photoBuilder = new SharePhoto.Builder();
photoBuilder.SetBitmap(bitmap);
var photo = photoBuilder.Build().JavaCast<SharePhoto>();
var photos = new List<SharePhoto>();
photos.Add(photo);
SharePhotoContent photoContent = new SharePhotoContent.Builder().SetPhotos(photos).Build();
fShareButton.ShareContent = photoContent;
#endregion
}
You must set callbackManager and fill ShareContent property in ShareButton, in my example I use ShareLinkContent for the content, but there are other options like "ShareMediaContent", "SharePhotContent", etc., you can get more explanaition about this in https://developers.facebook.com/docs/sharing/android/?locale=en_US :
fShareButton = FindViewById<ShareButton>(Resource.Id.fShareButton);
callbackManager = CallbackManagerFactory.Create();
fShareButton.RegisterCallback(callbackManager, this);
var content = new ShareLinkContent.Builder();
content.SetContentUrl(Android.Net.Uri.Parse("https://www.mivinco.com/linkapp_an9.html"));
var hashtag = new ShareHashtag.Builder();
hashtag.SetHashtag("#porqueTuExperienciaCuenta");
content.SetShareHashtag((ShareHashtag)hashtag.Build());
fShareButton.ShareContent = content.Build();
Also, you should implement IFacebookCallback interface in your activity:
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
callbackManager.OnActivityResult(requestCode, (int)resultCode, data);
}
It works fine in my Android app. Let me know if it works fine in your app too.

Xamarin Forms - Customize FontFamily, FontSize of a DatePicker

I searched about how to change the fontsize/fontfamily of a DatePicker such as an Entry, but I couldn't find anything, any ideas?
Thank !
You could do it via custom renderer:
For example, I will use renderer for iOS. Control will be native element for each platform. And you could change it in native way.
[assembly: ExportRenderer(typeof(DatePicker), typeof(CustomDatePickerRenderer))]
namespace SuperForms.Samples.iOS
{
public class CustomDatePickerRenderer : DatePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
//Control is UITextField
var someFontWithName = UIFont.FromName("fontName", 14);
UIFont font = Control.Font.WithSize(14);
Control.Font = font;
}
}
}
UPDATE
For Android:
[assembly: ExportRenderer(typeof(DatePicker), typeof(CustomDatePickerRenderer))]
namespace SuperForms.Samples.Droid
{
public class CustomDatePickerRenderer : DatePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
// Control is Android.Widget.EditText
Control.Typeface = Android.Graphics.Typeface.CreateFromAsset(Forms.Context.Assets, "Path/To/YourFont.otf");
Control.TextSize = 14;
}
}
}
**Xamarin Forms** => This is for **Android**, using **custom renderer** we can change the font size of datepicker.
[assembly: ExportRenderer(typeof(DatePicker), typeof(CustomDatePickerRenderer))]
namespace Samples.Droid
{
public class CustomDatePickerRenderer : DatePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.DatePicker> e)
{
base.OnElementChanged(e);
**Control.TextSize = 12;**
}
}
}
Thank you
I dont know if you require answer now, still i am attaching the code which solves the font size problem of date picker without using custom rendering..
Create MainPage.Xaml file
<DatePicker x:Name="PickerDate" MinimumDate="05-24-2017" Format="mm-dd-yyyy" MaximumDate="12-31-2050" IsVisible="False" DateSelected="PickerDate_DateSelected"/>
<Label x:Name="DateLabel" Text="Tap to Select Date" FontSize="14" HorizontalOptions="Start">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_1"/>
</Label.GestureRecognizers>
</Label>
create MainPage.Xaml.cs File
private void TapGestureRecognizer_Tapped_1(object sender, EventArgs e)
{
PickerDate.Focus();
}
private void PickerDate_DateSelected(object sender, DateChangedEventArgs e)
{
DateLabel.Text = PickerDate.Date.Date.ToString("MM-dd-yyyy");
}
This solves problem in Android and IOS.