Drag and drop in Grid layout in Xamarin Forms - xamarin

I have the following grid layout set up in my XAML page.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView BackgroundColor="Red" Grid.Row="0" Grid.Column="0">
<BoxView.GestureRecognizers>
<PanGestureRecognizer PanUpdated="PanGestureRecognizer_OnPanUpdated"/>
</BoxView.GestureRecognizers>
</BoxView>
<BoxView BackgroundColor="Green" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" />
<BoxView BackgroundColor="Red" Grid.Row="0" Grid.Column="3" />
<BoxView BackgroundColor="Blue" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
<BoxView BackgroundColor="Purple" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2"/>
<BoxView BackgroundColor="Aqua" Grid.Row="2" Grid.Column="0" />
<BoxView BackgroundColor="Fuchsia" Grid.Row="2" Grid.Column="1" />
<BoxView BackgroundColor="GreenYellow" Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2">
</BoxView>
</Grid>
I want to add a drag and drop functionality on each box view. The idea is I should be able to drag each box view and drop it on another box view having the same column span. Can someone please advise me on how to do this ? Please help.

Unfortunately, there is no built-in drag and drop functionality in Xamarin.Forms just yet. You can still implement it yourself using PanGestureRecognizer.
You can add gesture recognizer to your view, for example Label, like this:
<Label>
<Label.GestureRecognizers>
<PanGestureRecognizer PanUpdated="PanGestureRecognizer_OnPanUpdated" />
</Label.GestureRecognizers>
</Label>
Now in the PanUpdated event handler you can use TranslationX and TranslationY to move a view around.
private double _startTranslationX, _startTranslationY
private void PanGestureRecognizer_OnPanUpdated(object sender,
PanUpdatedEventArgs e)
{
var box = (BoxView) sender;
if (e.StatusType == GestureStatus.Started)
{
_startTranslationX = box.TranslationX;
_startTranslationY = box.TranslationY;
}
else if (e.StatusType == GestureStatus.Running)
{
box.TranslationX = _startTranslationX + e.TotalX;
box.TranslationY = _startTranslationY + e.TotalY;
}
else if (e.StatusType == GestureStatus.Completed)
{
box.TranslationX = _startTranslationX + e.TotalX;
box.TranslationY = _startTranslationY + e.TotalY;
//handle drop here (depending on your requirements)
}
}
To actually implement a drop functionality you will have to manually test where the object is currently located and if dropping is allowed there.

Related

MAUI Image as embedded resouce

I am creating a MAUI project that uses graphic components (buttons) defined in an external DLL.
The images of these buttons are resources embedded in the external DLL that I load in this way:
ImageSource.FromResource (Instance.LOCAL_ASSEMBLY_IMAGEPATH + filename, Instance.LOCAL_ASSEMBLY);
When I run on windows the images are correct, when I run on android the images are randomly placed ...
This is only a display issue because the button instance is right.
Windows example
Android example
XAML top bar
<Shell.TitleView>
<Grid x:Name="ShellViewObject" HorizontalOptions="FillAndExpand" Margin="0" Padding="0" ColumnSpacing="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="48" />
<ColumnDefinition Width="48" />
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
</Grid>
</Shell.TitleView>
Button creation as follows
BadgeButton vo = new SimpleControls.BadgeButton();
vo.StyleId = name;
vo.Padding = new Thickness(0, 0, 0, 0);
vo.Margin = new Thickness(0, 0, 0, 0);
vo.ImageSize = 40;
vo.BadgeImageText = img;
vo.HorizontalOptions = LayoutOptions.CenterAndExpand;
vo.Clicked += CALLING_TOP_BAR_BUTTON_CLICK;
vo.VerticalOptions = LayoutOptions.Center;
return vo;
Badge button XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiSY.SimpleControls.BadgeButton" Padding="0" Margin="0">
<Grid Padding="0" RowSpacing="0" ColumnSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image x:Name="BadgeIconImage" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2"
Margin="3" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
/>
<Frame x:Name="BadgeFrame" Grid.Row="0" Grid.Column="1" CornerRadius="8"
Padding="0" HasShadow="False" BorderColor="Transparent"
VerticalOptions="Fill" HorizontalOptions="Fill"
WidthRequest="35" HeightRequest="35">
<Label x:Name="BadgeTextLabel" FontSize="3" HorizontalOptions="Center" VerticalOptions="Center" />
</Frame>
</Grid>
</ContentView>

Xamarin Carousel GestureRecognizers Not Working

I want to implement a Carousel view swipe gesture recognizer left or right Swipes.
But ONLY tapped event can be recognized ,gesture events cannot be captured(not firing).
What i need is when user swipe left or right according to the swipe event i want to manage dot button opacity accordingly.
I saw some nuget packages already there to achieve this.I prefer not to use nuget packages.
I have tried the tapped event,tapped event is firing but not the gesture event
<CarouselView x:Name="CV" ItemsSource="{Binding People}" HeightRequest="200" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" Margin="10" >
<CarouselView.ItemsLayout>
<GridItemsLayout Orientation="Horizontal" SnapPointsAlignment="Center" SnapPointsType="Mandatory"/>
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<Frame BorderColor="LightGray" CornerRadius="3" HasShadow="False">
<Grid>
<Grid.GestureRecognizers>
<SwipeGestureRecognizer Direction="Left" Swiped="SwipeGestureRecognizer_OnSwiped" />
<SwipeGestureRecognizer Direction="Right" Swiped="SwipeGestureRecognizer_OnSwiped"/>
<SwipeGestureRecognizer Direction="Up" Swiped="SwipeGestureRecognizer_OnSwiped" />
<SwipeGestureRecognizer Direction="Down" Swiped="SwipeGestureRecognizer_OnSwiped"/>
</Grid.GestureRecognizers>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Grid.Column="0" Grid.Row="0" Source="person" VerticalOptions="Start"/>
<StackLayout Grid.Column="1" Grid.Row="1" HorizontalOptions="EndAndExpand" VerticalOptions="EndAndExpand">
<Label Text="{Binding}" FontSize="24" HorizontalOptions="EndAndExpand"/>
<Label Text="Company Address" HorizontalOptions="EndAndExpand"/>
<Label Text="City, State" HorizontalOptions="EndAndExpand"/>
</StackLayout>
</Grid>
</Frame>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
Yes,CarouselView have GestureRecognizers ,for example,
<CarouselView>
<CarouselView.GestureRecognizers>
<SwipeGestureRecognizer Swiped="OnSwiped" />
</CarouselView.GestureRecognizers>
</CarouselView>
method OnSwiped
private void OnSwiped(object sender, SwipedEventArgs e)
{
if (e.Direction == (e.Direction & SwipeDirection.Left))
{
}
}

Listview with ffimageloading loads shrunken image after navigate away from page and back

In my Xamarin Forms app, I have a Syncfusion SfListView with an item template that contains a ffimageloading image control. The list view has an item tapped event that navigates to a details page. Upon navigating back, I have the list rebinding in the page's onappearing method. Sometimes, rather most of the time (not all the time) when you click a list item, navigate to the details page, and come back, the list will load with the item that you clicked, but the image in the row that you clicked is shrunken. I attached a pic. Here's the relevant code
<syncfusion:SfListView x:Name="CountriesListView" ItemTapped="SflistView_ItemTapped"
AutoFitMode="Height" ItemsSource="{ Binding CountryList }" VerticalOptions="FillAndExpand">
<syncfusion:SfListView.HeaderTemplate>
<DataTemplate>
......
</DataTemplate>
</syncfusion:SfListView.HeaderTemplate>
<syncfusion:SfListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame OutlineColor="Gray" Padding="2" HasShadow="True" HeightRequest="200">
<Grid RowSpacing="5" ColumnSpacing="0" Margin="10,5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="AUTO" />
</Grid.RowDefinitions>
<!--<Image Source="{Binding MainIMageURL}" Aspect="Fill" Grid.RowSpan="2">
</Image>-->
<ffimageloading:CachedImage Aspect="Fill" Grid.RowSpan="2"
FadeAnimationEnabled="true"
Source="{ Binding MainIMageURL }" />
<Image Source="{Binding ShadowOverlay}" Grid.RowSpan="2" Aspect="Fill" VerticalOptions="End" HorizontalOptions="Fill" />
<Grid Margin="10,10,10,0" RowSpacing="10" ColumnSpacing="10" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="AUTO" />
<!--<RowDefinition Height="25" />-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="AUTO" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" Grid.Row="0" Grid.ColumnSpan="3" HorizontalOptions="Center"
VerticalOptions="End"
FontSize="25" LineBreakMode="NoWrap" TextColor="#FFFFFF">
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String">
<On Platform="iOS" Value="HelveticaNeue-Bold" />
<On Platform="Android" Value="sans-serif-medium" />
</OnPlatform>
</Label.FontFamily>
</Label>
</Grid>
</Grid>
</Frame>
</ViewCell>
</DataTemplate>
</syncfusion:SfListView.ItemTemplate>
</syncfusion:SfListView>
protected override void OnAppearing()
{
BindData();
}
private async Task BindData()
{
await LoadCountries();
}
private async Task LoadCountries()
{
try
{
CountriesListView.IsBusy = true;
Console.WriteLine("Getting countries");
await vm.RefreshDataAsync();
Console.WriteLine("Countries retrieved");
}
catch (Exception ex)
{
.......
}
finally
{
CountriesListView.IsBusy = false;
}
}

ListView Item doesn't expand-collapse height in Xamarin Forms

I have a List View. In ListView I have ListViewCell. ListViewCell have expand-Collapse functionality. There are few problems in expand collapse behaviours.
1- If I expand first item, it works fine. But If I expand second item first and expand first item, it first item goes behind. See Case-1 in screen shot.
2- If I click on list view item, it show in gray color for a second. I want to stop this. It should not change and color when user click on any cell. Case-2
3- If I expand first item and collapse it again. It collapse but it keep white space between second and first item.
I have noticed this behavior. Above issue resolve if I scroll down and up. Well, in ideal case, user doesn't scroll up and down after every operation :D
Note: I have Entry, DatePicker and Buttons in ListViewCell. User must be able to input in it.
Here is my code. I have also attached screen shot. Please suggest
Main Page List View
<ListView x:Name="WorkHistoryListView"
ItemsSource="{Binding WorkHistoryList}"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
SeparatorVisibility="None"
ItemTapped="OnListViewItemTapped"
Margin="10"
HasUnevenRows = "true"
IsPullToRefreshEnabled="False">
<ListView.ItemTemplate>
<DataTemplate>
<localview:WorkHistoryViewCell />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
WorkHistoryViewCell.xaml
<StackLayout Margin="0" Padding="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<!-- Blue heading-->
<StackLayout Margin="0" Padding="0" Grid.Row="0" BackgroundColor="#367fa9">
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
Padding="15" RowSpacing="10" Margin="0" BackgroundColor="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Label Text="{Binding Name}" HorizontalOptions="Center" Grid.Column="0" Grid.Row="0"/>
<Label Text="{Binding Date}" HorizontalOptions="Center" Grid.Column="1" Grid.Row="1"/>
<Label Text="+" HorizontalOptions="End" VerticalOptions="Center" Grid.Column="2" x:Name="LabelCollapse" Grid.Row="0" Grid.RowSpan="2" FontFamily="Roboto">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="LabelOpenCommand"/>
</Label.GestureRecognizers>
</Label>
</Grid>
</StackLayout>
<StackLayout Margin="0" Padding="0" Grid.Row="1" x:Name="FrameVisible">
<Frame Margin="0" Padding="0" HorizontalOptions="FillAndExpand" BackgroundColor="White" OutlineColor="Gray">
<StackLayout Margin="0" VerticalOptions="Fill" Padding="20" IsVisible="{Binding IsWeekly}">
<Grid>
<Grid.Resources>
<ResourceDictionary>
<local:InvertBooleanConverter x:Key="invertBooleanConverter" />
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontFamily" Value="Roboto"/>
<Setter Property="TextColor" Value="White"/>
</Style>
</ResourceDictionary>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="125"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Image Source="EditLog.png" Grid.Column="1" Grid.Row="0" HorizontalOptions="End" VerticalOptions="Center"
HeightRequest="24">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnImageViewItemTapped"/>
</Image.GestureRecognizers>
</Image>
<Label Text="Date" Grid.Column="0" Grid.Row="0" Style="{StaticResource LabelStyle}"
TextColor="Black" FontFamily="Roboto" Margin="0" />
<local:ExtendedDatePicker TextColor="LightGray" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1"
IsEnabled="False" Date="{Binding Date}" BackgroundColor="White">
<DatePicker.Format>dd/MM/yyyy</DatePicker.Format>
</local:ExtendedDatePicker>
<Label Text="Pay" Grid.Column="0" Grid.Row="2" Style="{StaticResource LabelStyle}"
TextColor="Black" FontFamily="Roboto" Margin="0,10,0,0" />
<local:CustomEntry Grid.Column="0" Grid.Row="3" Margin="0,10,0,0" WidthRequest="150" Text="{Binding Pay}"
Style="{StaticResource LabelStyle}" TextColor="Black" HorizontalOptions="EndAndExpand" VerticalOptions="FillAndExpand"/>
<Button Text="Submit" BorderRadius="18" TextColor="White" Command="{Binding SubmitWeeklyCommand}" Grid.Column="0" Grid.Row="4" FontFamily="Roboto"/>
</Grid>
</StackLayout>
</Frame>
</StackLayout>
</Grid>
</StackLayout>
WorkHistoryViewCell.xaml.cs //Command to expand collapse
private void LabelOpenCommand(object sender,TappedEventArgs e)
{
if (LabelCollapse.Text == "+")
{
FrameVisible.IsVisible = false;
LabelCollapse.Text = "-";
FrameVisible.IsVisible = true;
}
else
{
FrameVisible.IsVisible = true;
LabelCollapse.Text = "+";
FrameVisible.IsVisible = false;
}
}
Screenshot
It happens 'cause the cell's height is calculated only on the first rendering. After that, the changes affect just the inner layout view.
Try call ForceUpdateSize(); at the end of your current TappedCommand's logic. It'll force the entire cell to recalculate its bounds.
The code should look like:
private void LabelOpenCommand(object sender,TappedEventArgs e)
{
if (LabelCollapse.Text == "+")
{
FrameVisible.IsVisible = false;
LabelCollapse.Text = "-";
FrameVisible.IsVisible = true;
}
else
{
FrameVisible.IsVisible = true;
LabelCollapse.Text = "+";
FrameVisible.IsVisible = false;
}
ForceUpdateSize
}
I hope it helps.

Embed image not showing in Xamarin.Forms

I have two images in 'Images' folder. Trying to load these images in page but image not showing on page. It does not produce any error in debug. I am checking in Xamarin live player android device.
ImageResourceExtension.cs
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Xamarin.Forms.Internals;
namespace Buffting
{
// You exclude the 'Extension' suffix when using in Xaml markup
[Preserve(AllMembers = true)]
[ContentProperty(nameof(Source))]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
return null;
// Do your translation lookup here, using whatever method you require
var imageSource = ImageSource.FromResource(Source);
return imageSource;
}
}
}
BeautySalon.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"
xmlns:local="clr-namespace:Buffting;assembly=Buffting"
x:Class="Buffting.Home.BeautySalon"
Title="Beauty Salon">
<ContentPage.Content>
<ListView x:Name="SalonList" RowHeight="370">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame Margin="5,5,5,-5" OutlineColor="Blue" HasShadow="true">
<Grid>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.ColumnSpan="2" HeightRequest="200" Source="{ Binding SalonImage}" VerticalOptions="Fill" Aspect="AspectFill" />
</Grid>
<Grid Grid.Row="1" Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="1" Grid.Column="0" Margin="0, 40, 0, 0" Text="{ Binding SalonName }" FontSize="Large" TextColor="White" />
<Image Grid.Row="1" Grid.Column="1" x:Name="Star" Source="{local:ImageResource Buffting.Images.star_outline.png}" />
</Grid>
<Grid Grid.Row="2" Padding="0, 0, 10, 0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Location:" FontAttributes="Bold" FontSize="Small" TextColor="Black" />
<Label Grid.Row="0" Grid.Column="1" Text="{ Binding Location}" />
<Label Grid.Row="1" Grid.Column="0" Text="Full Address:" FontAttributes="Bold" FontSize="Small" TextColor="Black" />
<Label Grid.Row="1" Grid.Column="1" Text="{ Binding Address}" />
<Label Grid.Row="2" Grid.Column="0" Text="Phone:" FontAttributes="Bold" FontSize="Small" TextColor="Black" />
<Label Grid.Row="2" Grid.Column="1" Text="{ Binding Phone}" />
<Label Grid.Row="3" Grid.Column="0" Text="Opening Time:" FontAttributes="Bold" FontSize="Small" TextColor="Black" />
<Label Grid.Row="3" Grid.Column="1" Text="{ Binding OpeningTime}" />
</Grid>
</Grid>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
I am using this code but image is not loading. I ma new in Xamarin please guide me.
It's wrong, the images are placed within each native project. For Xamarin.Forms you should place the images in the Drawables folders.
If your project is android and ios ,you finally have two images : one in iosproject/Resources and one in AndroidProject/Resources/Drawab.
see Images Doc
If you want to load your images from the shared assembly. Ensure images are set as "EmbeddedResource" (Right Click: Properties, Build Action).
You have too add each image in there native Projects. here is a sample of how it should look like:
You can use the following plugin to generate your images for iOS:
Plugin: Link
For Android:
For IOS :
You can now reference your images in your xaml :
<Image Source="star_outline.png" />
<Image Source="star_selected.png" />
UPDATE:
In your xaml change:
<Image Grid.Row="1" Grid.Column="1" x:Name="Star" Source="{local:ImageResource Buffting.Images.star_outline.png}" />
with :
<Image Grid.Row="1" Grid.Column="1" x:Name="Star" Source="star_outline.png" />
The image should appear , This answers your main question. I'm not sure why your using IMarkupExtension , your not even calling it in the xaml
I had this same problem and found the answer in this thread. Embedded images not showing
When using the ImageResourceExtension the Source property should be prefixed with the Assembly Na

Resources