Hi i am trying to create a simple FAB on my Xamarin.Forms Application. I am using FAB.Forms Nuget Package to achieve this (the newest pre-release).
I am following this example
So this is the the xaml code that should work, but does not for some reason:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="LoginSystem.Views.DailyPage"
xmlns:ViewModels="clr-namespace:LoginSystem.ViewModels"
xmlns:fab='clr-namespace:FAB.Forms;assembly=FAB.Forms'
BackgroundColor="Azure"
Title="Daily-Stats">
<ContentPage.Content>
<RelativeLayout>
<!--<StackLayout VerticalOptions="Center">
<Label Text="Welcome your Daily-Stats!" TextColor="Blue" FontSize="Large" VerticalOptions="Center" HorizontalOptions="Center" Margin="0,0,0,50" />
<Label Text="Page Under Construction" TextColor="Yellow" FontSize="Medium" VerticalOptions="Center" HorizontalOptions="Center" Margin="0,0,0,80" />
</StackLayout>-->
<ContentView
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}">
<ListView x:Name="List" BackgroundColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell TextColor="Gray" Text="{Binding .}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentView>
<fab:FloatingActionButton
Source="drawable/Add"
Size="Normal"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1, Constant=-75}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1, Constant=-75}"
/>
</RelativeLayout>
</ContentPage.Content>
</ContentPage>
The app just crashed for whatever reason.
This is the .cs file for the above xaml:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using LoginSystem.Models;
using LoginSystem.ViewModels;
using FAB.Forms;
namespace LoginSystem.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DailyPage : ContentPage
{
public DailyPage()
{
InitializeComponent();
var items = new List<string>();
for (int i = 0; i < 30; i++)
{
items.Add(string.Format("Abbas {0}", i));
}
this.List.ItemsSource = items;
NavigationPage.SetHasBackButton(this, false);
//BindingContext = new DailyPage_vm();
}
public DailyPage(string email, string password)
{
InitializeComponent();
NavigationPage.SetHasBackButton(this, false);
this.BindingContext = new DailyPage_vm(email, password);
}
}
}
I have tried making this work on the Old already release Nuget, but no luck.
Related
I'm going through simple example explained in video:
https://youtu.be/5Qga2pniN78?t=961
At 16. minute (timestamp in link above), he implements the Delete Command on SwipeItem.
In my local project, everything worked so far, but Delete Command is never triggered. I checked source generators, DeleteCommand exists.
My XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp1.MainPage"
xmlns:viewmodel="clr-namespace:MauiApp1.ViewModel"
x:DataType="viewmodel:MainViewModel">
<Grid RowDefinitions="100, Auto, *"
ColumnDefinitions=".75*, .25*"
Padding="10"
RowSpacing="10"
ColumnSpacing="10">
<Image Grid.ColumnSpan="2" Source="tom.jpg"
BackgroundColor="Transparent"></Image>
<Entry Placeholder="Enter task" Grid.Row="1" Text="{Binding Text}"></Entry>
<Button Text="Add" Grid.Row="1" Grid.Column="1" Command="{Binding AddCommand}"></Button>
<CollectionView Grid.Row="2" Grid.ColumnSpan="2" ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type x:String}">
<SwipeView>
<SwipeView.RightItems>
<SwipeItem Text="Delete" BackgroundColor="Red"
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainViewModel}}, Path=DeleteCommand}"
CommandParameter="{Binding .}">
</SwipeItem>
</SwipeView.RightItems>
<Grid Padding="0,5">
<Frame>
<Label Text="{Binding .}" FontSize="24"></Label>
</Frame>
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
View Model:
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace MauiApp1.ViewModel
{
public partial class MainViewModel : ObservableObject
{
public MainViewModel()
{
Items = new();
Items.Add("test");
}
[ObservableProperty]
private ObservableCollection<string> items;
[ObservableProperty]
private string text;
[RelayCommand]
private void Add()
{
if (string.IsNullOrWhiteSpace(text))
{
return;
}
Items.Add(Text);
Text = string.Empty;
}
[RelayCommand]
private void Delete(string s)
{
if (Items.Contains(s))
{
Items.Remove(s);
}
}
}
}
Why is DeleteCommand not triggering?
try this
Command="{Binding BindingContext.DeleteCommand,
Source={x:Reference myPage}}"
where myPage is your page's name
<ContentPage x:Name="myPage" ...
Resolved,
I forgot to add <SwipeItems> element after <SwipeView.RightItems>.
AncestorType={x:Type viewmodel:MainViewModel}
Your viewmodel is not part of the visual tree, so you can't bind to it with relative source anyway.
You can use your CollectionView's Binding Context and then the specific property you need:
Command="{Binding BindingContext.DeleteCommand, Source={RelativeSource AncestorType={x:Type CollectionView}}}
I have a xamarin forms app with a login screen.The problem I am facing is keyboard overlap when user enter details.The Username and password entering field is inside frame.
What I am getting
What I want
My Xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="#173F5F"
x:Class="app.Login">
<ScrollView>
<RelativeLayout>
<Image Source="backgrnd.png" Aspect="Fill"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}"
RelativeLayout.HeightConstraint= "{ConstraintExpression Type=RelativeToParent, Property=Height}"/>
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height}">
<StackLayout Orientation="Vertical" VerticalOptions="StartAndExpand" Margin="15,30,15,0">
<Image Source="logo.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="150" WidthRequest="150"></Image>
<Image Source="backlogo.png" HorizontalOptions="Center" VerticalOptions="Center" ></Image>
</StackLayout>
<StackLayout VerticalOptions="End" Margin="15,0,15,50" >
<Frame BackgroundColor="Snow" OutlineColor="Snow" HasShadow="True" HorizontalOptions="FillAndExpand" Padding="10,10,10,10"
CornerRadius="5"
Margin="15,10,15,0">
<StackLayout VerticalOptions="End" >
<StackLayout Orientation="Horizontal">
<Image Source="userlogo.png" HorizontalOptions="Start" HeightRequest="30" WidthRequest="30"></Image>
<Entry TextColor="Black"
x:Name="userName"
PlaceholderColor="Gray"
ReturnType="Next"
BackgroundColor="Snow"
Placeholder="User ID"
VerticalOptions="Center"
HorizontalOptions="FillAndExpand"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Image Source="locklogo.png" HorizontalOptions="Start" HeightRequest="30" WidthRequest="30"></Image>
<Entry TextColor="Black"
PlaceholderColor="Gray"
x:Name="password"
BackgroundColor="Snow"
VerticalOptions="Center"
Placeholder="Password"
IsPassword="true"
HorizontalOptions="FillAndExpand"/>
</StackLayout>
<Grid>
<Button x:Name="LoginButton" BackgroundColor="#4080a6" TextColor="White" Text="Sign In" Clicked="Login_Clicked" BorderRadius="7" BorderColor="#4080a6" BorderWidth = "2" HorizontalOptions="FillAndExpand" />
</Grid>
</StackLayout>
</Frame>
</StackLayout>
</StackLayout>
</RelativeLayout>
</ScrollView>
</ContentPage>
I tried Xam.Plugins.Forms.KeyboardOverlap but it doesnt solved my problem.Any help is appreciated.
Take a look at the answer here
I tried option 2 on Android and it works fine.
For your case,
try to add this Code to your page class
protected override void OnAppearing()
{
base.OnAppearing();
userName.Focused += InputFocused;
password.Focused += InputFocused;
userName.Unfocused += InputUnfocused;
password.Unfocused += InputUnfocused;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
userName.Focused -= InputFocused;
password.Focused -= InputFocused;
userName.Unfocused -= InputUnfocused;
password.Unfocused -= InputUnfocused;
}
void InputFocused(object sender, EventArgs args)
{
Content.LayoutTo(new Rectangle(0, -270, Content.Bounds.Width, Content.Bounds.Height));
}
void InputUnfocused(object sender, EventArgs args)
{
Content.LayoutTo(new Rectangle(0, 0, Content.Bounds.Width, Content.Bounds.Height));
}
Update
this code should be working on both Android and IOS
I'm developing an app for iOS and Android in Xamarin Forms and I've implemented the functionality for google and facebook login. I did that in the portable project and now I'm trying to style the buttons to look like the "Login with Facebook" button but the only style templates I found are for Android and iOS. I want to add the buttons to my MainPage.xaml so that the button is added to the view only there, but it is shown in the iOS and Android app.
Right now it looks like this without any style:
<Button x:Name="facebookLoginButton" Text="Facebook Login" Clicked="FacebookLoginButton_Clicked"/>
<Button x:Name="googleLoginButton" Text="Google Login" Clicked="GoogleLoginButton_Clicked"/>
There's a design guideline for the facebook here but I'm looking for a library which makes it possible to add the buttons to the MainPage.xaml without styling the buttons on my own.
In short: I'm looking for the following Android layout code snippet for Xamarin Forms which I can use in the xaml file
<com.facebook.widget.LoginButton
xmlns:fb="http://schemas.android.com/apk/res-auto"
android:id="#+id/loginFacebookButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
fb:login_text="#string/loginFacebookButton"
fb:logout_text=""
style="#style/FacebookLoginButton"/>
You have 3 ways of doing this :
You can do it the xaml way :
<Frame CornerRadius="3" BackgroundColor="#4167b2" HeightRequest="60" Margin="20" Padding="0" HasShadow="false">
<StackLayout Orientation="Horizontal" Padding="5">
<Image HeightRequest="80" Aspect="AspectFill" Source="http://3daystartup.org/wp-content/uploads/2011/07/facebook-logo-png-white-facebook-logo-png-white-facebook-icon-png-32.png" />
<Label Text="Continue with Facebook" VerticalOptions="CenterAndExpand" FontSize="20" FontAttributes="Bold" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer x:Name="FacebookButton" AutomationId="FacebookButton" Command="{Binding FacebookButtonCommand}" />
</StackLayout.GestureRecognizers>
</StackLayout>
</Frame>
You can do it the image way :
<Image HeightRequest="80" Aspect="AspectFill" Source="https://medyo.github.io/assets/images/facebook_connect_button.png">
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="FacebookImageButton" AutomationId="FacebookImageButton" Command="{Binding FacebookButtonCommand}" />
</Image.GestureRecognizers>
</Image>
Both methods have TapGestureRecognizer to it so you can click on it
please find the best answer here using facebook SDK and dependency injection.
https://blog.xamarin.com/native-android-facebook-authentication-azure-app-service/
as in the link described.
1) Create Button as view in Shared library
public class FacebookLoginButton : Xamarin.Forms.View
{
}
2) Use it in xaml
</code><?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:CoffeeCups.View;assembly:CoffeeCups"
x:Class="CoffeeCups.View.LoginPage">
<ContentPage.Content>
<StackLayout HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Padding="8">
<Label Text="Login for Coffee!"
VerticalOptions="Center"/>
<controls:FacebookLoginButton/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
3) you need to have render as below in your android project. it similar code in IOS.
using CoffeeCups.View;
using Xamarin.Forms;
using CoffeeCups.Droid;
using Xamarin.Forms.Platform.Android;
using Xamarin.Facebook.Login.Widget;
[assembly: ExportRenderer(typeof(FacebookLoginButton), typeof(FacebookLoginButtonRenderer))]
namespace CoffeeCups.Droid
{
public class FacebookLoginButtonRenderer : ViewRenderer<FacebookLoginButton, LoginButton>
{
LoginButton facebookLoginButton;
protected override void OnElementChanged(ElementChangedEventArgs<FacebookLoginButton> e)
{
base.OnElementChanged(e);
if(Control == null || facebookLoginButton == null)
{
facebookLoginButton = new LoginButton(Forms.Context);
SetNativeControl(facebookLoginButton);
}
}
}
}
Bonus UWP: this is not in the article but I achieved having native button in xamarin forms using winsdkfb library. basically your renderer in uwp looks like as below
[assembly: ExportRenderer(typeof(FacebookLoginButton), typeof(FacebookLoginButtonRendererUWP))]
namespace CoffeeCups.UWP
{
public class FacebookLoginButtonRendererUWP : ViewRenderer<FacebookLoginButton, FBLoginButton>
{
FBLoginButton facebookLoginButton;
protected override void OnElementChanged(ElementChangedEventArgs<FacebookLoginButton> e)
{
base.OnElementChanged(e);
if (Control == null || facebookLoginButton == null)
{
facebookLoginButton = new FBLoginButton();
SetNativeControl(facebookLoginButton);
Control.Click += buttonClick;
}
}
Button layout in Xamarin.Forms
I got facebook s logo from here:
http://3daystartup.org/wp-content/uploads/2011/07/facebook-logo-png-white-facebook-logo-png-white-facebook-icon-png-32.png
Put inside ContentPage.Content tag
<Frame CornerRadius="5"
HorizontalOptions="CenterAndExpand"
VerticalOptions="EndAndExpand"
BackgroundColor="#4167b2"
Margin="10"
Padding="5"
HasShadow="false">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Image Source="facebook" HeightRequest="32" WidthRequest="32"
Grid.Column="0" Grid.Row="0" />
<Label Text="Entre com o Facebook" Grid.Column="1" Grid.Row="0"
VerticalOptions="CenterAndExpand" FontSize="20"
FontAttributes="Bold" TextColor="White" />
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoginCommand}" />
</Grid.GestureRecognizers>
</Grid>
</Frame>
while making custom nested views i faced a problem.
i'm trying to use my custom view(ViewCell) from various pages.
and this is how i used it.
it wont raise any error if i use View for Xaml and codebehind,
but it wont display anything.
if i try ViewCell for xaml and its codebehind, i get some error.
and this is how i used it.
in mainPage xaml
<local:UploaderCell Uploader="{Binding post.uploader}"/>
this is the line causing the error, and
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns:local="clr-namespace:EodiRoad;assembly=EodiRoad"
xmlns:ic="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EodiRoad.SocialPage"
Title="Story">
<ContentPage.ToolbarItems>
<ToolbarItem Icon="plus.png" Order="Primary" Priority="0" Activated="OnCreatePostClicked"/>
</ContentPage.ToolbarItems>
<StackLayout>
<ListView
x:Name="socialPostsListView"
HasUnevenRows="true"
IsPullToRefreshEnabled="true"
Refreshing="Handle_Refreshing"
SeparatorVisibility="None"
ItemSelected="OnSocialPostSelected"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" Padding="5">
<local:UploaderCell Uploader="{Binding post.uploader}"/>
<Image
x:Name="postImage"
Source="{Binding post.image}"
Aspect="AspectFill"
MinimumHeightRequest="200"
/>
<StackLayout Orientation="Horizontal">
<Switch IsToggled="{Binding post.isLiked}"/>
<Button Text="comment"/>
<Button Text="share"/>
</StackLayout>
<StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand">
<Label Text="{Binding post.content}"/>
<Label Text="{Binding post.uploadedTime}" TextColor="Gray"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
this is my full mainPage xaml code.
in UploderCell.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell
xmlns:ic="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EodiRoad.UploaderCell">
<StackLayout Orientation="Horizontal" Padding="5">
<Button Clicked="Handle_Clicked" Image="{Binding Uploader.userProfile.userThumbnail}" BorderRadius="5" HeightRequest="50" WidthRequest="50"/>
<ic:CircleImage
x:Name="userProfileImage"
HeightRequest="50"
WidthRequest="50"
Aspect="AspectFill"
Source="{Binding Uploader.userProfile.userThumbnail}"
/>
<Label Text="{Binding Uploader.username}"/>
</StackLayout>
</ViewCell>
and the codeBehind
public partial class UploaderCell : ViewCell
{
public static readonly BindableProperty UploaderProperty =
BindableProperty.Create(
propertyName: "Uploader",
returnType: typeof(UserModel),
declaringType: typeof(UploaderCell)
);
public UserModel Uploader
{
get
{ return GetValue(UploaderProperty) as UserModel; }
set
{ SetValue(UploaderProperty, value); }
}
public UploaderCell()
{
InitializeComponent();
BindingContext = this;
}
}
and i get this error from mainPage
object of type Project.UploaderCell cannot be converted to type 'xamarin.forms.view'
what am i doing wrong here?
how could i possibly fi this..
In Xamarin Forms, I want to implement a horizontal listview (like shown in the image below). Via Rotation this is possible, but the I cannot change the row width. Is there also a possibility the let the second layout start under the first one?
Thanks in advance!
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Recipe.Pages.SearchPage"
Title="Search">
<ContentPage.Content>
<StackLayout Spacing="5" x:Name="layout" Orientation="Vertical" >
<StackLayout x:Name="layoutButtons" HorizontalOptions="FillAndExpand" Orientation="Horizontal" Spacing="5" BackgroundColor="Red">
<Button x:Name="btn1" BackgroundColor="White" Image="#drawable/scan" />
<Button x:Name="btn2" BackgroundColor="White" Image="#drawable/menu" />
<Button x:Name="btn3" BackgroundColor="White" Image="#drawable/search" />
</StackLayout>
<StackLayout x:Name="layoutList" >
<ListView x:Name="listView" Rotation="270" RowHeight="75" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#eee" Orientation="Vertical" >
<StackLayout Orientation="Horizontal" >
<Button BackgroundColor="White" Rotation="90" Image="{Binding Recipe}" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
EDIT
I also tried with a grid in the listview. Having the same issue.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Recipe.Pages.SearchPage"
Title="Search">
<ContentPage.Content>
<StackLayout Spacing="5" x:Name="layout" Orientation="Vertical" >
<StackLayout x:Name="layoutButtons" HorizontalOptions="FillAndExpand" Orientation="Horizontal" Spacing="5" BackgroundColor="Red">
<Button x:Name="btn1" BackgroundColor="White" Image="#drawable/scan" />
<Button x:Name="btn2" BackgroundColor="White" Image="#drawable/menu" />
<Button x:Name="btn3" BackgroundColor="White" Image="#drawable/search" />
</StackLayout>
<StackLayout x:Name="layoutList" >
<ListView x:Name="listView" Rotation="270" RowHeight="75" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" BackgroundColor="White" Rotation="90" Image="{Binding Recipe}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
I have also facing the same issue. I used below xaml code to manage the height and width of ListView.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VCRoom.HorizontalScroll">
<ContentPage.Content >
<RelativeLayout>
<ListView x:Name="TestListView"
RowHeight="80"
Rotation="270"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=-40}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=-0.5, Constant=40}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=80}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"
>
</ListView>
</RelativeLayout>
</ContentPage.Content>
</ContentPage>
Change RowHeight and Constant in XConstraint and YConstraint to manage Width and height of horizontal ListView accordingly.
Just for reference Below is custom cell I used to populate ListView items. I displayed vertical labels in each list item.
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="VCRoom.TestCell">
<ViewCell.View>
<StackLayout Orientation="Horizontal" HorizontalOptions="End" VerticalOptions ="Center">
<Label Rotation="90" Text="{Binding Day}" TextColor="#000000" HorizontalOptions="StartAndExpand" VerticalOptions="Start"/>
<Label Rotation="90" Text="{Binding mDate}" TextColor="#000000" HorizontalOptions="StartAndExpand" VerticalOptions="Start"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
Hope this will help future users.
The best solution that i found to resolve this problem is making a CustomScrollView with properties from Listview, like is showed in the tutorial from the Fabio Cozzolino.
Pay attention that he has a updated version in the comments.
He created a custom scrollview:
public class TLScrollView : ScrollView
{ public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(CustomScrollView), default(IEnumerable),
BindingMode.Default, null, new BindableProperty.BindingPropertyChangedDelegate(HandleBindingPropertyChangedDelegate));
private static object HandleBindingPropertyChangedDelegate(BindableObject bindable, object value)
{
throw new NotImplementedException();
}
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly BindableProperty ItemTemplateProperty =
BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(CustomScrollView), default(DataTemplate));
public DataTemplate ItemTemplate
{
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
}
public event EventHandler<ItemTappedEventArgs> ItemSelected;
public static readonly BindableProperty SelectedCommandProperty =
BindableProperty.Create("SelectedCommand", typeof(ICommand), typeof(CustomScrollView), null);
public ICommand SelectedCommand
{
get { return (ICommand)GetValue(SelectedCommandProperty); }
set { SetValue(SelectedCommandProperty, value); }
}
public static readonly BindableProperty SelectedCommandParameterProperty =
BindableProperty.Create("SelectedCommandParameter", typeof(object), typeof(CustomScrollView), null);
public object SelectedCommandParameter
{
get { return GetValue(SelectedCommandParameterProperty); }
set { SetValue(SelectedCommandParameterProperty, value); }
}
static void HandleBindingPropertyChangedDelegate(BindableObject bindable, object oldValue, object newValue)
{
var isOldObservable = oldValue?.GetType().GetTypeInfo().ImplementedInterfaces.Any(i => i == typeof(INotifyCollectionChanged));
var isNewObservable = newValue?.GetType().GetTypeInfo().ImplementedInterfaces.Any(i => i == typeof(INotifyCollectionChanged));
var tl = (CustomScrollView)bindable;
if (isOldObservable.GetValueOrDefault(false))
{
((INotifyCollectionChanged)oldValue).CollectionChanged -= tl.HandleCollectionChanged;
}
if (isNewObservable.GetValueOrDefault(false))
{
((INotifyCollectionChanged)newValue).CollectionChanged += tl.HandleCollectionChanged;
}
if (oldValue != newValue)
{
tl.Render();
}
}
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Render();
}
}
Created a method to render the scrollview:
public void Render ()
{ if (ItemTemplate == null || ItemsSource == null)
{
Content = null;
return;
}
var layout = new StackLayout();
layout.Orientation = Orientation == ScrollOrientation.Vertical ? StackOrientation.Vertical : StackOrientation.Horizontal;
foreach (var item in ItemsSource)
{
var command = SelectedCommand ?? new Command((obj) =>
{
var args = new ItemTappedEventArgs(ItemsSource, item);
ItemSelected?.Invoke(this, args);
});
var commandParameter = SelectedCommandParameter ?? item;
var viewCell = ItemTemplate.CreateContent() as ViewCell;
viewCell.View.BindingContext = item;
viewCell.View.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = command,
CommandParameter = commandParameter,
NumberOfTapsRequired = 1
});
layout.Children.Add(viewCell.View);
}
Content = layout; }
Then, a customRenderer to each platform (Here iOS):
[assembly: ExportRenderer(typeof(TLScrollView), typeof(TLScrollViewRenderer))]
namespace TitiusLabs.Forms.iOS.Controls
{
class CustomScrollViewRenderer : ScrollViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
var element = e.NewElement as CustomScrollView;
element?.Render();
}
} }
You can use the FlowListView plugin to archive horizontal listview easily on xamarin forms.
NuGet - DLToolkit.Forms.Controls.FlowListView