How to implement Carousel View in Xamarin.forms - xamarin

Is there any way we can create Carousel View instead of Carousel page so that only portion of the page swipes left or right. Also I want to create this control in the Xamarin Forms and not specific to platform.
If we need to create this custom control in the xamarin.android or xamarin.iOS then what is the real benefits of using the Xamarin.forms where this simple requirements are not getting satisfied.

There's a well documented CarouselView project hosted on github:
https://github.com/chrisriesgo/xamarin-forms-carouselview
and
http://chrisriesgo.com/xamarin-forms-carousel-view-recipe/

The nuget package for the CarouselView is now available (v2.3.0-pre1):
https://www.nuget.org/packages/Xamarin.Forms.CarouselView/2.3.0-pre1

We can use the CarouselView which was introduced in Xamarin forms 4.3. Now in Xamarin 4.6, we don't have to use the Forms.SetFlags("CollectionView_Experimental"); in appdelegate of iOS and mainactivity of android.
However, to use the indicatorview for the Carousel page we have to set this
Forms.SetFlags("IndicatorView_Experimental"); in appdelegate of iOS and mainactivity of android.

I have just implemented a similar thing. To create the a carousel view, I just created a horizontal Stacklayout, wrapped in a horizontal scroll view.
In my particular example, I needed to create an image gallery. I used the Camera control from the Xamarin.Labs project to get the image from either the camera roll or the camera itself. I then added this as a child to the Stacklayout.
Hope this helps.

As of Xamarin.Forms V2.2.0-pre1 CarouselView has now been added to Xamarin.Forms.
CarouselView
CarouselView is intended to fully replace CarouselPage. CarouselPage
will be deprecated in a future release. CarouselView is superior in
many ways, including its ability to be virtualized and nested within
layouts.
See https://forums.xamarin.com/discussion/63983/xamarin-forms-2-2-0-pre1-released#latest
Unfortunately there is no documentation on this as of yet.
EDIT:
CarouselView was Removed for Xamarin.Forms V2.2.0.31 because it wasn't ready for stable release. But from the look of it it will be merged back soon.
For now you can find the seperate CarouselView nuget package here: https://www.nuget.org/packages/Xamarin.Forms.CarouselView/2.3.0-pre1
and you can use it like so:
Namespace:
xmlns:cv="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"
Then we can simply add the CarouselView at the top of our page:
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height=".3*"/>
<RowDefinition Height=".7*"/>
</Grid.RowDefinitions>
<cv:CarouselView ItemsSource="{Binding Zoos}" x:Name="CarouselZoos">
<cv:CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Image Grid.RowSpan="2" Aspect="AspectFill" Source="{Binding ImageUrl}"/>
<StackLayout Grid.Row="1" BackgroundColor="#80000000" Padding="12">
<Label TextColor="White" Text="{Binding Name}" FontSize="16" HorizontalOptions="Center" VerticalOptions="CenterAndExpand"/>
</StackLayout>
</Grid>
</DataTemplate>
</cv:CarouselView.ItemTemplate>
</cv:CarouselView>
<!--List of Monkeys below-->
</Grid>
more info: https://blog.xamarin.com/flip-through-items-with-xamarin-forms-carouselview/

If you use Xamarin.Forms V2.2.0-pre1 and you need to display different views for each page, you can use a derived class like that:
public class CarouselViewMultiPage : CarouselView
{
List<View> _children = new List<View> { };
public List<View> Children {
get { return _children; }
set {
_children = value;
OnPropertyChanged();
}
}
public CarouselViewMultiPage ()
{
this.ItemTemplate = new CarouselTemplateSelector();
this.ItemsSource = Children;
this.SetBinding(CarouselView.ItemsSourceProperty, "Children");
BindingContext = this;
}
}
public class CarouselTemplateSelector : DataTemplateSelector
{
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
DataTemplate dt = new DataTemplate();
View civ = (View)item;
return new DataTemplate(() =>
{
return civ;
});
}
}
so you can call it passing Views:
public App()
{
// The root page of your application
MainPage = new ContentPage {
Content = new CarouselViewMultiPage
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Children =
{
new Label() { Text="Page 1"},
new Label() { Text="Page 2"},
new Label() { Text="Page 3"},
}
}
};
}

CarouselView has been introduced in Xamarin forms v4.4. You can have a look at this. In additional to CarouselView, IndicatorView is also added to indicate the nth item in the carousel.

Related

xamarin Syncfusion carousel with dots

I have a implement syncfusion Carousel and binding items using ItemTemplate.When i load the items to Carousel all item appears in Carousel view.But i need to add a doted indicator for it.
When user swipe though the Carousel by the dots should indicate current position.
When reading from documentation of syncfusion rotator have this functionality.
I need to add this to carousel view.
Here you can find all the SfCarousel Class Members.
And there's no property for the dots you refered in the SfCarousel print.
In fact, I think you are confusing it with another component called SfRotator. (that has an identical example like your print). and the property you are looking for is called: DotPlacement.
And can have the following states:
None //No Dots
Default //Dots Inside the Rotator View
OutSide //Dots Outside the Rotator View
We have analyzed your query and currently we don’t have dots view support in CarouselView. However, we can fulfill this requirement by using Border or Button control as like below code snippet.
Custom DotsView:
XAML:
<border:SfBorder BorderColor="{Binding ThumbBorder}" HorizontalOptions="Center" VerticalOptions="Center" BorderWidth="5" CornerRadius="50" />
Carousel View:
XAML:
<carousel:SfCarousel x:Name="carousel" Grid.Row="0" Offset="0" ItemsSource="{Binding ImageCollection}" ItemTemplate="{StaticResource itemTemplate}"
ItemHeight="200" SelectionChanged="Carousel_SelectionChanged"
ItemWidth="200" />
<StackLayout Grid.Row="1" HorizontalOptions="Center" x:Name="rotatorThumb" BackgroundColor="Transparent" Orientation="Horizontal"/>
C#:
public MainPage()
{
InitializeComponent();
Command command = new Command((object thumb) =>
{
var thumbView = thumb as DotsView;
if (thumbView != null)
{
((rotatorThumb.Children[carousel.SelectedIndex] as DotsView).BindingContext as CarouselModel).
ThumbBorder = Color.LightGray;
carousel.SelectedIndex = thumbView.Index;
(thumbView.BindingContext as CarouselModel).ThumbBorder = Color.Red;
}
});
for (var i = 0; i < ImageCollection.Count; i++)
{
var itemView = new DotsView() { BindingContext = ImageCollection[i], Index = i };
if (carousel.SelectedIndex == i)
(itemView.BindingContext as CarouselModel).ThumbBorder = Color.Red;
TapGestureRecognizer thumbTap = new TapGestureRecognizer();
thumbTap.Command = command;
itemView.GestureRecognizers.Add(thumbTap);
thumbTap.CommandParameter = itemView;
rotatorThumb.Children.Add(itemView);
}
}
Output:
Sample

How to make ActivityIndicator overlay full screen?

I have a StackLayout and a number of elements inside (buttons, texts etc).
I want the ActivityIndicator to overlay the entire screen and make it not able to do anything to those elements.
I have put ActivityIndicator inside the StackLayout but wrapped it with AbsoluteLayout thinking that AbsoluteLayout can easitly overlap everything:
<StackLayout>
<AbsoluteLayout>
<ActivityIndicator ... />
</AbsoluteLayout>
<...other elements...>
</StackLayout>
Instead activity indicator is displayed at the top of the StackLayout and other elements are available for affecting. I'm new in Xamarin and layouts, what am I doing wrong? All samples in the Internet have single ActivityIndicator per page...
It is better said that an AbsoluteLayout's children can easily overlap each other. Just as a StackLayout lets you stack controls inside , vertically or horizontally, an AbsoluteLayout lets you position controls inside using absolute or proportional values, thus if two controls have the same absolute positioning set, they will overlap 100%.
Therefore, you want to wrap your StackLayout and another StackLayout that has your ActivityIndicator inside an AbsoluteLayout using proportional sizing, e.g:
<AbsoluteLayout>
<StackLayout
x:Name="mainLayout"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All" >
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Do Something"
Clicked="DoSomethingBtn_Clicked" />
</StackLayout>
<StackLayout
x:Name="aiLayout"
IsVisible="False"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Gray" Opacity="0.5">
<ActivityIndicator
x:Name="ai"
IsRunning="False"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Color="Black"/>
</StackLayout>
</AbsoluteLayout>
The above sets the two StackLayouts to both take up the full size of the parent container of the AbsoluteLayout, which is presumably a Page. The StackLayout that has the indicator is initially hidden. IN the page code behind for the above example, I show the second StackLayout and start the activity indicator and show it for 2 seconds, and then hide it again:
private async void DoSomethingBtn_Clicked(object sender, EventArgs e)
{
ai.IsRunning = true;
aiLayout.IsVisible = true;
await Task.Delay(2000);
aiLayout.IsVisible = false;
ai.IsRunning = false;
}
Here is what it looks like:
And since the second StackLayout completely covers the first, none of the controls in the first StackLayout are clickable.
Might be worth going over the docs for the AbsoluteLayout to understand the AbsoluteLayout.LayoutBounds and AbsoluteLayout.LayoutFlags:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/absolute-layout
If you want to "overlap", you need to be outside of the StackLayout. A Grid is the most common control for this:
<Grid>
<StackLayout>
<...other elements...>
</StackLayout>
<ActivityIndicator ... />
</Grid>
Here's a hacked-up control for making things full-screen via the horribly-named RelativeLayout (tested in Android only)
[ContentProperty("ContentInner")]
public class FullScreenLayout : ContentView
{
public View ContentInner
{
get => ((RelativeLayout) Content).Children[0];
set
{
var display = DeviceDisplay.MainDisplayInfo;
var screenWidth = display.Width / display.Density;
var screenHeight = display.Height / display.Density;
var wrapper = new RelativeLayout();
wrapper.Children.Add(value, () => new Rectangle(0, 0, screenWidth, screenHeight));
Content = wrapper;
}
}
}
It can be used like this:
<controls:FullScreenLayout>
<!-- Anything you want fullscreen here -->
</controls:FullScreenLayout>
Unfortunately, if you use NavigationPage, this won't overlap the navigation bar. Every other solution currently on this page has the same issue. According to this question, it's not possible to solve this without using platform-specific customer renderers. Ugh.
If you don't mind the page being dimmed, you can use Rg.Plugins.Popup which implements the custom renderers needed.
I ended up solving my similar problem (dimming most of the screen) by implementing a custom renderer for the navigation page itself.

how to use radio buttons in xamarin forms

Creating a Registration page, I need to get the following data from user.
First Name
Last Name
Username
Email
Password
Date of Birth
Gender
User Role
For the last two parameters, I am unable to find how to use radio buttons in Xamarin.Forms. Following is my code for the Registration Page.
<StackLayout BackgroundColor="#30af91" Padding="60">
<Entry Text="{Binding FirstName}" Placeholder="First Name"/>
<Entry Text="{Binding LastName}" Placeholder="Last Name"/>
<Entry Text="{Binding UserName}" Placeholder="Last Name"/>
<Entry Text="{Binding Email}" Placeholder="Email" />
<Entry Text="{Binding Password}" Placeholder="Password" IsPassword="True"/>
<Entry Text="{Binding ConfirmPassword}" Placeholder="Confirm Password" IsPassword="True"/>
<DatePicker MinimumDate="1/1/1948" MaximumDate="12/31/2007"/>
<!--Radio buttons for Gender
1. Male 2.Female-->
<!--Radio Buttons for UserRole
1. Admin 2.Participant-->
<Button Command="{Binding RegisterCommand}" Text="Register"/>
<Label Text="{Binding Message}" />
</StackLayout>
Xamarin forms does not provide Radio Button.
You can either use
1)Switch
2)Picker
or any other component to fulfill your requirement
UPDATE
The xamarin forms update version 4.6 has introduced the Radio button control, Here is the official documentation
I think there is a simpler solution that is fairly easy and requires no libraries. Really a a radio group is just a fancy ListView. You would just need to create a viewModel for each radio button that has a IsSelected flag and switch between 2 images. I had a need to allow a user to select how long a token persisted:
XAML
<ListView
HasUnevenRows="True"
HorizontalOptions="FillAndExpand"
ItemsSource="{Binding Durations}"
ItemSelected="ListView_ItemSelected"
SelectedItem="{Binding SelectedDuration}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout
Orientation="Horizontal">
<Image
HeightRequest="18"
IsVisible="{Binding IsSelected}"
Source="radioButtonChecked.png"
WidthRequest="18"/>
<Image
HeightRequest="18"
IsVisible="{Binding IsUnselected}"
Source="radioButtonUnchecked.png"
WidthRequest="18"/>
<Label
Margin="8,0,0,0"
Text="{Binding Caption}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
We create a listview in our content page and listen for the ItemSelected event. Each list item is a horizontal stack panel where we flip between two images depending on the selected state
Code Behind
public partial class LoginPage : ContentPage
{
LoginPageViewModel LoginPageViewModel { get; }
public LoginTwoFactorFrequencyPage ()
{
BindingContext = LoginPageViewModel = new LoginPageViewModel();
InitializeComponent ();
}
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
LoginPageViewModel.UpdateSelected(e.SelectedItem as PersistenceDuration);
}
}
The page's code behind instantiates a view model and calls an UpdateSelected method with the newly selected item on the page's view model*
RadioButton ViewModel
The view model for each radio button:
public class PersistenceDuration : ViewModelBase
{
bool isSelected;
public string Caption { get; set; }
public TwoFactorTokenPersistenceDuration Duration { get; set; }
public bool IsSelected
{
get => isSelected;
set
{
isSelected = value;
OnPropertyChanged();
OnPropertyChanged("IsUnselected");
}
}
public bool IsUnselected => !IsSelected;
public PersistenceDuration(string caption, TwoFactorTokenPersistenceDuration duration)
{
Caption = caption;
Duration = duration;
IsSelected = false;
}
}
The radio button view model holds selection info and the caption. We make sure to fire OnPropertyChanged whenever the selected state changes
Page ViewModel
public class LoginPageViewModel : ViewModelBase
{
PersistenceDuration duration;
PersistenceDuration selectedDuration;
public ObservableCollection<PersistenceDuration> Durations { get; }
public PersistenceDuration SelectedDuration
{
get => selectedDuration;
set
{
if (value != null)
{
duration = value;
UpdateSelected(duration);
}
OnPropertyChanged();
}
}
public LoginTwoFactorFrequencyViewModel()
{
Durations = new ObservableCollection<PersistenceDuration>(
new List<PersistenceDuration>()
{
new PersistenceDuration(AppResources.Save_code__forever, TwoFactorTokenPersistenceDuration.Forever),
new PersistenceDuration(AppResources.ChatRequireEvery30Days, TwoFactorTokenPersistenceDuration.ThirtyDays),
new PersistenceDuration(AppResources.ChatRequireEveryLogin, TwoFactorTokenPersistenceDuration.None),
});
}
public void UpdateSelected(PersistenceDuration persistenceDuration)
{
foreach (var item in Durations)
item.IsSelected = persistenceDuration == item;
}
}
In the page view model we create a list of radio button view models that the XAML binds to. When we UpdateSelected() all the IsSelected states are updated which trigger binding updates which flip the image.
You will still need to do something about the highlight when someone selects an item, but that is easy enough to find on the internet :)
You can use XLabs plugin from manage NuGets package. After installing you can use like this:
In Xaml:
controls:BindableRadioGroup x:Name="Radiobtn"
In C#:
string[] gender = {"MAlE","FEMALE"}
Radiobtn.Add(gender)
Refer Link
https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/samples/XLabs.Samples/XLabs.Samples/Pages/Controls
You can get the radio button effect without a package. Use Labels with text unicode circle \u26AA or \u25CB. Attach a tab gesture recognizer to each label.
When tapped, change the text of the selected button to unicode circle bullet \u29BF and change the text of the other button(s) back to unicode circle \u26AA.
Test on your preferred platforms as each platform may display somewhat differently. You may need to adjust the font size as you change the text.
If you want real radiobuttons you can xlabs their package (https://github.com/XLabs/Xamarin-Forms-Labs/tree/master/src/Forms/XLabs.Forms/Controls/RadioButton)
Personally I'd just use a picker, Xlabs package hasn't been updated in a while so their might be some bugs in the radiobutton
You can use image as a radio button. When tou you click on it, it can change. It is not a good way to do it though.
This is xaml code:
<Image Scale="0.7" HorizontalOptions="Start" x:Name="radioButton" Source="unRadioBtn.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="radioButton_Clicked"></TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
And this is .cs:
private void radioButton_Clicked(object sender, EventArgs e)
{
radioButton.Source = "radioBtn.png";
}
Xamarin.Forms 4.6 introduced a new RadioButton control. You can find the documentation here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/radiobutton
You can use the switch component. Also you can see the implementation for a checkbox component from the XLabs project which is now discontinued, get the code and modify it as you need.
Hint: You're gonna need the custom renderers per platform for it to work .
You need to use Picker
https://developer.xamarin.com/api/type/Xamarin.Forms.Picker/
Actually it is the best alternative to RadionButton On Xamarin.forms
XLabs RadioButton and BindableRadioGroup work well: XLabs RadioButton for Xamarin Forms
Here's a simple Yes/No radio using the BindableRadioGroup:
var answers = new List<string>();
answers.Add("Yes");
answers.Add("No");
var RadioGroup = new XLabs.Forms.Controls.BindableRadioGroup()
{
ItemsSource = answers,
Orientation = StackOrientation.Horizontal
};
Xamarin Forms now provides a Radio Button control.
See docs here:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/radiobutton
As of XF 4.8 this is still experimental and I've not yet used this feature so can't comment on its stability.

TextCellRenderer in Xamarin.UWP

How could we set TextCell height with padding/margin in Windows Universal Project using Xamarin.Forms?
I tried following Custom renderer in Native project:
class CustomTextCellRenderer : TextCellRenderer
{
public override Windows.UI.Xaml.DataTemplate GetTemplate(Cell cell)
{
var d = base.GetTemplate(cell);
//Set something here???
return d;
}
}
but couldn't find any property to be set.
There is function to set dependency property of DataTemplate but I coudn't figure it out, what will be the dependency property name for height to set?
d.SetValue(???DependencyProperty???, value);
Since the TextCell is a built in cell, it's optimized and designed to be used as is. However you can create a custom DataTemplate based on the TextCell template and return that instead.
You can find the original template in the Xamarin.Forms source. Then in the UWP platform project's App.xaml, define your new DataTemplate inside the ResourceDictionary with a different key:
<DataTemplate x:Key="MyTextCell">
<StackPanel Background="Aqua">
<TextBlock
Padding="0 10 0 10"
Margin="5"
Text="{Binding Text}"
Style="{ThemeResource BaseTextBlockStyle}" />
<TextBlock
Text="{Binding Detail}"
Style="{ThemeResource BodyTextBlockStyle}"
x:Name="detail"/>
</StackPanel>
</DataTemplate>
and access it inside the custom renderer with:
return App.Current.Resources["MyTextCell"] as Windows.UI.Xaml.DataTemplate;

WP7: Binding to an element outside pivot.itemtemplate

I've been struggling for a while on this. I'm a bit of a newbie, but i lurked a lot and still couldn't find a solution to my problem, so I decided to post my question here.
I'm binding a pivot to a collection of objects I want to display to create a gallery. Here is my pivot control bound to a list called gallery, where each object contains 2 strings (url and description).
<controls:Pivot ItemsSource="{Binding gallery}" Grid.Row="0" x:Name="galleryPivot">
<controls:Pivot.ItemTemplate>
<DataTemplate>
<StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image Source="{Binding url}" />
<Grid Visibility="{Binding ElementName=galleryPivot, Path=DataContext.ShowDetail}">
<ListBox>
<ListBoxItem>
<StackPanel>
<TextBlock Text="{Binding description}" />
</StackPanel>
</ListBoxItem>
</ListBox>
</Grid>
</Grid>
</StackPanel>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
The datacontext is the viewmodel and initialized in the constructor of the page.
Here is my ViewModel:
public class GalleryViewModel : INotifyPropertyChanged
{
public List<Gallery> gallery
{
get { return Globals.pictures; }
}
private Visibility _showDetail = Visibility.Collapsed;
public Visibility ShowDetail
{
get { return _showDetail; }
set {
_showDetail = value;
RaisePropertyChanged("ShowDetail");
}
}
public GalleryViewModel()
{ }
public event PropertyChangedEventHandler PropertyChanged = delegate { return; };
protected void RaisePropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
The gallery object is a list in my ViewModel, as the ShowDetail property. As ShowDetail is outside the scope, I tried to set ElementName as explained here.
The pivot binds well to the gallery list, but when I change the value of ShowDetail, the grid won't hide. I also tried to set ElementName to LayoutRoot but it still won't work.
My question, how can I bind the visibility when it is outside the scope of the itemtemplate?
Within a DataTemplate the ElementName binding refers only to the names of elements that are within that DataTemplate. The data context within your data template is the Gallery instance, not the GalleryViewModel. You could move the ShowDetail property down to the Gallery class instead.
If you'd rather not do that, then an alternative would be to use a proxy for the data context, which you add as a resource to the page and bind to the page's data context (a GalleryViewModel instance presumably). You can then reference that resource as you would any other resource to get at the parent data context.
If you're not familiar with this proxy concept, then Dan Wahlin's post on the subject should help.

Resources