Related Tag List
Related Tag List
RelatedTagListView
is a component that displays a list of related tags to a user. For users with a
slower connection or queries that don't have any related tags, RelatedTagListView
also supports
loading and empty states.
Light Mode | Dark Mode |
---|---|
By default, a single list item shows the following:
- Tag name
- Left icon: usually used as type icon (curated, etc...)
- Right icon: usually used as status icon
Usage
To use RelatedTagListView
, include it in your XML layout as shown below:
<co.empathy.x.components.ui.relatedtag.list.RelatedTagListView
android:id="@+id/relatedTagListView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
We recommend using the RelatedTagListViewModel
to get the full list of data from the API and then
render it using the RelatedTagListView
.
The basic setup of the ViewModel and connecting it to the View is done the following way:
// Instantiate the ViewModel
val viewModel: RelatedTagListViewModel by viewModels {
RelatedTagListViewModelFactory()
}
// Bind the ViewModel with RelatedTagListView
viewModel.bindView(relatedTagListView, viewLifecycleOwner)
To instantiate RelatedTagListViewModel
you may want to pass an instance of the
RelatedTagsRepository
interface. See
this point
to read more.
All the logic of subscribing to data emitted by the ViewModel is provided by the bindView
function. Other than related tags data loading, the ViewModel is also handling actions like user
clicking a related tag by default.
And that would be actions necessary to use RelatedTagListView
. To get deeper and understand how to
customize it, please keep reading.
Handling Actions
RelatedTagListView
includes a set of related tags actions. Actions on RelatedTagListView
items
are available on click. With these, you can:
- Select the related tag
- Deselect the related tag
Light Mode | Dark Mode |
---|---|
The following actions are implemented by default, but you can add your own listeners if you want to extend the behaviour:
relatedTagListView.setRelatedTagItemClickListener { relatedTag ->
// Handle related tag click
}
relatedTagListView.setRelatedTagListOnItemsChangeListener {
// Handle on related tag list items change
}
Style Customization
There are two ways to customize the appearance of RelatedTagListView
:
- Using XML attributes
- Using the
StyleCustomizer
API at runtime to customize the style of allRelatedTagListView
instances
Using XML Attributes
There are many XML attributes that can be used to customize the appearance of the related tag list. The most useful ones include:
xIsRelatedTagLeftIconVisible
: Whether the left icon should be displayed.xIsRelatedTagRightIconVisible
: Whether the right icon should be displayed.xRelatedTagLeftIcon
: Drawable reference for the related tag left icon.xRelatedTagRightIcon
: Drawable reference for the related tag right icon.xRelatedTagTitleTextColor
: Color of the related tag title text.xRelatedTagTitleTextSize
: Size of the related tag title text.xRelatedTagBackgroundColor
: Background color of the related tag list item.
The full list of available XML attributes is available under RelatedTagListView
styleable,
here (opens new window).
Using StyleCustomizer API
The following example shows how to modify the style of all RelatedTagListView
instances globally
to:
- Change the background color
- Change the title text style
- Change the default icons
To make these changes, we need to define a custom XComponents.relatedTagListViewStyleCustomizer
:
XComponents.relatedTagListViewStyleCustomizer = StyleCustomizer { defaultViewStyle ->
defaultViewStyle.copy(
relatedTagBackgroundColor = ColorStateList.valueOf(Color.BLUE),
relatedTagRightIcon = context.getDrawable(R.drawable.x_ic_curated)!!,
relatedTagTitleTextStyle = TextStyle(
color = Color.WHITE,
size = resources.getDimensionPixelSize(R.dimen.x_font_size_base_xl),
),
)
}
These changes should have the following results:
Before | After |
---|---|
The `StyleCustomizer` should be set before the View is rendered to make sure that the new
style was applied. :::
Functional Customization: Creating a Custom ViewHolder Factory
RelatedTagListView
provides a way to completely change the default ViewHolders and add different
types of views. All you need to do is to provide your own RelatedTagListItemViewHolderFactory
.
Let's see an example that only displays the tag name, without any icon or border.
- Create the
custom_related_tag_list_item.xml
layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:singleLine="true"
android:textAllCaps="true"
android:textColor="#7A7A7A"
android:textSize="14sp"
android:textStyle="normal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
- Create a custom ViewHolder and ViewHolder factory:
class CustomRelatedTagListItemViewHolderFactory : RelatedTagListItemViewHolderFactory() {
override fun createRelatedTagViewHolder(parentView: ViewGroup): BaseRelatedTagListItemViewHolder {
return CustomRelatedTagViewHolder(parentView, listenerContainer.relatedTagClickListener)
}
}
class CustomRelatedTagViewHolder(
parent: ViewGroup,
private val relatedTagClickListener: RelatedTagListView.RelatedTagClickListener,
private val binding: CustomRelatedTagListItemBinding = CustomRelatedTagListItemBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
),
) : BaseRelatedTagListItemViewHolder(binding.root) {
private lateinit var relatedTag: RelatedTag
init {
binding.root.setOnClickListener { relatedTagClickListener.onClick(relatedTag) }
}
override fun bind(relatedTag: RelatedTag, diff: RelatedTagListPayloadDiff) {
this.relatedTag = relatedTag
binding.apply {
nameTextView.text = relatedTag.tag
}
}
}
- Set the custom ViewHolder factory on the
RelatedTagListView
:
relatedTagListView.setViewHolderFactory(CustomRelatedTagListItemViewHolderFactory())
These changes should have the following results:
RelatedTagsRepository
When RelatedTagListViewModel
is instantiated it needs a RelatedTagsRepository
to get the list of
related tags. If you don't provide one the ViewModel will use the one set in XAdapter, which is the
common one for all RelatedTagListView
instances. But sometimes you may want an instance of
RelatedTagListView
showing tags from another endpoint or with another configuration. In that case,
you should provide a custom RelatedTagsRepository
implementation, which has the following
interface:
public fun interface RelatedTagsRepository : XRepository {
public suspend fun getRelatedTags(
query: String,
selectedRelatedTags: List<RelatedTagDto>,
requestId: Any
): ResponseResult<Failure, List<RelatedTagDto>>
}
You can also use DefaultRelatedTagsRepository
- a more detailed implementation that covers the
most generic cases and uses the Empathy Platform APIs.
To use your custom RelatedTagsRepository
pass it to the RelatedTagListViewModel
when you
instantiate the ViewModel:
val viewModel: RelatedTagListViewModel by viewModels {
RelatedTagListViewModelFactory(
repository = CustomRelatedTagsRepository()
)
}