Xamarin - Entry Focused and TapGestureRecognizer not working - xamarin

<StackLayout Orientation="Horizontal" FlowDirection="RightToLeft" HorizontalOptions="EndAndExpand" Spacing="0">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="GoToBasket"></TapGestureRecognizer>
</StackLayout.GestureRecognizers>
<Frame x:Name="frmBasket" CornerRadius="24" Padding="8" BackgroundColor="#FFFFFF">
<StackLayout Orientation="Horizontal">
<Entry x:Name="lblTotalBasket" TextChanged="lblTotalBasket_TextChanged" HorizontalOptions="FillAndExpand" IsReadOnly="True" Text="{Binding TotalPrice, StringFormat='₺{0:0.00}'}" Margin="0, 0, 5, 0" HorizontalTextAlignment="Center" FontSize="13" VerticalTextAlignment="Center" FontAttributes="Bold" BackgroundColor="#FFFFFF" TextColor="{StaticResource Primary}"></Entry>
<Label x:Name="lblBasketIcon" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" BackgroundColor="Transparent" Text="" FontSize="15" TextColor="{StaticResource Primary}" Margin="8, 0, 0, 0" FontFamily="{StaticResource FontAwesomeSolid}"></Label>
</StackLayout>
</Frame>
</StackLayout>
StackLayout TapGestureRecognizer working except Entry element. I tried add TapGestureRecognizer and Focused attribute for Entry element but also not worked.
How StackLayout TapGestureRecognizer does work on Entry element tap ?

If you set the IsReadOnly=false to entry, the TapGestureRecognizer won't work because it will get fouced when tap it and user can type something. In this cause, you can call your method in the foucsed event:
<Entry x:Name="lblTotalBasket" Focused="lblTotalBasket_Focused"/>
And in code behind:
private void lblTotalBasket_Focused(object sender, FocusEventArgs e)
{
Console.WriteLine("lblTotalBasket_Focused-entry");
}
If you set the IsReadOnly=ture to entry, the TapGestureRecognizer will execute and you can also add TapGestureRecognizer to entry directly:
<Entry x:Name="lblTotalBasket" Focused="lblTotalBasket_Focused" HorizontalOptions="FillAndExpand" IsReadOnly="True" Text="{Binding TotalPrice, StringFormat='₺{0:0.00}'}" Margin="0, 0, 5, 0" HorizontalTextAlignment="Center" FontSize="13" VerticalTextAlignment="Center" FontAttributes="Bold" BackgroundColor="#FFFFFF">
<Entry.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"></TapGestureRecognizer>
</Entry.GestureRecognizers>
</Entry>
And in code behind:
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
Console.WriteLine("TapGestureRecognizer_Tapped-entry");
}
Update:
In Android, you also need to set isEnable = false to make TapGestureRecognizer work:
<Entry x:Name="lblTotalBasket" IsEnabled="False"/>

Try setting TapGesture for parent control and for your entry set InputTransparent="True" so that when you tap on entry it will actually recognized as tap on parent control.

Related

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.

Grouped ListView throws Index Out of Range exception when clicking outside of list in xamarin forms wpf

I have face issue with grouped listview in xamarin forms wpf application. I have used group listview in one of the pages in the application, where if I click outside of the grouped listview, the application is crashed. Please suggest any idea to fix this crash. Thank you.
exception : An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
Index was out of range. Must be non-negative and less than the size of the collection.
Image :
SampleCode :
Xaml :
<StackLayout HorizontalOptions = "FillAndExpand" VerticalOptions = "FillAndExpand">
<ListView x:Name="GroupedViewM" IsGroupingEnabled="true" ItemsSource="{Binding All}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemTapped="SelectedUserorChannel">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Padding="0,0,0,10">
<Label Text="{Binding Title}" TextColor="#e0e2e5" FontSize="22" VerticalTextAlignment="Center" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>
<Image x:Name="AddButton" IsVisible="{Binding AddChannelBtnVisibility}" Source="add.png" HeightRequest="20" WidthRequest="20" HorizontalOptions="EndAndExpand" VerticalOptions="CenterAndExpand" Margin="0,0,10,0">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="CreateNewChannel"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image Source="{Binding ProfileImage}" HorizontalOptions="Start" VerticalOptions="FillAndExpand" HeightRequest="20" WidthRequest="20"/>
<Label Text="{Binding FirstName}" TextColor="#e0e2e5" FontSize="Small" HorizontalOptions="FillAndExpand" VerticalTextAlignment="Center" VerticalOptions="FillAndExpand"/>
<Frame CornerRadius="5" BackgroundColor="#5e997c" Padding="8,0" IsVisible="{Binding MessageCountVisibility}" HorizontalOptions="EndAndExpand" VerticalOptions="CenterAndExpand">
<Label Text="{Binding MessageCount}" TextColor="White" FontSize="15" HorizontalOptions="Center" VerticalOptions="Center"/>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Xaml.cs
private void SelectedUserorChannel(object sender, ItemTappedEventArgs e)
{
try
{
var userModel = ((ListView)sender).SelectedItem as UserModel;
OpenUserOrGroupChat(userModel);
((ListView)sender).SelectedItem = null;
}
catch (Exception exception)
{
LoggingManager.Error(exception);
}
}
private async void CreateNewChannel(object sender, EventArgs e)
{
try
{
await Helper.NavigateToAsync(new CreateChannelView());
}
catch (Exception exception)
{
LoggingManager.Error(exception);
}
}`
Probably you are casting null with some datatype say UserModel.
i would suggest you to refactor your code with a null check in place
{
if (((ListView)sender).SelectedItem != null && ((ListView)sender).SelectedItem as UserModel userModel)
{
OpenUserOrGroupChat(userModel);
((ListView)sender).SelectedItem = null;
}
}
Try this setting Footer property of this ListView as:
<ListView x:Name="GroupedViewM" IsGroupingEnabled="true"
ItemsSource="{Binding All}"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
ItemTapped="SelectedUserorChannel"
Footer="">
</ListView>

List View on binding context change empties the button text

I have been facing this weird behaviour for a while now and I am unable to understand what exactly is causing the problem.
I am using FreshMvvm and I have a ListView with two buttons inside of it.
Now the problem is one of the buttons gets its text from Binding, Secondly to assign the button with a click command I had to follow this.
Now after adding this, the click event works perfectly but the text binding is not working I suspected this happened because of binding context change which I am sure is the whole reason but I am not able to find a way to fix this my listview code is as follows:
<ListView Grid.Row="1"
ItemsSource="{Binding CategoryAndActivities}"
x:Name="WishListName"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame>
<Grid VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!--Image and Title-->
<AbsoluteLayout Grid.Row="0"
HeightRequest="70"
IsClippedToBounds = "true">
<ffimageloading:CachedImage Source="{Binding ActivityImage}"
Aspect="AspectFill"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.0, 0.0, 0.3, 0.85"
Margin="5, 0, 5, 5"
ErrorPlaceholder="nopreviewlandscape"
LoadingPlaceholder="loadingicon"/>
<Label x:Name="ActivityNameLabel"
Text="{Binding ActivityName}"
FontAttributes="Bold"
VerticalTextAlignment="Start"
TextColor="{StaticResource price_text_color}"
FontSize="Small"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="1.0, 0.0, 0.7, 0.85"
Margin="5, 5, 5, 5">
</Label>
</AbsoluteLayout>
<!--Descp-->
<StackLayout Grid.Row = "1"
IsClippedToBounds="true">
<Label Text="{Binding AcitivityDescription}"
FontSize="Small"
LineBreakMode="WordWrap"
Margin="5, 0, 5, 5"/>
</StackLayout>
<Grid BackgroundColor="White"
Grid.Row = "2"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"/>
<ColumnDefinition Width="50*"/>
</Grid.ColumnDefinitions>
<Button BackgroundColor="{StaticResource ColorBrandingYellow}"
HorizontalOptions="FillAndExpand"
Command="{Binding AddToWishListCommand}"
Grid.Column="0"
BindingContext="{Binding Source={x:Reference ListName}, Path=BindingContext}"
CommandParameter="{Binding Source={x:Reference ActivityNameLabel},Path=BindingContext}"
TextColor="Black"
Text="{resourceLocal:Translate addToWishlist}"
FontSize = "Small" />
<Button BackgroundColor="{StaticResource ColorBrandingYellow}"
HorizontalOptions="FillAndExpand"
Grid.Column="1"
TextColor="Black"
Text="{Binding ActivityAmount}"
FontSize = "Small"
Command="{Binding GoFeatureActivityDetail}"
BindingContext="{Binding Source={x:Reference ListName}, Path=BindingContext}"
CommandParameter="{Binding Source={x:Reference ActivityNameLabel},Path=BindingContext}"/>
</Grid>
</Grid>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The problem is in the button with binding as text what happems is the text just show empty even though the data actually exist.
The Click event code is as follows:
public ICommand GoFeatureActivityDetail { get; set; }
public BrowseFeaturesPageModel()
{
AddToWishListCommand = new Command(WishListCommand);
GoFeatureActivityDetail = new Command(FeatureActivityDetailCommand);
}
private async void FeatureActivityDetailCommand(object obj)
{}
Right thinking, bad implementation.
What's going on here is that you've changed the Button's BindingContext and now it's not anymore able to "see" the ActivityAmount property of the item 'cause it's 'looking' to the BrowseFeaturesPageModel object.
You can keep the things simpler, changing the BindingContext only where you'll use, not the whole View (the button in this case):
<Button BackgroundColor="{StaticResource ColorBrandingYellow}"
HorizontalOptions="FillAndExpand"
Grid.Column="1"
TextColor="Black"
Text="{Binding ActivityAmount}"
FontSize = "Small"
Command="{Binding BindingContext.GoFeatureActivityDetail, Source={x:Reference ListName}}"
CommandParameter="{Binding .}"/>

How can I create a label inside a ViewCell that when clicked will call a method?

I have this code:
<ViewCell x:Name="ss" Height="50">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<Label Style="{DynamicResource ListItemTextStyle}" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Category Group" />
<Switch x:Name="ssSwitch" HorizontalOptions="End" VerticalOptions="Center" Grid.Column="1" Toggled="SsSwitch" />
</Grid>
</ViewCell>
I would like to extend this with another row and a label with the text of "Clear Deck"
How can I add a label for this that when clicked will call a method?
Here's a simple example of how to do it. You just need to add a Label with a TapGestureRecognizer. Then you need to implement ClearLabelTapped in the code behind.
<ViewCell x:Name="ss" Height="50">
<StackLayout Orientation="Vertical">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<Label Style="{DynamicResource ListItemTextStyle}" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Text="Category Group" />
<Switch x:Name="ssSwitch" HorizontalOptions="End" VerticalOptions="Center" Grid.Column="1" Toggled="SsSwitch" />
</Grid>
<Label Text="Clear Deck">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="ClearLabelTapped" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ViewCell>
Code behind:
public void ClearLabelTapped(object sender, EventArgs args)
{
// This is called when you tab the "Clear Deck" label
}
Please notice that using view models and commands would be a better way to do this (separation of concerns) but I wanted to keep this simple. Refer to the official documentation on how to work with the TapGestureRecognizer.

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