官术网_书友最值得收藏!

iOS text-to-speech implementation

Each module will retrieve the current container used throughout the entire lifetime of your application. Inside the register function is where we register the class implementation of the text to speech interface. This will be done at the very start of the application before we load anything else.

Let's start first with adding the iOS module. Add a new folder in the iOS project called Modules, create a new file called iOSModule.cs, and paste in the following:

     
    public class IOSModule : IModule 
    { 
        public void Register(ContainerBuilder builer) 
        { 
            builer.RegisterType<TextToSpeech> ().As<ITextToSpeech> ().SingleInstance (); 
        } 
    } 

The next step is to add the iOS text to speech service. Add a new folder called Services and add a new file called TextToSpeech.cs. In this file, we are going to access the iOS AVSpeechSynthesizer:

public class TextToSpeech : ITextToSpeech 
    { 
        public void Speak (string msg) 
        { 
            var speechSynthesizer = new AVSpeechSynthesizer (); 
 
            var speechUtterance = new AVSpeechUtterance (msg)  
            { 
                Rate = AVSpeechUtterance.MaximumSpeechRate / 4, 
                Voice = AVSpeechSynthesisVoice.FromLanguage ("en-US"), 
                Volume = 0.5f, 
                PitchMultiplier = 1.0f 
            }; 
 
            speechSynthesizer.SpeakUtterance (speechUtterance); 
        } 
    } 

Looking closely at this class, we are going to use the speech synthesizer to produce a SpeechUtterrance object, which contains the text to speak. We also set the language, volume, and speech rate.

Note

Notice how we inherit the interface we are going to register through the IoC container?

As we are coding this class on the native side, we are able to access all native iOS features, so back in the PCL when we call the function Speak in the interface, the preceding code will execute.

Our next step is to implement the view model principles for our pages. Create a new folder called ViewModels and add two new files, ViewModelBase.cs and MainPageViewModel.cs. The ViewModelBase class will be the base call for all view models for handling property change events with any view model's properties:

public abstract class ViewModelBase : INotifyPropertyChanged 
    { 
        #region Public Events 
 
        public event PropertyChangedEventHandler PropertyChanged; 
 
        #endregion  
 
        #region Methods 
 
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
        { 
            PropertyChangedEventHandler handler = this.PropertyChanged; 
 
            if (handler != null) 
            { 
                handler(this, new PropertyChangedEventArgs(propertyName)); 
            } 
        } 
 
        #endregion 
    } 

Let's look a bit closer. The first property defined is PropertyChanged EventHandler, which will fire on any property data change. Notice the use of the # define statements; these are useful for breaking up blocks of coding and navigating through your code sheets.

Note

These are particularly useful when we have big code sheets.

The class inherits the INotifyPropertyChanged interface, meaning we have to define the OnPropertyChanged function. This function is used to fire the PropertyChanged event to signal that a property within this class has changed data. Now let's implement the MainPageViewModel.

How do we use the OnPropertyChanged principle with our MainPageViewModel?

With each property in the MainPageViewModel, we have to call the OnPropertyChanged function to fire the EventHandler, thus notifying of a data change for a particular property. Let's begin by creating the MainPageViewModel with its private properties and constructor:

public class MainPageViewModel : ViewModelBase 
    { 
        #region Private Properties 
 
        private readonly ITextToSpeech _textToSpeech; 
 
        private string _descriptionMessage = "Enter text and press the 'Speak' button to start speaking"; 
 
        private string _speakEntryPlaceholder = "Text to speak"; 
 
        private string _speakText = string.Empty; 
 
        private string _speakTitle = "Speak"; 
 
        private ICommand _speakCommand; 
 
        #endregion 
 
        #region Constructors 
 
        public MainPageViewModel (ITextToSpeech textToSpeech)  
        { 
           _textToSpeech = textToSpeech; 
 
            _speakCommand = new Command ((c) => _textToSpeech.Speak (this.SpeakText)); 
        }  
 
        #endregion 
    } 

This is the first time we are going to access the Systems.Windows.Input library. Commands are used for our Button object on the ContentPage; we will set up a binding on the button so whenever a press event occurs, this command will execute, running the action it is assigned in the constructor. Notice how we are passing the TextToSpeech interface; this is where things will get trickier with the IoC container.

Now we add the public properties of the view model, which call the OnPropertyChanged function:

#region Public Properties 
 
        public string DescriptionMessage 
        { 
            get 
            { 
                return _descriptionMessage; 
            } 
 
            set 
            { 
                if (value.Equals(_descriptionMessage)) 
                { 
                    return; 
                } 
 
                _descriptionMessage = value; 
                OnPropertyChanged("DescriptionMessage"); 
            } 
        } 
 
        public string SpeakEntryPlaceholder 
        { 
            get 
            { 
                return _speakEntryPlaceholder; 
            } 
 
            set 
            { 
                if (value.Equals(_speakEntryPlaceholder)) 
                { 
                    return; 
                } 
 
                _speakEntryPlaceholder = value; 
                OnPropertyChanged("SpeakEntryPlaceholder"); 
            } 
        } 
 
        public string SpeakText 
        { 
            get 
            { 
                return _speakText; 
            } 
 
            set 
            { 
                if (value.Equals(_speakText)) 
                { 
                    return; 
                } 
 
                _speakText = value; 
                OnPropertyChanged("SpeakText"); 
            } 
        } 
 
        public string SpeakTitle 
        { 
            get 
            { 
                return _speakTitle; 
            } 
 
            set 
            { 
                if (value.Equals(_speakTitle)) 
                { 
                    return; 
                } 
 
                _speakTitle = value; 
                OnPropertyChanged("SpeakTitle"); 
            } 
        } 
 
        public ICommand SpeakCommand 
        { 
            get 
            { 
                return _speakCommand; 
            } 
 
            set 
            { 
                if (value.Equals(_speakCommand)) 
                { 
                    return; 
                } 
 
                _speakCommand = value; 
                OnPropertyChanged("SpeakCommand"); 
            } 
        } 
 
        #endregion 

That's it! We have our first view model. Notice the get and set methods for each property; they are exactly the same as functions, just with a nicer presentation. Every time we retrieve the data inside a public property, it will pull the data contained in the private property, and every time we set the public property, if the value is different to the current value, we will set the private variable contained and call the OnPropertyChanged function to fire the EventHandler in the base class. When this event fires, it will update whatever view is bound to it.

主站蜘蛛池模板: 海淀区| 南开区| 高淳县| 于田县| 青海省| 潜江市| 徐汇区| 阿瓦提县| 新竹市| 左贡县| 连江县| 广南县| 富锦市| 潜山县| 南江县| 手机| 松溪县| 且末县| 安图县| 枝江市| 康乐县| 嘉善县| 阿坝县| 合作市| 固原市| 泊头市| 海口市| 奇台县| 嘉黎县| 门头沟区| 介休市| 佛教| 巴里| 佳木斯市| 上思县| 磐安县| 鄯善县| 赤壁市| 鄂伦春自治旗| 洞口县| 嘉鱼县|