UI Components

The XDK ship with a number of UI Components to simplify application development. This section explores the Core Component library in more details.

Name Description
The Conversation View Presents a single Conversation, with a Message List of messages for that Conversation, as well as a Compose Bar for sending messages in that Conversation. Required component of any application
The Conversation List A list for viewing Conversations, used by your application to let users see a Conversation List and select one to open.
The Conversation Item An item of the Conversation List; generated by the Conversation List
The Message List A list for viewing Messages, scrolling through them and marking them as read
The Message Item An Item representing a message within the Message List. Generated by the Message List. Used by the Conversation View
The Identity List A list for viewing Identities. Used by applications to add or remove users from a Conversation
The Identity Item An Item representing an Identity/user within the Identity List. Generated by the Identity List.
The Compose Bar A panel for putting a text editor and buttons to allow users to enter text, and perform other message-sending-related activities such as selecting files for upload.
The Avatar Component Picture representing a user. Generated by Identity Item, Conversation Item and Message Item.
The Presence Component Conveys a user’s status/availability. Generated by Avatar.
The Typing Indicator A Component for indicating that a user is typing into a Conversation View

Of the above widgets, the ones most commonly used directly by developers are described below, and the rest are described in the API Reference.

The Conversation View

The Conversation View is the primary UI Component for adding conversations to an application. It serves the following goals:

  1. Displays the messages that have been sent and received
  2. Provides a Compose Bar for the user to send their own messages
  3. Manages sending read receipts as the user scrolls through messages
  4. Manages sending and displaying typing indicators.

In other words, the Conversation View manages the core tasks of having messaging within your application.

iOS Conversation View
Android Conversation View

The Layer Conversation View includes the following subcomponents:

  • Message Items List View: Renders a list of Messages returned by a Query
  • Typing Indicator Layout: Renders a message indicating who is currently typing a Message into this Conversation
  • Compose Bar: A text area for typing a Message, and views for adding buttons next to the text area

Creating the View

Include the following in the layout file:

<com.layer.xdk.ui.conversation.ConversationView
    android:id="@+id/conversation"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Data binding can be used so setters on the view do not have to explicitly be called. Include the variable in your layout:

<data>
    <variable
        name="viewModel"
        type="com.layer.xdk.ui.conversation.ConversationViewModel"/>
</data>

and add these attributes to your view:

app:conversation="@{viewModel.conversation}"
app:layerClient="@{viewModel.layerClient}"
app:messageItemsListViewModel="@{viewModel.messageItemsListViewModel}"

Creating the View Model

Create a new ConversationViewModel using the ServiceLocator:

ConversationViewModel viewModel = serviceLocator.getComponent().conversationViewModel();

This automatically provides the necessary dependencies from the ServiceLocator to create the ConversationViewModel instance. Alternatively, if using a Dagger implementation, you can retrieve an instance from your Component.

If using data binding, set the view model on the ConversationView through data binding:

binding.setViewModel(viewModel);

If not using data binding, call the following setters:

conversationView.setAdapter(viewModel.getAdapter());
conversationView.setLayerClient(viewModel.getLayerClient());
conversationView.setMessageItemsListViewModel(viewModel.getMessageItemsListViewModel());

An OnItemLongClickListener may be set on this view model to handle long clicks. For instance, a long click might trigger a delete message prompt or start a contextual action mode. This may be set by calling:

viewModel.getMessageItemsListViewModel().setItemLongClickListener(longClickListener);

Once a Conversation object is obtained from the LayerClient, set it on the view model:

viewModel.setConversation(conversation);

If not using data binding, you must call the following setter to set the conversation on the ConversationView:

ConversationView.setConversation(conversationView, 
        conversation,
        viewModel.getLayerClient(),
        viewModel.getMessageItemsListViewModel());

Defining a query

By default, the view model creates a query that captures all messages in the conversation sorted by their position. To set a custom query predicate, use MessageItemsListViewModel.setQueryPredicate(). Sorting is not modifiable at this time due to paging restrictions.

Set up the Compose Bar

The Compose Bar is not driven by a view model at this time. To set up the compose bar, obtain a reference to the view using:

ComposeBar composeBar = conversationView.getComposeBar();

Set a TextSender to use for sending text messages:

composeBar.setTextSender(new RichTextSender(context, layerClient));

Set desired AttachmentSenders to use for sending other message types:

GallerySender gallerySender = new GallerySender(R.string.xdk_ui_attachment_menu_gallery,
        R.drawable.ic_photo_black_24dp, 
        context,
        layerClient);
composeBar.addAttachmentSendersToDefaultAttachmentButton(gallerySender);

Customizing the Compose Bar

The ComposeBar contains 9 configurable buttons, 4 to the left and 5 to the right of the EditText. By default, one of the left buttons is configured to be the attachment button and 1 of the right buttons is configured to be the send button. These can be customized by calling the appropriate accessor and modifying the View.

For example, to add a button to the left of the default attachment button:

ImageButton button = composeBar.getLeftButton1();
button.setImageResource(R.drawable.xdk_ui_ic_feedback);
button.setVisibility(View.VISIBLE);

To remove the default attachment button:

ImageButton button = composeBar.getDefaultAttachButton();
button.setVisibility(View.GONE);

The Conversation List

The Conversation List serves the following goals:

  1. Display a list of Conversations to the user
  2. Allow the user to select a Conversation to open in the Conversation View
  3. Find Conversations with unread messages
  4. See recent state of each Conversation
Empty Conversation List
Conversation List with Large Sized Items

Creating the View

Include the following in the layout file:

<com.layer.xdk.ui.conversation.ConversationItemsListView
    android:id="@+id/conversations_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:itemHeight="@dimen/xdk_ui_item_height_large"/>

The itemHeight attribute determines which layout is to be used (tiny, small, medium or large).

Data binding can be used so the setter on the view does not have to explicitly be called. Include the variable in your layout:

<data>
    <variable
        name="viewModel"
        type="com.layer.xdk.ui.conversation.ConversationItemsListViewModel"/>
</data>

and add this attribute to your view:

app:adapter="@{viewModel.conversationItemsAdapter}"

Creating the View Model

Create a new ConversationItemsListViewModel using the ServiceLocator:

ConversationItemsListViewModel viewModel = serviceLocator.getComponent().conversationItemsListViewModel();

This automatically provides the necessary dependencies from the ServiceLocator to create the ConversationItemsListViewModel instance. Alternatively, if using a Dagger implementation, you can retrieve an instance from your Component.

If using data binding, set the view model on the ConversationItemsListView through data binding:

binding.setViewModel(viewModel);

If not using data binding, call the following setters:

conversationItemsListView.setAdapter(viewModel.getConversationItemsAdapter());

An OnItemClickListener and OnItemLongClickListener may be set on this view model to handle single and long clicks. For instance, a single click might start the activity that shows the Conversation View and a long click might trigger a delete conversation prompt or contextual action mode. This may be set by calling:

viewModel.setItemClickListener(clickListener);
viewModel.setItemLongClickListener(longClickListener);

Defining a query

By default, the view model creates a query that captures all conversations the user is participating in sorted by the last message received time. To use the default query, use the useDefaultQuery() method:

viewModel.useDefaultQuery();

To set a custom query predicate and sort descriptor, use the useQuery() method:

The Identity List

The Identity List serves the following goals:

  1. Display a list of Identities/users
  2. Allow the user to select Identities to have a Conversation with
  3. View status of users

Note that an Identity List is typically restricted to listing users who:

  • People that your user has had Conversations with in the past
  • People that you have explicitly issued a layerClient.follow("userID"); operation on from the client
  • People that your server has explicitly issued a follows request on. These requests are sent to Layer’s Server API.
Identity List with size = tiny
Identity List with size = medium

Creating the View

Include the following in the layout file:

<com.layer.xdk.ui.identity.IdentityItemsListView
    android:id="@+id/participants"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:itemHeight="@dimen/xdk_ui_item_height_medium" />

The itemHeight attribute determines which layout is to be used (tiny, small, medium or large).

Data binding can be used so the setter on the view does not have to explicitly be called. Include the variable in your layout:

<data>
    <variable
        name="viewModel"
        type="com.layer.xdk.ui.identity.IdentityItemsListViewModel"/>
</data>

and add this attribute to your view:

app:adapter="@{viewModel.getAdapter}"

Creating the View Model

Create a new IdentityItemsListViewModel using the ServiceLocator:

IdentityItemsListViewModel viewModel = serviceLocator.getComponent().identityItemsListViewModel();

This automatically provides the necessary dependencies from the ServiceLocator to create the IdentityItemsListViewModel instance. Alternatively, if using a Dagger implementation, you can retrieve an instance from your Component.

If using data binding, set the view model on the IdentityItemsListViewModel through data binding:

binding.setViewModel(viewModel);

If not using data binding, call the following setter:

identityItemsListView.setAdapter(viewModel.getAdapter());

Populate the view model with identities by calling useIdentities():

List<Identity> identities = new ArrayList<>(conversation.getParticipants());
Collections.sort(comparator, identities);
viewModel.useIdentities(identities);

A query can also be used to populate the list by calling useQuery():

Predicate predicate = new Predicate(Identity.Property.METADATA, 
        "key.subKey", 
        Predicate.Operator.EQUAL_TO, 
        "value");
SortDescriptor sortDescriptor = new SortDescriptor(Identity.Property.DISPLAY_NAME, 
        SortDescriptor.Order.ASCENDING);
mItemsListViewModel.useQuery(predicate, sortDescriptor);

The Avatar Component

The Avatar is a simple representation of a user where a compact but visual representation is needed. The Avatar is used within many of the XDK UI Components, but can also be used directly. For example, if creating a profile page for a user, you may use this Avatar Component as part of the profile. Having an Avatar Component that looks exactly the way the Avatar looks within the XDK UI Components will help create a consistent look and feel across your application.

The only information the Avatar provides beyond a photo, is the user’s online status via an embedded Presence Component.

Avatars are used inside most components and don’t typically need to be initialized manually. If customization is desired then an avatar can be included in your view by adding the following to the layout file:

<com.layer.xdk.ui.avatar.AvatarView
    android:id="@+id/avatar"
    android:layout_width="@dimen/xdk_ui_avatar_width"
    android:layout_height="@dimen/xdk_ui_avatar_height"
    android:layout_gravity="center_vertical" />

AvatarView also requires an ImageCacheWrapper which can be set by calling setImageCacheWrapper(). It is also recommended that you set an IdentityFormatter by calling setIdentityFormatter(). Set the participants to show via setParticipants().

Participants, IdentityFormatter and ImageCacheWrapper, along with style attributes can also be set via data binding by adding the following attributes to the view:

app:identityFormatter="@{viewModel.identityFormatter}"
app:imageCacheWrapper="@{viewModel.imageCacheWrapper}"
app:participants="@{viewModel.participants}"

The Presence Component

The Presence Component shows the status of a specific user in a very compact format and renders simply a colored circle where color conveys status.

Include the following in the layout file:

<!-- Note this is usually drawn over an AvatarView -->
<com.layer.xdk.ui.presence.PresenceView
    android:id="@+id/presence"
    android:layout_width="@dimen/xdk_ui_avatar_presence_height"
    android:layout_height="@dimen/xdk_ui_avatar_presence_height"
    android:layout_gravity="bottom|right" />

There is no view model for this view so the participants are set using setParticipants()

presenceView.setParticipants(conversation.getParticipants());

If multiple participants are set on the view then the view will be hidden. Participants along with style attributes can also be set via data binding by adding the following attribute:

app:participants="@{viewModel.participants}"
UI Concepts Misc Components