I'm using this code to create something looking like a button:
<Grid Grid.Column="0" ColumnSpacing="0" Margin="0,0,10,0">
<Frame Grid.Column="0" CornerRadius="5" OutlineColor="Black">
<Label x:Name="faveIconLabel" Style="{StaticResource mediumIcon}" Margin="0,2,0,0" HorizontalOptions="Fill" FontFamily="FontAwesome" VerticalOptions="Center" VerticalTextAlignment="Center" />
</Frame>
<Frame Grid.Column="1" CornerRadius="5" OutlineColor="Black">
<Label x:Name="hiddenIconLabel" Style="{StaticResource mediumIcon}" Margin="0,2,0,0" HorizontalOptions="Fill" FontFamily="FontAwesome" VerticalOptions="Center" VerticalTextAlignment="Center" />
</Frame>
</Grid>
Is there a way that I can simulate the click event to make it look like something actually got pressed when they click on the label?
If you don't want to use a custom renderer, a simple way would be to change the background color in the handleClick, and then revert it back to its original color after a few milliseconds. For example,
private void handleClick(object sender, EventArgs e) {
var view = (View)sender;
view.BackgroundColor = Color.FromHex("#DD000000");
Device.StartTimer(
TimeSpan.FromMilliseconds(100),
() =>
{
// Revert it back to the original color, whatever it may be.
Device.BeginInvokeOnMainThread(() =>
{
view.BackgroundColor = Color.Transparent;
});
return false; // return false to prevent the timer from calling again
});
}
You can add a TapGestureRecognizer to virtually any VisualElement, including Label, Image, etc.
faveIconLabel.GestureRecognizers.Add(new TapGestureRecognizer((view) => OnLabelClicked()));
Related
Sorry for my perhaps silly question. As I am new to Xamarin Forms, I need some basic hints:
I need a window ("secondary window") sliding from left into my main window. In this window, a list of items (with images and text) should be displayed and this window should cover only 1/4 to 1/2 of my main window. Dragging an item from this secondary window to the main window should start some action with this item on main window.
What type of view is best for this purpose and what are the keywords to search for? This looks like a flyout menu but how can I create such view from my main menu or clicking on a button?
I am using C# and Visual Studio 2022
Maybe like this , one page (ContentPage) with a Grid in a Grid.
The Grid MainContentGrid is sliding and the MenuContainer Grid is showing.
Then use Drag and Drop to put the Like Image in MenuContainer on the Drophere Image in MainContentGrid, then an event.
The MainContentGrid is using TranslateTo to slide away and back.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/gestures/drag-and-drop
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/animation/simple
The MainPage
<Grid>
<!-- Menu Grid -->
<Grid x:Name="MenuContainer" BackgroundColor="Gray">
<StackLayout
Margin="24,100,0,0"
HorizontalOptions="Start"
Spacing="30">
<Label
FontSize="28"
HorizontalOptions="Center"
Text="MENU Options" />
<Image
HeightRequest="50"
HorizontalOptions="Center"
Source="imglike.png"
VerticalOptions="Center"
WidthRequest="50">
<Image.Clip>
<EllipseGeometry
Center="25,25"
RadiusX="25"
RadiusY="25" />
</Image.Clip>
<Image.GestureRecognizers>
<DragGestureRecognizer />
</Image.GestureRecognizers>
</Image>
</StackLayout>
</Grid>
<!-- Main Content -->
<Grid
x:Name="MainContentGrid"
Padding="24,5,24,0"
BackgroundColor="Red"
ColumnDefinitions="*,Auto"
RowDefinitions="Auto,*">
<!-- Header Text -->
<StackLayout
Grid.Row="0"
Grid.Column="1"
Spacing="4"
VerticalOptions="Center">
<Label Text="Slide Menu" />
</StackLayout>
<!-- Hamburger Pic -->
<Frame
Grid.Row="0"
Grid.Column="0"
BackgroundColor="Red"
BorderColor="Gray"
CornerRadius="28"
HeightRequest="56"
HorizontalOptions="Start"
VerticalOptions="Center"
WidthRequest="56">
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="ProfilePic_Clicked" />
</Frame.GestureRecognizers>
<Image
HeightRequest="50"
HorizontalOptions="Center"
Source="icnhamburger.png"
VerticalOptions="Center"
WidthRequest="50">
<Image.Clip>
<EllipseGeometry
Center="25,25"
RadiusX="25"
RadiusY="25" />
</Image.Clip>
</Image>
</Frame>
<Frame
Grid.Row="1"
Grid.Column="0"
BackgroundColor="Red"
BorderColor="Gray"
CornerRadius="28"
HeightRequest="56"
HorizontalOptions="Start"
VerticalOptions="Center"
WidthRequest="56">
<Image
Aspect="AspectFill"
HeightRequest="50"
HorizontalOptions="Center"
Source="drop.png"
VerticalOptions="Center"
WidthRequest="50">
<Image.GestureRecognizers>
<DropGestureRecognizer Drop="DropGestureRecognizer_Drop" />
</Image.GestureRecognizers>
</Image>
</Frame>
</Grid>
</Grid>
MainPage.cs
public partial class MainPage : ContentPage
{
private const uint AnimationDuration = 500u;
public MainPage()
{
InitializeComponent();
}
private async Task CloseMenu()
{
//Close the menu and bring back back the main content
_ = MainContentGrid.FadeTo(1, AnimationDuration);
_ = MainContentGrid.ScaleTo(1, AnimationDuration);
await MainContentGrid.TranslateTo(0, 0, AnimationDuration, Easing.CubicIn);
}
async void ProfilePic_Clicked(System.Object sender, System.EventArgs e)
{
// Reveal our menu and move the main content out of the view
_ = MainContentGrid.TranslateTo(this.Width * 0.5, this.Height * 0, AnimationDuration, Easing.CubicIn);
await MainContentGrid.ScaleTo(0.8, AnimationDuration);
_ = MainContentGrid.FadeTo(0.8, AnimationDuration);
}
private async void DropGestureRecognizer_Drop(object sender, DropEventArgs e)
{
await CloseMenu();
await DisplayAlert("Job", "I have a job for you to do !", "OK");
}
}
This is how it looks
hello i want to pass the Label with the button in xaml
its a list view and each row has her own Label and i want update each row by the label
<Label Grid.Column="2"
Grid.Row="1"
Text="{Binding Label}"
FontSize="20"
TextColor="Black"
Margin="0,10,0,0"
FontFamily="{StaticResource font}"
HorizontalOptions="Start"
VerticalOptions="Center"/>
<ImageButton Grid.Column="2"
Grid.Row="0"
HorizontalOptions="End"
VerticalOptions="End"
Source="plus.png"
Margin="9"
clicked ="update"
BackgroundColor="Transparent"/>
and the function in the class
public void update (object sender , EventArgs e)
{
update by the Label
}
i know that's there is something with commands but i'm beginner and i don't know how to use it i tried this and i didn't work.
Command="{Binding Path=BindingContext.UpdateCommand, Source={x:Reference Name=listViewEvent}}"
CommandParameter="{Binding Label}"
and the function is this
UpdateCommand = new Command<string>(async (args) => {
String Label = args as string;
DisplayAlert("update", "update", "OK");
_ = Navigation.PushAsync(new AddReminder(Label));
});
and the alert didn't show
please i need help
you don't need to "pass" the Label
<ImageButton Grid.Column="2" Cilcked="update" ... />
protected void update(object sender, EventArgs a)
{
var btn = (ImageButton)sender;
// MyClassName should be the name of your model class
// this will get you the object referenced by the selected row
var item = (MyClassName)btn.BindingContext;
// then you can reference any property of item
// ie, item.Label, etc
}
<Label x:Name="myLabel"
Grid.Column="2"
Grid.Row="1"
Text="{Binding Label}"
FontSize="20"
TextColor="Black"
Margin="0,10,0,0"
FontFamily="{StaticResource font}"
HorizontalOptions="Start"
VerticalOptions="Center"/>
<ImageButton Grid.Column="2"
Grid.Row="0"
HorizontalOptions="End"
VerticalOptions="End"
Source="plus.png"
Margin="9"
clicked ="update"
BackgroundColor="Transparent"
CommandParameter={x:Reference myLabel}/>
And then in code behind you can get the label
protected void update(object sender, EventArgs a)
{
var btn = (ImageButton)sender;
var label = btn.CommandParameter as Xamarin.Forms.Label;
}
<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.
I want that when my image is loading then GIF image should be displayed but when image loading is completed then GIF should disappear.
But I don't know how to do. Please tell me the step by step procedure.
imageWave1.IsVisible = !imageWave1.IsLoading;
stackBehindImage.IsVisible = true;
imageWave1.IsVisible = true;
stackFrontImage.IsVisible = false;
Second Image is displaying where GIF should be displayed first then until the second image is Loading
<StackLayout x:Name="stackFrontImage" Padding="0" HeightRequest="100" Spacing="0" Margin="10" IsVisible="True">
<ffimageloading:SvgCachedImage HeightRequest="100"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
Aspect="AspectFill"
x:Name="imageWave"
Source="outlet.gif"
IsVisible="True"
Margin="0"/>
</StackLayout>
<StackLayout x:Name="stackBehindImage" HeightRequest="100" Padding="0" Spacing="0" Margin="10" IsVisible="False">
<ffimageloading:SvgCachedImage x:Name="imageWave1"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
Aspect="AspectFill"
HeightRequest="50"
Margin="0"/>
This is my XAML code.
I have written all these things but my both images(GIF and PNG) displaying together. please correct me what I am doing wrong here.
//This should be displayed when my imagewave1.source is Loading.
<StackLayout x:Name="stackFrontImage" Padding="0" HeightRequest="100" Spacing="0" Margin="10" IsVisible="True">
<ffimageloading:SvgCachedImage HeightRequest="100"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
Aspect="AspectFill"
x:Name="imageWave"
Source="outlet.gif"
IsVisible="True"
Margin="0"
LoadingPlaceholder="imageWave1"
Finish="ImageWave_Finish"
DownloadStarted="ImageWave_DownloadStarted"/>
</StackLayout>
//This Should be displayed after loading itself and then GIF should disappear.
<StackLayout x:Name="stackBehindImage" HeightRequest="100" Padding="0" Spacing="0" Margin="10" IsVisible="False">
<ffimageloading:SvgCachedImage x:Name="imageWave1"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
Aspect="AspectFill"
HeightRequest="100"
Margin="0"
Source="http://192.168.0.110/repos/xformsexperimental/RestApiTrain/images/mcdonalds.png"
LoadingDelay="5"/>
private void ImageWave_Finish(object sender, FFImageLoading.Forms.CachedImageEvents.FinishEventArgs e)
{
stackBehindImage.IsVisible = true;
}
private void ImageWave_DownloadStarted(object sender, FFImageLoading.Forms.CachedImageEvents.DownloadStartedEventArgs e)
{
stackBehindImage.IsVisible = false;
}
Here is the screenshot kindly check.
There is an property called LoadingPlaceholder you can use during the loading time of the image.
There are two events called DownloadStarted and Finish Occurs before/after every image loading. You can use these two events to control the visible ability of your second image.
For example:
<ffimageloadingsvg:SvgCachedImage HeightRequest="100"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
Aspect="AspectFill"
x:Name="imageWave"
Source="outlet.gif"
IsVisible="True"
Margin="0"
LoadingPlaceholder="imageWave1"
Finish="ImageWave_Finish"
DownloadStarted="ImageWave_DownloadStarted"
/>
In code behind:
private void ImageWave_Finish(object sender, FFImageLoading.Forms.CachedImageEvents.FinishEventArgs e)
{
stackFrontImage.IsVisible = false;
}
private void ImageWave_DownloadStarted(object sender, FFImageLoading.Forms.CachedImageEvents.DownloadStartedEventArgs e)
{
stackFrontImage.IsVisible = true;
}
You should use like this:
<ffimageloading:CachedImage HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="300" HeightRequest="300"
DownsampleToViewSize="true"
LoadingPlaceholder = "loading.png"
Source = "http://loremflickr.com/600/600/nature?filename=simple.jpg">
</ffimageloading:CachedImage>
In this LoadingPlaceholder is what you can show the loading image, once the Source image is loaded it will automatically disappear.
try this for loading indicator
<Image x:Name="img" Aspect="AspectFill" />
<ActivityIndicator BindingContext="{x:Reference img}" IsRunning="{Binding IsLoading}" />
I wanted to add some effects to the StackLayout GestureRecognizers so the user know they have selected the button but I don't see a way to do it? I have tried to change the BackgroundColor for the StackLayout but that is not working.
Can I change the BackgroundColor or is there a long hold event I can use ?
xaml code
<StackLayout VerticalOptions="Center"
x:Name="slpatient"
Grid.Row="4"
BackgroundColor="#8cb8e1"
Orientation="Horizontal">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Tapped="Button_Clicked" />
</StackLayout.GestureRecognizers>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="user_34.png"
Grid.Column="1"
VerticalOptions="Center" />
<Label Text="Click me to change the BackgroundColor!"
Grid.Column="2"
TextColor="White"
LineBreakMode="WordWrap"
VerticalOptions="FillAndExpand"
VerticalTextAlignment="Center"/>
</Grid>
</StackLayout>
cs code
private void Button_Clicked_Clicked(object sender, System.EventArgs e)
{
slpatient.BackgroundColor = Color.Black;
var masterDetailPage = Application.Current.MainPage as MasterDetailPage;
masterDetailPage.Detail = new NavigationPage((new SearchPage("DrugName")));
}
The change color functionality is likely happening on a non-UI thread. So you could potentially enclose it in Device.BeginInvokeOnMainThread so it gets called in the UI thread, as shown:
Device.BeginInvokeOnMainThread(() =>
{
slpatient.BackgroundColor = Color.Black;
});
To answer your second question, yes you can add a timer too:
private void Button_Clicked_Clicked(object sender, System.EventArgs e)
{
slpatient.BackgroundColor = Color.Black;
var masterDetailPage = Application.Current.MainPage as MasterDetailPage;
Device.StartTimer(TimeSpan.FromSeconds(10), () =>
{
masterDetailPage.Detail = new NavigationPage((new SearchPage("DrugName")));
return false; // True = Repeat again, False = Stop the timer
});
}
I have tried to change the BackgroundColor for the StackLayout but that is not working.
If you want to change background color, I suggest you can consider to use Xameffects, you can install xameffects from nuget packages. Changing TouchEffect.Color.
<ContentPage
x:Class="App4.Page21"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xe="clr-namespace:XamEffects;assembly=XamEffects">
<ContentPage.Content>
<StackLayout
xe:TouchEffect.Color="Red"
HorizontalOptions="Center"
VerticalOptions="Center">
<Button
x:Name="btn1"
Clicked="Btn1_Clicked"
HorizontalOptions="Center"
Text="btn1"
VerticalOptions="Center" />
</StackLayout>
</ContentPage.Content>
More detailed info, you can take a look:
https://github.com/mrxten/XamEffects