CollectionView disabling scrolling in Xamarin forms - xamarin

I am trying to disable scrolling in my collection view. The reason why I want to do that is there is a scroll view already in my XAML code. When I try to scroll all page elements on the page, collection view elements are also scrolled themselves but I don't want that.
<ScrollView>
<StackLayout Padding="20" Spacing="20" >
<Frame CornerRadius="15"
BackgroundColor="#A6EDB3"
VerticalOptions="StartAndExpand"
HeightRequest="200"
IsClippedToBounds="True"
Padding="0" >
<StackLayout Padding="10,5,10,5"
Orientation="Horizontal" >
<Image Source="settingsIcon"
HeightRequest="25"
WidthRequest="25"
Aspect="Fill" />
<Label Text="Filter"
FontSize="Medium"
VerticalTextAlignment="Center"
VerticalOptions="Center"/>
</StackLayout>
</Frame>
<Label Text="Vocabulary topics" TextColor="black" FontSize="20" FontAttributes="Bold" ></Label>
<CollectionView x:Name="topics" Scrolled="topics_Scrolled" VerticalScrollBarVisibility="Never" >
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="0,10,0,10">
<Frame HasShadow="False"
HeightRequest="60"
CornerRadius="15"
BackgroundColor="{Binding BackgroundColor}"
HorizontalOptions="Fill" >
<StackLayout Orientation="Horizontal">
<Frame BackgroundColor="{Binding BoxColor}" WidthRequest="40" ></Frame>
<StackLayout>
<Label Text="{Binding Name}"></Label>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ScrollView>

Having two scrolls on the same page is not the correct way.
Also if you just want to place items above/below your collectionView use the Header/Footer properties then!!
For instance, for the current design, your CollectionView could look something like below and work as you want it to.
<CollectionView Padding="20" x:Name="topics" Scrolled="topics_Scrolled" VerticalScrollBarVisibility="Never" >
<CollectionView.Header>
<StackLayout Spacing="20" >
<Frame CornerRadius="15"
BackgroundColor="#A6EDB3"
VerticalOptions="StartAndExpand"
HeightRequest="200"
IsClippedToBounds="True"
Padding="0" >
<StackLayout Padding="10,5,10,5"
Orientation="Horizontal" >
<Image Source="settingsIcon"
HeightRequest="25"
WidthRequest="25"
Aspect="Fill" />
<Label Text="Filter"
FontSize="Medium"
VerticalTextAlignment="Center"
VerticalOptions="Center"/>
</StackLayout>
</Frame>
<Label Text="Vocabulary topics" TextColor="black" FontSize="20" FontAttributes="Bold" ></Label>
</StackLayout>
</CollectionView.Header>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="0,10,0,10">
<Frame HasShadow="False"
HeightRequest="60"
CornerRadius="15"
BackgroundColor="{Binding BackgroundColor}"
HorizontalOptions="Fill" >
<StackLayout Orientation="Horizontal">
<Frame BackgroundColor="{Binding BoxColor}" WidthRequest="40" ></Frame>
<StackLayout>
<Label Text="{Binding Name}"></Label>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Note: you might have to adjust the margin and padding properties for it to look the exact same. My code is just an example.
For more information on CollectionView check: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/

You can use InputTransparent.
In your case what I would do would be to wrap the CollectionView in a <ContentView> as:
<ContentView InputTransparent="True"
x:Name="content">
<CollectionView ItemsSource="{Binding Items}"...>
...
</CollectionView>
</ContentView>
Create a scroll event to your scroll view:
<ScrollView Scrolled="ScrollView_Scrolled">
...
</ScrollView>
Then, with this event, make sure that the InputTransparent switches depending on the scroll position:
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
var scrollView = sender as ScrollView;
// Get the height of your scroll view
var contentSize = scrollView.ContentSize.Height;
// Get the max position of the scrollview
var maxPos = contentSize - scrollView.Height;
// Compare it to the current position
if (Convert.ToInt16(e.ScrollY) >= Convert.ToInt16(maxPos))
{
// Switch input transparent value
content.InputTransparent = false;
}
else if (Convert.ToInt16(e.ScrollY) == 0)
{
content.InputTransparent = true;
}
}
This is perfectly fine to use two scrollable controls on the same page for what you want to do. And I don't think <CollectionView.Header> would give you the result you want.
I hope it was helpful! 🙂

Related

How to make the BindableLayout to be scrollable

I have one list and i don't want to use listview inside it as how can i make it scrollable, data is binding but i am not able to scroll it.
<Grid Grid.Row="0" IsVisible="{Binding SearchListLayout}" Margin="0" Padding="0" BackgroundColor="White">
<ScrollView>
<StackLayout BindableLayout.ItemsSource="{Binding ProductsList}" x:Name="SearchLayoutItemList" HeightRequest="255">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="37,Auto">
<Image Grid.Row="0" Source="searchingicon.png" Style="{DynamicResource icons}"/>
<Label Grid.Row="0" Text="{Binding name}" FontSize="14" TextColor="Black" Margin="50,0,0,0" HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand"/>
<Image Grid.Row="0" Source="reload.png" Style="{DynamicResource icons}" HorizontalOptions="EndAndExpand" Margin="0,0,15,0"/>
<BoxView Grid.Row="1" Style="{DynamicResource DarkSeparator}" />
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>
</Grid>
Although the BindableLayout technically can display your list of items via the StackLayout, and the StackLayout height is being restraint to your height request; the encompassing ScrollViewer has nothing to scroll since it fully contains your StackLayout.
To achieve what you probably want (a fixed 255 pixel StackLayout that scrolls your items) the ScrollViewer should be inside the StackLayout as the rendered ItemsPanel for you Items. Again, you could achieve this with custom BindableLayouts, but this is exactly what Xamarin Forms ListView does by default.
You probably simply want to change your BindableLayout implementation to a ListView:
<Grid Grid.Row="0" IsVisible="{Binding SearchListLayout}" Margin="0" Padding="0" BackgroundColor="White">
<ListView ItemsSource="{Binding ProductsList}" x:Name="SearchLayoutItemList" HeightRequest="255">
<ListView.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="37,Auto">
<Image Grid.Row="0" Source="searchingicon.png" Style="{DynamicResource icons}"/>
<Label Grid.Row="0" Text="{Binding name}" FontSize="14" TextColor="Black" Margin="50,0,0,0" HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand"/>
<Image Grid.Row="0" Source="reload.png" Style="{DynamicResource icons}" HorizontalOptions="EndAndExpand" Margin="0,0,15,0"/>
<BoxView Grid.Row="1" Style="{DynamicResource DarkSeparator}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
The scrollview could not scroll as you set the HeightRequest="255" for the stacklayout in the scrollview. That because the display content's height is equal with the Scrollview, left content was covered.
Then I remove the HeightRequest
in StackLayout, the ScrollView could scroll. But the scrollview will fill the whole page which I thought is not what you want. So you could add parent layout Stacklayout outside the scrollview which set the size of scrollview equal to 255 and let it scroll at the same time. I just made an example :
<StackLayout>
<ScrollView HeightRequest="255">
<StackLayout BindableLayout.ItemsSource="{Binding ItemCollection}" x:Name="SearchLayoutItemList" >
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="37,Auto">
<Image Grid.Row="0" Source=""searchingicon.png"" />
<Label Grid.Row="0" Text="{Binding name}" FontSize="14" TextColor="Black" Margin="50,0,0,0" HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand"/>
<Image Grid.Row="0" Source="reload.png" HorizontalOptions="EndAndExpand" Margin="0,0,15,0"/>
<BoxView Grid.Row="1" BackgroundColor="Yellow"/>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>
</StackLayout>
For more info, you could refer to Xamarin.Forms ScrollView.
Hope it works for you.

Xamarin - ImageButton doesnt activate every click

Screen
On the picture above you can see where the ImageButton sometimes activates. When I spam clicking in the blue area the counter sometimes increases. I think there might be another Layer on top of the ImageButton but I dont know how to fix it. Below there is the XAML code. Hopefully somebody can help. Thanks!
<StackLayout>
<Label Text="Discover" TextColor="Black" FontSize="24" FontAttributes="Bold" Margin="15" />
<CarouselView ItemsSource="{Binding plants}" HeightRequest="300" PeekAreaInsets="100">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HeightRequest="280" WidthRequest="180" BackgroundColor="Wheat" HasShadow="True" Margin="10" Padding="0" HorizontalOptions="CenterAndExpand" CornerRadius="10" >
<Grid>
<StackLayout>
<ImageButton Source="{Binding imgsource}" VerticalOptions="FillAndExpand"
Aspect="AspectFill" Opacity="0.8" Clicked="ImageButton_Clicked"/>
</StackLayout>
<StackLayout Margin="0,10" >
<Image Source="https://icons-for-free.com/iconfiles/png/512/bookmark-131964752402712733.png" HeightRequest="35"
Aspect="AspectFit" HorizontalOptions="EndAndExpand" Margin="5,-15"/>
<Label Text="{Binding name_norm}" TextColor="Black" FontSize="16" FontAttributes="Bold"
Margin="15,-10,0,0" VerticalOptions="EndAndExpand" />
<StackLayout Orientation="Horizontal" Margin="15,-8,0,0" >
<Image Source="https://www.freeiconspng.com/thumbs/info-icon/info-icon-24.png" HeightRequest="15"
Aspect="AspectFit"/>
<Label Text="{Binding name_lat}" TextColor="Black" FontSize="16" FontAttributes="Italic" VerticalOptions="EndAndExpand" Margin="-5,0" />
</StackLayout>
</StackLayout>
</Grid>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Label x:Name="label" Text="0 ImageButton clicks"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
Here the C# Code:
namespace PlantBase
{
public partial class MainPage : ContentPage
{
int clickTotal;
public MainPage()
{
InitializeComponent();
}
private void ImageButton_Clicked(object sender, EventArgs e)
{
clickTotal += 1;
label.Text = $"{clickTotal} ImageButton click{(clickTotal == 1 ? "" : "s")}";
}
}
}
Check VisualElement.InputTransparent Property.
false if the element and its children should receive input; true if neither the element nor its children should receive input and should, instead, pass inputs to the elements that are visually behind the current visual element. Default is false.
What you need is to set InputTransparent to true on the text stackLayout .
<StackLayout InputTransparent="True" Margin="0,10" VerticalOptions="EndAndExpand" BackgroundColor="SaddleBrown">
<Label Text="{Binding name_norm}" TextColor="White" FontSize="16" FontAttributes="Bold" Margin="15,-10,0,0" VerticalOptions="EndAndExpand" />
<StackLayout Orientation="Horizontal" Margin="15,-8,0,0" BackgroundColor="Aqua">
<Image Source="https://www.freeiconspng.com/thumbs/info-icon/info-icon-24.png" HeightRequest="15" Aspect="AspectFit" />
<Label Text="{Binding name_lat}" TextColor="White" FontSize="16" FontAttributes="Italic" VerticalOptions="EndAndExpand" Margin="-5,0" />
</StackLayout>
</StackLayout>
Okay I found the Problem. It was that before I put the red Flag on the Top and the text at the bottom in one Stacklayout which expanded from top to bottom. Now that i put them in seperate StackLayouts it works and the ImageButton is free.
Pictures before/after.
old StackLayout
new Stacklayout
The new XAML is:
<CarouselView ItemsSource="{Binding plants}" HeightRequest="300" PeekAreaInsets="100">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HeightRequest="280" WidthRequest="180" BackgroundColor="Wheat" HasShadow="True" Margin="10" Padding="0" HorizontalOptions="CenterAndExpand" CornerRadius="10" >
<Grid>
<StackLayout>
<ImageButton Source="{Binding imgsource}" VerticalOptions="FillAndExpand"
Aspect="AspectFill" Opacity="0.9" Clicked="ImageButton_Clicked" />
</StackLayout>
<StackLayout VerticalOptions="StartAndExpand" HorizontalOptions="EndAndExpand" BackgroundColor="Aqua">
<ImageButton Source="https://icons-for-free.com/iconfiles/png/512/bookmark-131964752402712733.png" HeightRequest="35"
Aspect="AspectFit" HorizontalOptions="EndAndExpand" Margin="5,0" BackgroundColor="Transparent" Clicked="ImageButton_Clicked_1" />
</StackLayout>
<StackLayout Margin="0,10" VerticalOptions="EndAndExpand" BackgroundColor="SaddleBrown">
<Label Text="{Binding name_norm}" TextColor="White" FontSize="16" FontAttributes="Bold"
Margin="15,-10,0,0" VerticalOptions="EndAndExpand" />
<StackLayout Orientation="Horizontal" Margin="15,-8,0,0" BackgroundColor="Aqua" >
<Image Source="https://www.freeiconspng.com/thumbs/info-icon/info-icon-24.png" HeightRequest="15"
Aspect="AspectFit" />
<Label Text="{Binding name_lat}" TextColor="White" FontSize="16" FontAttributes="Italic" VerticalOptions="EndAndExpand" Margin="-5,0" />
</StackLayout>
</StackLayout>
</Grid>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
New Question now. Since at the bottom there is the Text StackLayout, where the Text is I cant press the ImageButton. How can I put the ImageButton as top "layer" so I can also press it while pressing on the text.

Auto-stack labels in stacklayout without margin

I'm having problem with not being able to stack two labels in a StackLayout and fit the content without a margin.
Expected result:
Current output:
I have tried and set the VerticalOptions, Margin and Padding properties but it still contains the margin (the red background) as well as the second content is not touching the "ceiling" of it's StackLayout parent.
Current code:
<ViewCell>
<StackLayout Orientation="Horizontal" VerticalOptions="Start">
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="summary.png"/>
</StackLayout>
<StackLayout Orientation="Vertical" VerticalOptions="Start" BackgroundColor="Red" Margin="0" Padding="0">
<StackLayout BindingContext="{Binding Date}" VerticalOptions="Start" BackgroundColor="Beige" Margin="0" Padding="0">
<Label Text="{Binding Text}" TextColor="{Binding Color}" VerticalOptions="Start"/>
</StackLayout>
<StackLayout BindingContext="{Binding Result}" VerticalOptions="Start" BackgroundColor="Blue" Margin="0" Padding="0">
<Label Text="{Binding Text}" TextColor="{Binding Color}" FontSize="{Binding FontSize}" VerticalOptions="Start"/>
</StackLayout>
</StackLayout>
</StackLayout>
</ViewCell>

Transparency not rendering the same on xamarin.ios project

I just can't understand why the background for my side menu on xamarin forms won't render the same on my xamarin.ios. Yet in other parts of the project my list views render and look the same when I use transparent backgrounds, I even tried copying and pasting the xaml code from other parts of the project where it does render the same, but still it does not work. In case anyone's wondering the side menu on ios was requested by the client.
Attached below I have 2 images showing how the side menu renders differently on the 2 platforms
Here's the Xaml code I'm using for my Side Menu:
<MasterDetailPage.Master>
<StackLayout Orientation="Vertical" BackgroundColor="Transparent" Spacing="0">
<StackLayout
HorizontalOptions="Fill"
Orientation="Horizontal"
VerticalOptions="Fill" BackgroundColor="Black" Padding="50, 50, 50, 50">
<StackLayout HorizontalOptions="Center" Orientation="Vertical">
<ffimageloading:CachedImage x:Name="ProfilePictureCircleImage"
LoadingPlaceholder="profile_image_placeholder.png"
ErrorPlaceholder="profile_image_placeholder.png"
DownsampleToViewSize="true"
FadeAnimationEnabled="true"
HeightRequest="65"
WidthRequest="65">
<ffimageloading:CachedImage.Transformations>
<fftransformations:CircleTransformation/>
</ffimageloading:CachedImage.Transformations>
</ffimageloading:CachedImage>
</StackLayout>
<StackLayout
HorizontalOptions="CenterAndExpand"
Orientation="Vertical"
VerticalOptions="CenterAndExpand">
<Label
x:Name="FullNameLabel"
FontSize="18"
HorizontalOptions="Center"
TextColor="White"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</StackLayout>
<BoxView HeightRequest="2" BackgroundColor="#D90B31"/>
<ListView
x:Name="NavigationMenuItems"
ItemSelected="OnMenuItemSelected"
BackgroundColor="{StaticResource TileColour}"
RowHeight="60"
SeparatorVisibility="None"
SeparatorColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!-- Main design for menu items -->
<StackLayout
Padding="20,10,0,10"
Orientation="Horizontal"
Spacing="20"
VerticalOptions="FillAndExpand"
BackgroundColor="Transparent">
<local:TintedCachedImage TintColor="{StaticResource SideMenuIconColor}"
Source="{Binding Icon}"
VerticalOptions="Center"
DownsampleToViewSize="true"
HeightRequest="19"
WidthRequest="19"/>
<Label
FontSize="15"
Text="{Binding Title}"
TextColor="{StaticResource SideMenuTextColor}"
VerticalOptions="Center" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage />
</MasterDetailPage.Detail>
above are pictures illustrating how it looks across the 2 platforms.
Found the solution to this question on another stackoverflow thread I had to use a custom renderer:
public class CustomSideMenuRenderer: TabletMasterDetailRenderer
{
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
var master = ViewControllers[0];
master.View.BackgroundColor = UIColor.Clear;
var detail = ViewController.ChildViewControllers[1];
}
}

Cardview in Xamarin.Forms?

Does anyone know if it's possible to create a CardView style (scrollable) list using Xamarin.Forms? We need it to render same on both iOS and Android. Also need to tweak properties like the shadow (to slightly raise each card)
Here is a nuget: https://github.com/tiger4589/Xamarin.Forms-CardView
Cardview control in Xamarin.Froms.
Install it in your shared project only and use the following import in your page's xaml:
xmlns:cardView="clr-namespace:CardView;assembly=CardView"
Just use the control in viewcell of your listview.
Example screenshot: each card is a row in listview
Following code is an usage example of above control:
<ListView
x:Name="listView"
Margin="0,8,0,0"
HasUnevenRows="True"
ItemTapped="Handle_ItemTapped"
ItemsSource="{Binding HouseholdDetail}"
SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="8,8,8,8" Orientation="Vertical">
<cardView:CardView
BackgroundColor="White"
CardViewHasShadow="True"
HeightRequest="220">
<cardView:CardView.CardViewContent>
<StackLayout
Padding="10"
HorizontalOptions="Center"
Spacing="10"
VerticalOptions="Center">
<Image HeightRequest="96" Source="{Binding Image}" />
<BoxView
HeightRequest="1"
WidthRequest="275"
Color="LightGray" />
<Grid>
<Label
Grid.Row="0"
Grid.Column="0"
Margin="15,0,0,0"
FontSize="Medium"
Text="{Binding FullName}" />
<Label
Grid.Row="0"
Grid.Column="1"
Margin="0,0,15,0"
FontSize="Medium"
HorizontalTextAlignment="End"
Text="{Binding Relation}" />
</Grid>
<BoxView
HeightRequest="1"
WidthRequest="275"
Color="LightGray" />
<Grid>
<Label
Grid.Row="0"
Grid.Column="0"
Margin="15,0,0,0"
FontSize="Medium"
Text="{Binding LeavesAt}" />
<Label
Grid.Row="0"
Grid.Column="1"
Margin="0,0,15,0"
FontSize="Medium"
HorizontalTextAlignment="End"
Text="{Binding ArrivesAt}" />
</Grid>
</StackLayout>
</cardView:CardView.CardViewContent>
</cardView:CardView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here you may notice the freedom you have such as you can define to have shadow or not and design the whole layout of cardview using Xamarin default layouts.
Why not use a frame? i am put inside at the listview, a frame with grid.
and do something like this to get the style cardview you like.
public class CardView : Frame
{
public CardView()
{
if (Device.OS == TargetPlatform.iOS)
{
HasShadow = false;
OutlineColor = Color.Transparent;
BackgroundColor = Color.Transparent;
}
if (Device.OS == TargetPlatform.Android)
{
HasShadow = true;
OutlineColor = Color.Transparent;
BackgroundColor = Color.Transparent;
}
}
}
No need Third party library
it is support scrollable and pullrefresh
<StackLayout>
<ListView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Frame HasShadow="True" >
<StackLayout>
<Label Text="{Binding Text}"
LineBreakMode="NoWrap"
FontSize="16" />
<Label Text="{Binding Description}"
LineBreakMode="NoWrap"
FontSize="16" />
</StackLayout>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>

Resources