Xamarin.Forms CarouselView
Contents
With CarouselView, item collections are displayed in a floating order. By default, items are listed in a horizontal position.
Our motivation in this post, get first five news from newsapi and show it in a CarouselView. Also, I used PancakeView plugin to make beautiful design. You can learn how to use PancakeView from my recent post.
Download Plugins
You need the following plugins for the project:
- Newtonsoft.Json -> to deserialize JSON files.
- Xamarin.Forms.PancakeView -> for design
You can use download plugins using Nuget Package Manager. I also recommend you to check out Top 5 Useful Plugins in Xamarin.
Get API Key
In this project I use News API because it is free. You need API key to query. Register this site and get an API key easily.
This is an example query to understand this documentation. Open the following link in a browser. You can see the result.
http://newsapi.org/v2/everything?q=bitcoin&from=2020-06-25&sortBy=publishedAt&apiKey=0aa6acdc93314fa380708f86053e21fc
Model Class
After open the above link you will see a JSON file. To convert this file to C# class use jsonutils.com. You can paste JSON file and convert it easily.
After doing the translation, create a folder named Model in the project and add a class named News.cs to this folder. Paste the class you just translated from the site into this class.
public class Source
{
public string id { get; set; }
public string name { get; set; }
}
public class Article
{
public Source source { get; set; }
public string author { get; set; }
public string title { get; set; }
public string description { get; set; }
public string url { get; set; }
public string urlToImage { get; set; }
public DateTime publishedAt { get; set; }
public string content { get; set; }
}
public class News
{
public string status { get; set; }
public int totalResults { get; set; }
public IList<Article> articles { get; set; }
}
Service Class
Add a Services folder to the project and create a class named NewsAPI.cs in this folder. There will be methods in this class that make the API query.
class NewsAPI
{
public const string NEWS_API_KEY = "WRITE YOUR API KEY HERE";
public const string BASE_URL = "https://newsapi.org/v2/everything?q={0}&from={1}&sortBy=publishedAt&apiKey={2}";
public static async Task<News> GetNewsAsync(string query)
{
string date = DateTime.Now.ToString("yyyy-MM-dd h:mm tt");
News news = new News();
string url = String.Format(BASE_URL, query, date, NEWS_API_KEY);
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var posts = JsonConvert.DeserializeObject<News>(content);
news = posts;
}
return news;
}
}
After write the class codes add namespaces that necessary. You will see the required namespaces already.
CarouselView ViewModel Class
To fully implement the MVVM architecture, add the ViewModels folder to the project and create a class named NewsViewModel.cs in this folder.
Put the answers from the API in a List<> named ArticleList. This list will be the ItemSource of CarouselView.
public class NewsViewModel : INotifyPropertyChanged
{
private List<Article> articleList { get; set; }
public List<Article> ArticleList
{
get
{
return articleList;
}
set
{
if (value != articleList)
{
articleList = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public NewsViewModel()
{
Task.Run(APIAsync);
}
private async Task APIAsync()
{
var news = await NewsAPI.GetNewsAsync("Android");
List<Article> articleList = new List<Article>();
for (int i = 0; i < 5; i++)
{
articleList.Add(new Article
{
title= news.articles[i].title,
description=news.articles[i].description,
urlToImage=news.articles[i].urlToImage,
url=news.articles[i].url
}
);
}
ArticleList = articleList;
}
}
APIAsync method gets news about “Android”. Assigns the title, description, urlToImage and url variables to the list with a for loop.
CarouselView Page
Now add a Views folder to the project and add a ContentPage named NewsPage.xaml. Create a CarouselView and IndicatorView in ContentPage. Set the ArticleList as ItemSource property of CarouselView.
<ContentPage.Content>
<StackLayout>
<CarouselView ItemsSource="{Binding ArticleList}" IndicatorView="IndicatorView">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout >
<Frame HorizontalOptions="Center" VerticalOptions="CenterAndExpand">
<StackLayout>
<pancakeview:PancakeView BackgroundColor="#d4d6c8" HeightRequest="600" WidthRequest="300" CornerRadius="20" HorizontalOptions="Center" VerticalOptions="Center">
<ScrollView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<pancakeview:PancakeView Grid.Row="0" BackgroundColor="Transparent" CornerRadius="20,20,0,0" HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="{Binding urlToImage}" HeightRequest="200" WidthRequest="300" Aspect="AspectFill" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" />
</pancakeview:PancakeView>
<Label Grid.Row="1" Text="{Binding title}" TextColor="Black" FontSize="20" FontAttributes="Bold" HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand" Margin="10" />
<Label Grid.Row="2" Text="{Binding description}" TextColor="Black" FontSize="15" HorizontalOptions="Center" VerticalOptions="Center" Margin="10" />
<Label Grid.Row="3" Text="{Binding url}" TextColor="#1235F5" FontSize="15" HorizontalOptions="Center" VerticalOptions="Center" Margin="10" TextDecorations="Underline" FontAttributes="Italic" />
</Grid>
</ScrollView>
</pancakeview:PancakeView>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<IndicatorView x:Name="IndicatorView"
IndicatorSize="7"
IndicatorsShape="Circle"
IndicatorColor="Black"
SelectedIndicatorColor="DarkGray"
HorizontalOptions="Center"
VerticalOptions="Center" Margin="0,0,0,20">
</IndicatorView>
</StackLayout>
</ContentPage.Content>
Add necessary namespaces for PancakeView and others if exists.
To link the ViewModel class to the page, add the following line in the constructor method of the NewsPage.xaml.cs class.
public NewsPage()
{
InitializeComponent();
this.BindingContext = new NewsViewModel();
}
Finally, set MainPage in the App.xaml.cs class before launching the application. And of course add the required namespaces.
public App()
{
InitializeComponent();
MainPage = new NewsPage();
}
CarouselView Output
Everything is ok. You can run the application and see how it looks.
Your screen will look different from this because the AppShell structure is used here. You can check our Using Shell in Xamarin.Forms article to learn how to use AppShell.