Tag Archives: C#

React to changes of focus in your Xamarin.tvOS applications

The focus engine introduced in UIKit for tvOS 9.0 is one of the key concepts you should know if you want to develop applications for the Apple TV.

It allows you to know what is the control that is currently focused on the screen, and to be notified when the focus changes from a view to another view (e.g. from a textfield to a button, from a collection view cell to the next cell, etc…).

Today I have created my first and simple application that uses a UICollectionView with few cells as you can see on the screenshot below. I was proud of my work until I realized that when the application is running, there is no visual indication that gives a feedback to the user of which cell is currently selected (cell #0 or cell #1).

tvOS - CollectionView without focus

I then looked for solutions to surround the focused cell with a white border to give an instant feedback to the user. The focus engine gives you this capability through the DidUpdateFocus method.

This method exposes a context to retrieve which views are focused (the previous and the next), and an animation coordinator to change attributes of these views within an animation.

When you know this method, it is very simple to accomplish your goal. The example below shows you how to remove the border for the old focused view, and add a border for the new focused view.

public override void DidUpdateFocus(UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
  base.DidUpdateFocus(context, coordinator);
  coordinator.AddCoordinatedAnimations(() =>
  {
    if (context.PreviouslyFocusedView != null)
    {
      var previousCell = (UICollectionViewCell)context.PreviouslyFocusedView;
      previousCell.Layer.BorderColor = UIColor.Clear.CGColor;
      previousCell.Layer.BorderWidth = 0;
    }

    if (context.NextFocusedView != null)
    {
      var nextCell = (UICollectionViewCell)context.NextFocusedView;
      nextCell.Layer.BorderColor = UIColor.White.CGColor;
      nextCell.Layer.BorderWidth = 5;
    }
  }, null);
}

The visual feedback is now more understandable for the user and he knows that the currently focused view is the cell #1.

tvOS - CollectionView with border when focused

It is good but if I want to have the same feature that is standard on the Apple TV (the cells sizes increase/decrease when they are focused/unfocused), what I need to do ?

If your cell is only composed with an UIImageView, you can select the option called “Adjusts image when focused” on the properties of this view in Xcode.

tvOS - ImageView adjusts image when focused

But when your cells are more complex like the sample below (each cell is composed with an UIImageView, a translucent UIView with a UILabel above), then you probably want to increase the size all the items inside the cell at the same time.

tvOS - CollectionView with scale when focused

No problem to achieve this goal with the same method that was previously mentioned. We just need to apply a transformation to the cell (CGAffineTransform.MakeScale(…)) when it receive the focus, and revert it (CGAffineTransform.MakeIdentity()) when the focus is lost.

public override void DidUpdateFocus(UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
  base.DidUpdateFocus(context, coordinator);
  coordinator.AddCoordinatedAnimations(() =>
  {
    if (context.PreviouslyFocusedView != null)
    {
      var previousCell = (UICollectionViewCell)context.PreviouslyFocusedView;
      previousCell.Transform = CGAffineTransform.MakeIdentity();
    }

    if (context.NextFocusedView != null)
    {
      var nextCell = (UICollectionViewCell)context.NextFocusedView;
      nextCell.Transform = CGAffineTransform.MakeScale(1.25f, 1.25f);
    }
  }, null);
}

As we have seen in this article, it’s pretty easy to interact with the focus engine of tvOS to apply any modifications on views, depending on the focus state of each of them.

Advertisements

Programmez #191 : Developing C# applications on OSX with Xamarin.Mac

You probably heard about Xamarin for mobile cross-platform development, but do you know that Xamarin also offers a solution to build OSX applications ?

Discover an overview of Xamarin.Mac in my article in the latest issue of Programmez, a magazine available in French-speaking countries (France, Belgium, Switzerland, Luxemburg, Canada…).

Programmez 191

Share your SharePoint sites with external users using CSOM

Yesterday on the Office 365 Yammer Network, someone asked if it was possible to add external users to a group using CSOM.

After a quick research, I found that it was a recurrent question and there’s no clear answer to that question. So I decided to investigate and I found the answer 🙂

In CSOM, there’s a namespace called Microsoft.SharePoint.Client.Sharing in which there are two useful classes called WebSharingManager and DocumentSharingManager.

These two classes are used to share a site or a document with users (internal or external).

In my case, I want to share a site with an external user so I need to use WebSharingManager.

This class has a method called UpdateWebSharingInformation with the following signature :

public static IList<UserSharingResult> UpdateWebSharingInformation(
  ClientRuntimeContext context,
  Web web,
  IList<UserRoleAssignment> userRoleAssignments,
  bool sendServerManagedNotification,
  string customMessage,
  bool additivePermission,
  bool allowExternalSharing
)

As you can see, there are many parameters which are very easy to understand but the important parts are userRoleAssignments and allowExternalSharing.

The first is a collection of users with whom you want to share the resource. The second is to enable external sharing if the users are not employed by your company.

How to use it in practice ? It’s very easy.

using(var password = new SecureString())
{
  foreach(var c in "myPassword".ToCharArray())
    password.AppendChar(c);

  using(var ctx = new ClientContext("https://tenant.sharepoint.com/"))
  {
    ctx.Credentials = new SharePointOnlineCredentials("user@tenant.onmicrosoft.com", password);

    var users = new List<UserRoleAssignment>();
    users.Add(new UserRoleAssignment()
    {
      UserId = "username@externaldomain.com",
      Role = Role.View
    });

    WebSharingManager.UpdateWebSharingInformation(ctx, ctx.Web, users, true, null, true, true);
    ctx.ExecuteQuery();
  }
}

When you execute the code above, the external user is invited as a viewer in the site associated to the CSOM context. He will receive an email to access to the site.

If you want to know if the invitation was sent successfully and if the user has accepted (or not), you just have to go to Access requests and invitations through the site settings.

External Sharing / Pending Requests

If you want more information about WebSharingManager and DocumentSharingManager, just go to the official documentation on MSDN.