context.startActivity(ChannelListActivity.createIntent(context))Channel List Screen
The easiest way to set up a screen that shows the active user's channels and gives them the ability to search for messages is to use one of the following components:
ChannelListFragment: A Fragment that represents a self-contained channel list screen.ChannelListActivity: An Activity that is just a thin wrapper aroundChannelListFragment.
The ChannelListFragment contains these four inner components:
ChannelListHeaderView: Displays information about the current user and the connection state.ChannelListView: Displays a list of channel items in a paginated list.SearchInputView: An input field to search for messages that contain specific text.SearchResultListView: Displays a list of search result items.
Fragments and Activities representing self-contained screens are easy to use. They allow you to explore the SDK's features with ease; however, they offer limited customization.
Usage
To use the channel list screen, simply start ChannelListActivity from the SDK:
context.startActivity(ChannelListActivity.createIntent(context));This single line of code will produce a fully working solution, as shown in the image below.
![]() |
|---|
Alternatively, you can achieve the same result by adding ChannelListFragment from the SDK to your Fragment or Activity:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />class MyChannelListActivity : AppCompatActivity(R.layout.fragment_container) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, ChannelListFragment.newInstance())
.commit()
}
}
}public final class MyChannelListActivity extends AppCompatActivity {
public MyChannelListActivity() {
super(R.layout.fragment_container);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, ChannelListFragment.newInstance())
.commit();
}
}
}Next, let's see how to handle actions on the screen.
Handling Actions
To handle actions supported by ChannelListFragment, you need to implement corresponding click listeners in the parent Fragment or Activity:
class MyChannelListActivity : AppCompatActivity(R.layout.fragment_container),
ChannelListFragment.HeaderActionButtonClickListener,
ChannelListFragment.HeaderUserAvatarClickListener,
ChannelListFragment.ChannelListItemClickListener,
ChannelListFragment.SearchResultClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Add ChannelListFragment to the layout
}
override fun onUserAvatarClick() {
// Handle header avatar click
}
override fun onActionButtonClick() {
// Handle header action button click
}
override fun onChannelClick(channel: Channel) {
// Handle channel click
}
override fun onSearchResultClick(message: Message) {
// Handle search result click
}
}public final class MyChannelListActivity extends AppCompatActivity implements
ChannelListFragment.HeaderActionButtonClickListener,
ChannelListFragment.HeaderUserAvatarClickListener,
ChannelListFragment.ChannelListItemClickListener,
ChannelListFragment.SearchResultClickListener {
public MyChannelListActivity() {
super(R.layout.fragment_container);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add ChannelListFragment to the layout
}
@Override
public void onUserAvatarClick() {
// Handle header avatar click
}
@Override
public void onActionButtonClick() {
// Handle header action button click
}
@Override
public void onChannelClick(@NonNull Channel channel) {
// Handle channel click
}
@Override
public void onSearchResultClick(@NonNull Message message) {
// Handle search result click
}
}These are the main click listeners you can use with the ChannelListFragment:
HeaderActionButtonClickListener: Click listener for the right button in the header. Not implemented by default.HeaderUserAvatarClickListener: Click listener for the left button in the header represented by the avatar of the current user. Not implemented by default.ChannelListItemClickListener: Click listener for channel item clicks. Navigates toMessageListActivityby default.SearchResultClickListener: Click listener for search result items. Navigates toMessageListActivityby default.
Customization
The channel list screen component offers limited customization. The ChannelListFragment exposes a Builder with the following methods:
setFragment: Sets a custom channel list Fragment. The Fragment must be a subclass ofChannelListFragment.customTheme: Custom theme for the screen.showHeader: Whether the header is shown or hidden.showSearch: Whether the search input is shown or hidden.headerTitle: Header title. "Stream Chat" by default.
Other than that, you can use inheritance for further customization as shown in the example below:
class CustomChannelListFragment : ChannelListFragment() {
override fun setupChannelListHeader(channelListHeaderView: ChannelListHeaderView) {
super.setupChannelListHeader(channelListHeaderView)
// Customize channel list header view
// For example, set a custom listener for the avatar
channelListHeaderView.setOnUserAvatarClickListener {
// Handle avatar click
}
}
override fun setupChannelList(channelListView: ChannelListView) {
super.setupChannelList(channelListView)
// Customize channel list view
}
override fun setupSearchInput(searchInputView: SearchInputView) {
super.setupSearchInput(searchInputView)
// Customize search input field
}
override fun setupSearchResultList(searchResultListView: SearchResultListView) {
super.setupSearchResultList(searchResultListView)
// Customize search result list
}
override fun getFilter(): FilterObject? {
// Provide custom filter
return null
}
override fun getSort(): QuerySorter<Channel> {
// Provide custom sort
return super.getSort()
}
override fun createChannelListViewModelFactory(): ChannelListViewModelFactory {
// Provide custom ChannelListViewModelFactory
return ChannelListViewModelFactory(filter = getFilter(), sort = getSort())
}
override fun getTheme(): Int {
// Provide custom theme resource
return super.getTheme()
}
override fun applyStyle(style: ChannelListFragmentViewStyle) {
super.applyStyle(style)
// Apply additional custom styling
}
}
class CustomChannelListActivity : ChannelListActivity() {
override fun createChannelListFragment(): ChannelListFragment {
return ChannelListFragment.newInstance {
setFragment(CustomChannelListFragment())
customTheme(R.style.StreamUiTheme)
showSearch(true)
showHeader(true)
headerTitle("Title")
}
}
}public final class CustomChannelListFragment extends ChannelListFragment {
@Override
protected void setupChannelListHeader(@NonNull ChannelListHeaderView channelListHeaderView) {
super.setupChannelListHeader(channelListHeaderView);
// Customize channel list header view
// For example, set a custom listener for the avatar
channelListHeaderView.setOnUserAvatarClickListener(() -> {
// Handle avatar click
});
}
@Override
protected void setupChannelList(@NonNull ChannelListView channelListView) {
super.setupChannelList(channelListView);
// Customize channel list view
}
@Override
protected void setupSearchInput(@NonNull SearchInputView searchInputView) {
super.setupSearchInput(searchInputView);
// Customize search input field
}
@Override
protected void setupSearchResultList(@NonNull SearchResultListView searchResultListView) {
super.setupSearchResultList(searchResultListView);
// Customize search result list
}
@Nullable
@Override
protected FilterObject getFilter() {
// Provide custom filter
return super.getFilter();
}
@NonNull
@Override
protected QuerySorter<Channel> getSort() {
// Provide custom sort
return super.getSort();
}
@NonNull
@Override
protected ChannelListViewModelFactory createChannelListViewModelFactory() {
// Provide custom ChannelListViewModelFactory
return new ChannelListViewModelFactory.Builder()
.filter(getFilter())
.sort(getSort())
.build();
}
@Override
protected int getTheme() {
// Provide custom theme resource
return super.getTheme();
}
@Override
protected void applyStyle(@NonNull ChannelListFragmentViewStyle style) {
super.applyStyle(style);
// Apply additional custom styling
}
}
public final class CustomChannelListActivity extends ChannelListActivity {
@NonNull
@Override
protected ChannelListFragment createChannelListFragment() {
return ChannelListFragment.newInstance(builder -> {
builder.setFragment(new CustomChannelListFragment());
builder.customTheme(R.style.StreamUiTheme);
builder.showSearch(true);
builder.showHeader(true);
builder.headerTitle("Title");
return Unit.INSTANCE;
});
}
}Then you need to add CustomChannelListActivity to your AndroidManifest.xml, create an Intent for it using the ChannelListActivity.createIntent() method, and finally start the Activity:
context.startActivity(
ChannelListActivity.createIntent(
context = context,
activityClass = CustomChannelListActivity::class.java
)
)context.startActivity(ChannelListActivity.createIntent(context, CustomChannelListActivity.class));Fragments and Activities representing self-contained screens can be styled using the options described in the theming guide.
For advanced customization like custom event handling (e.g., filtering events by channel type when using multiple channel lists), use the component-based approach with ChannelListView instead. See Channel List Event Handling for more details.
