Creating the connection between Presenter and View

Now we move on to the user interface design and demonstrate how we set up the link between our presenters. Developing the user interface is no different to developing natively for iOS and Android; the only difference with MVP is that we initialize a view with its related presenter in the constructor.

Let's start by adding a new folder to the Chat.iOS project called Views, add in a new file called LoginViewController.cs, and implement the following:

public class LoginViewController : UIViewController, LoginPresenter.ILoginView
     {
         #region Private Properties
         private bool _isInProgress = false;
         private LoginPresenter _presenter;
         private UITextField _loginTextField;
         private UITextField _passwordTextField;
         private UIActivityIndicatorView _activityIndicatorView;
         #endregion
         #region Constructors
         public LoginViewController(LoginPresenter presenter)
         {
             _presenter = presenter;
         }
         #endregion
    } 
 

We start off simply with the private properties and the constructor, where we are passing a new LoginPresenter object that we create from the AppDelegate as the starting presenter. The two text fields are used for the username and password entries. We have these as a local variable as we will need to access one instance of each from multiple functions. We also have a UIActivityIndicatorView for displaying the progress when we login and register.

Let's go ahead and add the ViewDidLoad function. We will implement this in a few parts. First we are going to set the view of the presenter and initialize all the UI elements and add them into the View:

#region Public Methods
         public override void ViewDidLoad()
         {
             base.ViewDidLoad();
             View.BackgroundColor = UIColor.White;
             _presenter.SetView(this);
             var width = View.Bounds.Width;
             var height = View.Bounds.Height;
             Title = "Welcome";
             var titleLabel = new UILabel()
             {
                 TranslatesAutoresizingMaskIntoConstraints = false,
                 Text = "Chat",
                 Font = UIFont.FromName("Helvetica-Bold", 22),
                 TextAlignment = UITextAlignment.Center
             };
             _activityIndicatorView = new UIActivityIndicatorView()
             {
                 TranslatesAutoresizingMaskIntoConstraints = false,
                 Color = UIColor.Black
             };
             var descriptionLabel = new UILabel()
             {
                 TranslatesAutoresizingMaskIntoConstraints = false,
                 Text = "Enter your login name to join the chat room.",
                 Font = UIFont.FromName("Helvetica", 18),
                 TextAlignment = UITextAlignment.Center
             };
             _loginTextField = new UITextField()
             {
                 TranslatesAutoresizingMaskIntoConstraints = false,
                 Placeholder = "Username",
                 Font = UIFont.FromName("Helvetica", 18),
                 BackgroundColor = UIColor.Clear.FromHex("#DFE4E6"),
                 TextAlignment = UITextAlignment.Center
             };
             _passwordTextField = new UITextField()
             {
                 TranslatesAutoresizingMaskIntoConstraints = false,
                 Placeholder = "Password",
                 Font = UIFont.FromName("Helvetica", 18),
                 BackgroundColor = UIColor.Clear.FromHex("#DFE4E6"),
                 TextAlignment = UITextAlignment.Center
             };
             var buttonView = new UIView()
             {
                 TranslatesAutoresizingMaskIntoConstraints = false
             };
             var loginButton = new UIButton(UIButtonType.RoundedRect)
             {
                 TranslatesAutoresizingMaskIntoConstraints = false
             };
             loginButton.SetTitle("Login", UIControlState.Normal);
             loginButton.TouchUpInside += (sender, e) =>
                  Login(this, new Tuple<string, string>(_loginTextField.Text, _passwordTextField.Text));
             var registerButton = new UIButton(UIButtonType.RoundedRect)
             {
                 TranslatesAutoresizingMaskIntoConstraints = false
             };
             registerButton.SetTitle("Register", UIControlState.Normal);
             registerButton.TouchUpInside += (sender, e) =>
                 Register(this, new Tuple<string, string>(_loginTextField?.Text, _passwordTextField?.Text));
             Add(titleLabel);
             Add(descriptionLabel);
             Add(_activityIndicatorView);
             Add(_loginTextField);
             Add(_passwordTextField);
             Add(buttonView);
             buttonView.Add(loginButton);
             buttonView.Add(registerButton);
         }
         #endregion 

This is a large block of code, but we are creating quite a few UI elements. All have the TranslatesAutoresizingMaskIntoConstraints set to false ready for NSLayout . Have a look at how we integrate the ILoginView implementation with the Login and RegisterEventHandlers as they are wired to the TouchUpInside event of each button.

Now let's start building the NSLayoutConstraints. Add the following to the bottom of the ViewDidLoad function:

Tip

We are using the DictionaryViews object that we used in previous chapters. Create a new folder called Extras and add this object into the Extras folder.

var views = new DictionaryViews()
             {
                 {"titleLabel", titleLabel},
                 {"descriptionLabel", descriptionLabel},
                 {"loginTextField", _loginTextField},
                 {"passwordTextField", _passwordTextField},
                 {"loginButton", loginButton},
                 {"registerButton", registerButton},
                 {"activityIndicatorView", _activityIndicatorView},
                 {"buttonView", buttonView}
             };
             buttonView.AddConstraints(
                 NSLayoutConstraint.FromVisualFormat("V:|-[registerButton]-|", NSLayoutFormatOptions.DirectionLeftToRight, null, views)
                 .Concat(NSLayoutConstraint.FromVisualFormat("V:|-[loginButton]-|", NSLayoutFormatOptions.DirectionLeftToRight, null, views))
                 .Concat(NSLayoutConstraint.FromVisualFormat("H:|-[registerButton]-30-[loginButton]-|", NSLayoutFormatOptions.DirectionLeftToRight, null, views))
                 .ToArray());
             View.AddConstraints(
                 NSLayoutConstraint.FromVisualFormat("V:|-100-[titleLabel(50)]-[descriptionLabel(30)]-10-[loginTextField(30)]-10-[passwordTextField(30)]-10-[buttonView]", NSLayoutFormatOptions.DirectionLeftToRight, null, views)
                 .Concat(NSLayoutConstraint.FromVisualFormat("V:|-100-[activityIndicatorView(50)]-[descriptionLabel(30)]-10-[loginTextField(30)]-10-[passwordTextField(30)]-10-[buttonView]", NSLayoutFormatOptions.DirectionLeftToRight, null, views))
                 .Concat(NSLayoutConstraint.FromVisualFormat("H:|-10-[titleLabel]-10-|", NSLayoutFormatOptions.AlignAllTop, null, views))
                 .Concat(NSLayoutConstraint.FromVisualFormat("H:[activityIndicatorView(30)]-10-|", NSLayoutFormatOptions.AlignAllTop, null, views))
                 .Concat(NSLayoutConstraint.FromVisualFormat("H:|-10-[descriptionLabel]-10-|", NSLayoutFormatOptions.AlignAllTop, null, views))
                 .Concat(NSLayoutConstraint.FromVisualFormat("H:|-30-[loginTextField]-30-|", NSLayoutFormatOptions.AlignAllTop, null, views))
                 .Concat(NSLayoutConstraint.FromVisualFormat("H:|-30-[passwordTextField]-30-|", NSLayoutFormatOptions.AlignAllTop, null, views))
                 .Concat(new[] { NSLayoutConstraint.Create(buttonView, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterX, 1, 1)
 })
                 .ToArray());

The constraints will position the buttonView to the center of the screen horizontally; each buttons inside will be positioned horizontally next to each other. The rest of the layout is very self-explanatory. We are simply stacking the remaining element vertically down the page. The UIActivityIndicatorView will be positioned to the top right of the screen next to the TitleLabel. The rest of the layout will make more sense when we try running the application.

Finally, we add the remaining interface implementations; we require both Login and Register for the ILoginView interface. We also require IsInProgress  bool and the SetErrorMessage function; this will create a new UIAlertView showing the error message. We also override the get and set of IsInProgress to control the start and stop animation of the UIActivityIndicatorView:

         #region ILoginView implementation
         public event EventHandler<Tuple<string, string>> Login;
         public event EventHandler<Tuple<string, string>> Register;
         #endregion
         #region IView implementation
 
         public void SetErrorMessage(string message)
         {
             var alert = new UIAlertView()
             {
                 Title = "Chat",
                 Message = message
             };
             alert.AddButton("OK");
             alert.Show();
         }
         public bool IsInProgress
          {
              get
             {
                 return _isInProgress;
             }
             set
             {
                 if (value == _isInProgress)
                 {
                     return;
                 }
                 // we control the activity view when we set 'IsInProgress'
                 if (value)
                 {
                     _activityIndicatorView.StartAnimating();
                 }
                 else
                 {
                     _activityIndicatorView.StopAnimating();
                 }
                 _isInProgress = value;
             }
         }
         #endregion 

The link between our first view and presenter is not as clean as an MVVM BindingContext with Xamarin.Forms, but the advantage is having no middle layer of rendering between the native user interface and the data to be displayed.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.2.15