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

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.

主站蜘蛛池模板: 宿松县| 赤峰市| 房产| 新兴县| 乳源| 扎鲁特旗| 信丰县| 湘乡市| 大关县| 金堂县| 潜江市| 虞城县| 雷州市| 广昌县| 军事| 蒙自县| 周宁县| 汤阴县| 集贤县| 岚皋县| 湛江市| 河曲县| 申扎县| 云南省| 通化县| 彭阳县| 兴城市| 墨竹工卡县| 泗阳县| 绥阳县| 杨浦区| 西乌珠穆沁旗| 谢通门县| 垣曲县| 九龙县| 井冈山市| 宁陕县| 沿河| 扎赉特旗| 广丰县| 濮阳县|