I'm trying to setup a XAML form definition which shows a WebView but which has a Floating Action Button over the bottom right.
If I use an AbsoluteLayout, the FAB appears correctly over the WebView. However, due to the Height/WidthRequest of the Webview, it is displayed at full size - the text disappears off the right side and doesn't wrap, so the page doesn't scroll.
<ContentPage ...snip... Title="Document">
<StackLayout Padding="5,5,5,5" HorizontalOptions="FillAndExpand" Orientation="Vertical">
<WebView x:Name="webViewDocument" WidthRequest="1000" HeightRequest="1000" />
<Label Text="{Binding UpdatedWhen, StringFormat='Last Updated: {0:dd MMM yyyy HH:mm}'}"
VerticalTextAlignment="Center" HorizontalTextAlignment="End" FontSize="Small" />
<customControls:ImageButton x:Name="fab"
Source="{markupExtensions:PlatformImage SourceImage='IconFAB'}"
Command="{Binding AddCommand}"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="0.95,0.975,-1,-1"
Margin="10" />
</StackLayout>
</ContentPage>
If I use a StackLayout, the WebView sizes and scrolls correctly, however the FAB occupies a full width strip at the bottom of the screen and the text does not appear behind it - the WebView stops above it.
I've spent the last hour and a half trying every combination of nested Layout I can think of to solve this and just can't get it right - can some kind layout genius out there please tell me how I can solve this.
Thanks
Use a Grid and do not indicate rows or columns.
Something like this:
<Grid Padding="5,5,5,5"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<WebView x:Name="webViewDocument"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand" />
<Label Text="{Binding UpdatedWhen, StringFormat='Last Updated: {0:dd MMM yyyy HH:mm}'}"
VerticalOptions="End"
HorizontalOptions="Center"
HorizontalTextAlignment="End"
FontSize="Small" />
<customControls:ImageButton x:Name="fab"
Source="{markupExtensions:PlatformImage SourceImage='IconFAB'}"
Command="{Binding AddCommand}"
VerticalOptions="End"
HorizontalOptions="End"
Margin="10" />
</Grid>
This should work for you.
Related
I have used Rg.Plugins.Popup.
I have aligned close button which is aligned at top right corner 50% outside the window from right and top side as shown in below image.
Now it is showing as per expected design but issue is when I tap on it, only inward part of close button get clicked and outward part is not clickable. So not able to close popup till the time we click that inward part of Close button.
I am sharing my code for more idea.
<ScrollView Orientation="Horizontal">
<AbsoluteLayout HorizontalOptions="Center"
VerticalOptions="Center"
Padding="0,0,0,0"
Margin="0,0,0,0"
Opacity="1">
<Frame AbsoluteLayout.LayoutBounds="0,0,1,1"
IsClippedToBounds="True"
AbsoluteLayout.LayoutFlags="All"
HasShadow="False"
x:Name="outframe"
Margin="0"
CornerRadius="15"
Padding="0"
OutlineColor="#ffffff"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal"
x:Name="stkVideo"
Padding="0">
<Image x:Name="ximage"
Aspect="AspectFill"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
BackgroundColor="#4A4541" />
<video:VideoPlayer x:Name="trainingPlayer"
DisplayControls="True"
FillMode="ResizeAspectFill"
FlowDirection="LeftToRight"
Volume="100"
Grid.Row="0"
IsVisible="false">
</video:VideoPlayer>
</StackLayout>
</Frame>
<ContentView AbsoluteLayout.LayoutBounds="0.50, 0.50, -1, -1"
AbsoluteLayout.LayoutFlags="PositionProportional">
<Image Source="Play.png"
HeightRequest="{OnIdiom Phone=70,Tablet=85}"
WidthRequest="{OnIdiom Phone=70,Tablet=85}"
Aspect="AspectFit"
VerticalOptions="Center"
HorizontalOptions="Center"
x:Name="icnplay" />
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_1" />
</ContentView.GestureRecognizers>
</ContentView>
<ContentView AbsoluteLayout.LayoutBounds="1.04, -0.09, -1, -1"
AbsoluteLayout.LayoutFlags="PositionProportional" >
<Image Source="close.png"
HeightRequest="{OnIdiom Phone=35,Tablet=45}"
WidthRequest="{OnIdiom Phone=35,Tablet=45}"
Aspect="AspectFit">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Image.GestureRecognizers>
</Image>
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</ContentView.GestureRecognizers>
</ContentView>
</AbsoluteLayout>
</ScrollView>
What code changes do I need to do so that popup get close when user will click on Close button part which is outside the window as well?
The issue is the close button lies outside the bounds of the <AbsoluteLayout>. One solution involves a few steps:
Make the AbsoluteLayout larger by some amount
Add a margin to the video player Frame equal to how much larger the AbsoluteLayout was made
Update the position of the close button to remain in the top right corner of the video player Frame
Now the close button is contained within the AbsoluteLayout and the entire close button area will receive and raise events for taps/clicks.
I guess that you want to achieve this:
Clicking outside the yellow frame will close the everything.
The red part has a GestureRecognizer
You can achieve this by using a Grid or a Absolute layout, these views allow you to "stack" or add layers to the UI.
Code example:
<AbsoluteLayout
BackgroundColor="Green"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout AbsoluteLayout.LayoutBounds="1,1,1,1" AbsoluteLayout.LayoutFlags="All">
<Button Clicked="Button_Clicked" Text="Coso" />
<Button Clicked="Button_Clicked_1" Text="Show popup" />
</StackLayout>
<Frame
x:Name="closeFrame"
AbsoluteLayout.LayoutBounds="1,1,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Red"
IsVisible="false">
<Frame.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Tapped="TapGestureRecognizer_Tapped" />
</Frame.GestureRecognizers>
</Grid>
<Frame
x:Name="popupGrid"
AbsoluteLayout.LayoutBounds="0.5,0.5,0.5,0.5"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Yellow"
IsVisible="false">
<Label Text="Close ouside this" TextColor="Black" />
</Frame>
</AbsoluteLayout>
In code behind you turn the visibile on/off of the element
I have an AbsoluteLayout on a view in my Xamarin.Forms app, with 3 buttons in it. After another control is added programmatically, it covers the buttons. I cannot figure out how I can make the buttons to be always in front.
<ContentPage.Content>
<AbsoluteLayout x:Name="Container" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Button
Style="{StaticResource CallButtonStyle}"
...
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds=".85,.02"
Text="{Binding CameraSwitchIcon}" />
<Button
...
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds=".15,.95,80,80"
Text="{Binding VideoToggleIcon}" />
<Button
...
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds=".85,.95,80,80"
Text="{Binding AudioToggleIcon}" />
</AbsoluteLayout>
</ContentPage.Content>
all XF Layouts have RaiseChild() and LowerChild() methods you can use to adjust the Z index
I work on a Xamarin.Forms app that will contain a page with 2 CollectionView items:
an horizontal CollectionView that will display events
a vertical CollectionView that will display posts
I would like that the first list is progressively hidden as soon as the user starts to scroll on the second list.
We can found this behaviour on a sample from Syncfusion: but they use a SfRotator as control for the horizontal list:
I've tried to reproduce the same behaviour on my page, but it doesn't work as expected. My horizontal list is not hidden until I scroll vertically on this first list itself. If I scroll on the second vertical list, the first list is still visible:
My XAML looks like this:
<ContentPage.Content>
<RefreshView x:DataType="vm:NewsViewModel"
IsRefreshing="{Binding IsRefreshing}"
Command="{Binding RefreshCommand}">
<ScrollView>
<StackLayout Padding="16" Spacing="16">
<CollectionView x:Name="EventsListView"
ItemsSource="{Binding Events}"
HeightRequest="250"
VerticalScrollBarVisibility="Never"
SelectionMode="None">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal"
ItemSpacing="20" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<ctrl:ShadowFrame BackgroundColor="Red">
<StackLayout x:DataType="model:Event" >
<Label Text="{Binding Name}" />
<Image Source="{Binding Image}" />
</StackLayout>
</ctrl:ShadowFrame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CollectionView x:Name="NewsListView"
ItemsSource="{Binding News}"
VerticalScrollBarVisibility="Never"
SelectionMode="None">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical"
ItemSpacing="20" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<ctrl:ShadowFrame>
<StackLayout x:DataType="model:News">
<Label Text="{Binding Description}" />
<Label Text="{Binding Date}" />
<Image Source="{Binding Image}" />
</StackLayout>
</ctrl:ShadowFrame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ScrollView>
</RefreshView>
</ContentPage.Content>
=> Is there a way to achieve this?
Quick reminder that you Shouldn't use Scrollable Elements inside other Scrollable Element, it usually breaks how both work, Quoting:
Xamarin doesn't recommend using the ListView, WebView, or ScrollView
inside a ScrollView. Microsoft Xamarin.Forms Official Documentation
says that ScrollViews should not be nested. In addition, ScrollViews
should not be nested with other controls that provide scrolling, like
ListView and WebView.
And this is what happening:
The ScrollView isn't actually scrolling, the Vertical CollectionView is the one giving the Illusion that the page is scrolling, meaning that the Horizontal one is always on top.
How to fix it?
To fix this, you should remove the Vertical CollectionView and use some kind of Repeater View, this Post will guide you on how to achieve it.
How To develop this type of Design(I have attached image below)
Supposedly you are referring to the bars, not the overall layout, but it's not 100% clear from your question. While there are other possibilities to display the bars, I achieved quite a satisfying result by nesting an AbsoluteLayout in a frame. See the following example for one of the bars on the right
<Frame HasShadow="False" HeightRequest="20" CornerRadius="5" HorizontalOptions="Fill" Padding="0" BackgroundColor="Silver" IsClippedToBounds="True">
<AbsoluteLayout>
<ContentView AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,.33,1"
BackgroundColor="CadetBlue">
<Label Text="33%"
FontSize="Small"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="White"
FontAttributes="Bold" />
</ContentView>
</AbsoluteLayout>
</Frame>
The bar itself is wrapped by a Frame to get the rounded corners (see the CornerRadius property). Setting IsClippedToBounds to true is necessary, because otherwise the children won't be clipped and the rounded corners do not show.
Within the Frame there is the AbsoluteLayout the actual bars are placed in. And within, I added the dark-greenish bar as a ContentView (to be able to add a label with the percentage).
Please see the following code for one of the green/red bars. Basically it's the same, but I added two sub-bars within the absolute layout
<Frame HasShadow="False" HeightRequest="20" CornerRadius="5" HorizontalOptions="Fill" Padding="0" BackgroundColor="Silver" IsClippedToBounds="True">
<AbsoluteLayout>
<ContentView AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,.25,1"
BackgroundColor="LimeGreen">
<Label Text="25%"
FontSize="Small"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="White"
FontAttributes="Bold" />
</ContentView>
<ContentView AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="1,0,.75,1"
BackgroundColor="Red">
<Label Text="75%"
FontSize="Small"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="White"
FontAttributes="Bold" />
</ContentView>
</AbsoluteLayout>
</Frame>
Generalization
It'd be useful to extract a re-usable component. I will show for the simpler bar. Transferring the solution to the more complex one should be easy, though.
Code behind
In the code behind the following properties have to be added
public Rectangle FirstBarBounds => new Rectangle(0, 0, BarValue, 1);
public double BarValue
{
get => this._barValue;
set
{
if (this._barValue == value)
{
return;
}
this._barValue = value;
this.OnPropertyChanged();
}
}
(Adding a BindableProperty for BarValue could be useful, too, but admittedly I was too lazy.)
The properties can be bound to from XAML
<Frame ...>
<AbsoluteLayout>
<ContentView AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="{Binding FirstBarBounds}"
BackgroundColor="CadetBlue" >
<Label Text="{Binding FirstBarValue, StringFormat='{}{0:P0}'}"
FontSize="Small"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="White"
FontAttributes="Bold" />
</ContentView>
</AbsoluteLayout>
</Frame>
The LayoutBounds of the ContentView is bound to BarBounds (which in turn uses BarValue to determine the bounds of the bar) and the text is bound to BarValue. Since BarValue is a double, the value is formatted to a percentage by StringFormat='{}{0:P0}'.
Screenshot
Please see the following screen shot on how the bars are rendered on an Android device (Emulator).
I would like to add drop shadow to a Label. This label is overlapped in the Page, like an always visible control that opens a filtering page.
Please find a gif attached with my screen:
Here's my XAML:
<!-- **** Filter button **** -->
<Label
Margin="0,0,10,10"
WidthRequest="50"
HeightRequest="50"
HorizontalOptions="End"
VerticalOptions="End"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
FontSize="30"
Style="{DynamicResource FilterAction}"
Text=""
BackgroundColor="{StaticResource ComplementColor}"
FontFamily="{x:Static artina:FontAwesome.FontName}"
TextColor="White">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding btn_open_filter_businesses_click}" />
</Label.GestureRecognizers>
</Label>
<templates:Badge
BadgeText="{Binding number_of_filters_selected}"
BadgeTextColor="White"
BadgeBackgroundColor="#1DBDFF"
HorizontalOptions="End"
VerticalOptions="End"
TranslationX="-4"
TranslationY="-4"
IsVisible="{Binding number_of_filters_selected, Converter={StaticResource filterVis}"
x:Name="filtersCountBagde">
<templates:Badge.GestureRecognizers>
<TapGestureRecognizer Command="{Binding btn_open_filter_businesses_click}" />
</templates:Badge.GestureRecognizers>
</templates:Badge>
I would like something like Gmail, find the example below:
Any help would be appreciated.
You can use Xamarin Effects to achieve a shadow on your button. There is a code sample that you can download here which should get you started:
Shadow Effect
It will involve creating platform-specific implementations for your shadow.
You could also try the idea put forward in this similar question.