I am using Rg.Plugins.Popup plugin in my xamarin forms app. It is a nice plugin for modal dialogs. However, I am looking to dismiss the dialog when user scrolls down. (Most dialogs in iOS has this behavior of closing with scrolling down).
XAML inside Popup page.
Option 1
<pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
HasSystemPadding="True"
CloseWhenBackgroundIsClicked="False"
x:Name="MyPage"
x:Class="wQuran.Views.Today.PrayerTimesSettingsPopupPage">
<Frame Style="{DynamicResource PopupFrame}" VerticalOptions="FillAndExpand" IsClippedToBounds="True">
<Grid RowDefinitions="Auto,*" Style="{DynamicResource BaseGrid}">
<BoxView Grid.Row="0" Style="{DynamicResource PopupTitleBoxView}"/>
<Grid Grid.Row="0" ColumnDefinitions="*,30" HeightRequest="40" Padding="10">
<Label Grid.Column="0" Text="{Binding Title}" Style="{DynamicResource PopupTitleLabel}"/>
<ImageButton Grid.Column="1" Style="{DynamicResource DialogCloseImageButton}" Command="{Binding CloseDialogCommand}"/>
</Grid>
</Grid>
</Frame>
</pages:PopupPage>
Option 2.
Updated XAML and added the Frame inside ScrollView
<ScrollView Scrolled="ScrollView_Scrolled">
....
</ScrollView>
private void ScrollView_Scrolled(object sender, Xamarin.Forms.ScrolledEventArgs e)
{
if (e.ScrollY > 100)
{
itemViewModel.CloseDialogCommand.Execute(null);
}
}
In option 1 I don't have the scroll, so the plug in works with default behavior, but I have no way to close the dialog in scroll.
In option 2, I added the frame inside the scrollview to check for Y scroll and dismiss the dialog. The Scrolled event never fires. Additionally, I cannot close the dialog when clicking outside the modal.
After all, my question is how to dismiss the dialog while scrolling down?
After all, my question is how to dismiss the dialog while scrolling down?
I guess that you want to close PopupPage when ScrollView scroll ending. If yes, please take a look the following code:
<pages:PopupPage
x:Class="FormsSample.simplecontrol.Page16"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup">
<StackLayout
Padding="20,0"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
<Frame
Padding="0"
BackgroundColor="CadetBlue"
CornerRadius="10"
HeightRequest="100">
<ScrollView Scrolled="ScrollView_Scrolled">
<StackLayout Padding="10">
<Label
FontSize="20"
HorizontalOptions="Center"
Text="First Popup Page"
TextColor="Black" />
<Label Text="Hello Xamarin Guys" TextColor="Red" />
<Label Text="This is Very Awesome Popup Plugins For Xamarin forms" TextColor="LightBlue" />
<Button Text="Close" TextColor="Black" />
<Image Source="a11.jpg" />
</StackLayout>
</ScrollView>
</Frame>
</StackLayout></pages:PopupPage>
private async void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
ScrollView scrollView = sender as ScrollView;
double scrollingSpace = scrollView.ContentSize.Height - scrollView.Height;
if (scrollingSpace <= e.ScrollY) // Touched bottom
// Do the things you want to do
await PopupNavigation.Instance.PopAsync();
}
Related
I am trying to achieve the effect, cross-platform(ios, android and uwp), as shown in the image below:
Clicking "More" normally would open a page, as normal behaviour for a tab bar item. Not sure how to override that behaviour and reveal the sliding master page instead. To the left of the "More" tab bar item, theres another tab bar item, when clicked it refreshes the data on (or reloads) the MainPage.
SettingsPage.xaml (master page, the sliding settings page)
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyProject.Classes"
xmlns:views="clr-namespace:MyProject.Views"
x:Class="MyProject.Views.SettingsMasterPage"
IconImageSource="menu.png"
Padding="0,40,0,0"
Title="Menu">
<StackLayout>
<ListView x:Name="listView" x:FieldModifier="public">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:MasterPageItem}">
<local:MasterPageItem Title="Settings Link 1" />
<local:MasterPageItem Title="Settings Link 2" />
<local:MasterPageItem Title="Settings Link 3" />
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}" />
<Label Grid.Column="1" Text="{Binding Title}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
MyTabbedPage.xaml
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
xmlns:views="clr-namespace:MyProject.Views;assembly=MyProject"
x:Class="Xamarin.Sigma01.Views.LoggerDetectionTabbedPage"
android:TabbedPage.ToolbarPlacement="Bottom"
BarBackgroundColor="White"
SelectedTabColor="Black"
BarTextColor="Black">
<TabbedPage.Children>
<views:MainPage IconImageSource="tab_icon_mainpage.png" />
<!-- second link should be the sandwhich button that brings up the settings page -->
</TabbedPage.Children>
</TabbedPage>
MainPage.xaml (the main page, navigated to by the left TabBar link icon, to the left of the sandwhich icon with title "More")
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to the Main page!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
An easy way I can achieve the effect is to use Shell. It's released for months and just check your VS version for the correct template.
Create a new Xamarin.Forms project using VS2019.
You can use Shell out of the box if you can see the following screen.
Find "ItemsPage.xaml" in the Views folder.
Add one line in the ContentPage at the top
<ContentPage
...
Shell.TabBarIsVisible="False">
Add a StackLayout to contain the existing CollectionView and add your bottom buttons.
<RefreshView ...>
<!-- new StackLayout -->
<StackLayout>
<CollectionView ..... />
<!-- new Buttons -->
<StackLayout
HeightRequest="52"
Orientation="Horizontal"
BackgroundColor="#2196F3"
Visual="Material">
<Button
WidthRequest="200"
BackgroundColor="Transparent"
Text="Refresh"
Command="{Binding LoadItemsCommand}" />
<Button
BackgroundColor="Transparent"
Text="More"
Clicked="Button_Clicked" />
</StackLayout>
</StackLayout>
Go to "ItemsPage.xaml.cs" to complete the button event, add a method:
private void Button_Clicked(object sender, EventArgs e)
{
Shell.Current.FlyoutIsPresented = true;
}
Set startup project and deploy, check the effect and play around.
Additionally, in the latest Xamarin.Forms, UWP Shell is an experimental feature, and so does in XF 5.0. But the flyout things will probably work fine (not too sure about this).
An alternative, following the idea from #Shaw, but without Shell is to use the good old MasterDetail Page (which supports UWP) and add two buttons at the bottom to provide the "More" and "Refresh" functionality.
If this sounds like a good option for you, keep reading:
Add a Master-Detail Page to your Solution
On Visual Studio 2019 adding a Master-Detail to your solution is pretty straight forward. You only need to right click the Xamarin.Forms Project in the Solution Explorer and go to Add -> New Item (or simply use the shortcut Ctrl+Shift+A):
in the window that appears, select Master-Detail Page, give it a cool name (MasterDetailPage1 in this example!) and click Add:
By doing this you successfully have added a Master Detail to your solution. Now just go to App and set MainPage to it as follows:
MainPage = new MasterDetailPage1();
Add the bottom buttons
Now we want two buttons at the bottom of our Detail page. This is simply done by adding a stack of two buttons that locate at the end. Our newly added MasterDetailPage1Detail.xaml will then look like:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MasterTabRefresh.MasterDetailPage1Detail"
Title="Detail">
<StackLayout>
<Label Text="This is a detail page. To get the 'triple' line icon on each platform add a icon to each platform and update the 'Master' page with an Icon that references it."
Padding="10"/>
<StackLayout Orientation="Horizontal"
VerticalOptions="EndAndExpand"
Spacing="0">
<Button BackgroundColor="CornflowerBlue"
Text="Refresh"
TextColor="White"
CornerRadius="0"
HorizontalOptions="FillAndExpand"/>
<Button BackgroundColor="CornflowerBlue"
Text="More"
TextColor="White"
CornerRadius="0"
HorizontalOptions="FillAndExpand"
Clicked="MoreClicked"/>
</StackLayout>
</StackLayout>
</ContentPage>
which should look like:
And in the code behind (MasterDetailPage1Detail.xaml.cs ) we add the "More" functionality:
private void MoreClicked(object sender, EventArgs e)
{
((MasterDetailPage)Application.Current.MainPage).IsPresented = !((MasterDetailPage)Application.Current.MainPage).IsPresented;
}
Add a nice X (close) button to your menu/master
This could be achieved by adding a label with an "X" at the top right of the menu.
Simply modify your MasterDetailPage1Master.xaml to look like (note Label at Column 2 Row 0!)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MasterTabRefresh.MasterDetailPage1Master"
Title="Master">
<StackLayout>
<ListView x:Name="MenuItemsListView"
SeparatorVisibility="None"
HasUnevenRows="true"
ItemsSource="{Binding MenuItems}">
<ListView.Header>
<Grid BackgroundColor="#03A9F4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="80"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Label Grid.Column="2"
Grid.Row="0"
Text="X"
FontAttributes="Bold"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="X_Tapped"/>
</Label.GestureRecognizers>
</Label>
<Label
Grid.Column="1"
Grid.Row="2"
Text="My wonderful App"
Style="{DynamicResource SubtitleStyle}"/>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="15,10" HorizontalOptions="FillAndExpand">
<Label VerticalOptions="FillAndExpand"
VerticalTextAlignment="Center"
Text="{Binding Title}"
FontSize="24"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Which should look like this:
And then add the "Close" functionality to that "X" Label in the code behind (MasterDetailPage1Master.xaml):
private void X_Tapped(object sender, EventArgs e)
{
((MasterDetailPage)Application.Current.MainPage).IsPresented = false;
}
And that is it! This should get you going. Happy coding!
i have this:
<StackLayout VerticalOptions="FillAndExpand">
<LineEntry />
<ScrollView VerticalOptions="FillAndExpand">
<StackLayout x:Name="stack" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
</StackLayout>
</ScrollView>
</StackLayout>
But it does not scroll, except if you are into the LineEntry, because the keyboard is up. I think it's because the content page has less height than the scrollView, but don't know how to fix this.
I will update some mockups(can't use the real images) for more information, in the first one, does not works, in the second one, it works:
the content page has less height than the scrollView
This should be the first reason , and the send reason is the Content should exists some things , not a empty layot in ScrollView :
The follow code can work , just for reference :
<StackLayout VerticalOptions="FillAndExpand">
<Entry Text="First Entry"/>
<ScrollView HeightRequest="100" BackgroundColor="Beige" VerticalScrollBarVisibility="Always">
<StackLayout x:Name="stack"
HorizontalOptions="FillAndExpand"
HeightRequest="200">
<Entry Placeholder="Second Entry"/>
</StackLayout>
</ScrollView>
</StackLayout>
In Xamarin Forms 4.1, When scroll, scrollview content is covering/overflow the headerview and scrollview content is not shown completely.
Tried with IsClippedToBounds to true.
Created scrollviewrenderer, OnDraw() -> set clip to bound property. But didn't worked.
Example: Here is the XAML design
<Stacklayout>
<HeaderView/>
<ScrollView IsClippedToBounds="true">
<Stacklayout>
<label text="1"/>
........
........
<label text="100"/>
</Stacklayout>
</ScrollView>
</Stacklayout>
I make a custom control as the headerview in your description. And test on Xamarin.forms 4.1, works well.
MyCustomConrol:
<StackLayout Orientation="Horizontal" BackgroundColor="Aqua">
<Label x:Name="Title_label" Text="Title" TextColor="Black" FontSize="25" HorizontalOptions="StartAndExpand" Margin="8,0,4,0"/>
<Button x:Name="btnHello" Text="Hello" HorizontalOptions="EndAndExpand" Margin="4,0,8,0"/>
</StackLayout>
MainPage.xaml
<StackLayout>
<local:MyCustomControl></local:MyCustomControl>
<!--<HeaderView/>-->
<ScrollView IsClippedToBounds="true">
<StackLayout>
<Label Text="1"/>
<Label Text="2"/>
<Label Text="3"/>
……………
…………………
</StackLayout>
</ScrollView>
Result:
You could download from ScrollView/XamarinDemo folder of GitHub for reference.
https://github.com/WendyZang/Test.git
If you want your header to be always visible then rather than placinf your content in Header, it will be better to place your header content first then below that place your listview. Thus, your header remains intact and listview scrolls.
I've got following view:
<ContentPage.Content>
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<StackLayout VerticalOptions="CenterAndExpand" Margin="20, 0, 20, 0">
<StackLayout>
<Label Text="Login" HorizontalOptions="CenterAndExpand" />
<Entry Text="{Binding Login, Mode=OneWayToSource}"></Entry>
</StackLayout>
<StackLayout>
<Label Text="Hasło" HorizontalOptions="CenterAndExpand" />
<Entry IsPassword="True" Text="{Binding Password, Mode=TwoWay}"></Entry>
</StackLayout>
<Button Text="Zaloguj się" Command="{Binding SignInCommand}"></Button>
</StackLayout>
</StackLayout>
<BoxView AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" BackgroundColor="Gray" Opacity="0.5" InputTransparent="false" IsVisible="{Binding IsBusy}" />
<ActivityIndicator IsRunning="{Binding IsBusy}" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" />
</AbsoluteLayout>
</ContentPage.Content>
I want to move BoxView and ActivityIndicator to external control to make reusable component. The problem is that to achieve this I need to "group" these controls to obtain one child element.
The question is if is there any element I can use to group my controls, but which will not affect the way how controls are displayed? Alternatevlly which element I can use and how to still have effect of overlay over whole page and loading indicator?
I was trying to use AbsoluteLayout, StackLayout etc. but I couldn't position it to persist initial effect (overlay on whole page and loading indicator in the center with opacity = 1).
You can use DependencyService and reuse it in any page.
Check this tutorial.
There is also a working sample.
Im trying to show an Overlay with an activityIndicator by clicking an custom sync button in the toolbar. The Button makes an API call to get datas from my backend.
Im using Xamarin forms with the Prism Plugin
This is my MasterDetailPage Xaml
<MasterDetailPage.ToolbarItems >
<ToolbarItem Command="{Binding SyncCommand}" Icon="sync32.png">
</ToolbarItem>
</MasterDetailPage.ToolbarItems>
<MasterDetailPage.Master >
<ContentPage Title="Default"
BackgroundColor="Gray">
<StackLayout Padding="0,60,0,0">
<ListView x:Name="Menu"
VerticalOptions="FillAndExpand"
HorizontalOptions="Fill"
ItemsSource="{Binding Items}"
SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout MinimumHeightRequest="48"
Orientation="Horizontal"
Spacing="40">
<Label Text="{Binding TitleKey}"
TextColor="White"
FontSize="20"
VerticalOptions="Center"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Behaviors>
<behaviors:ListViewItemSelectedBehavior Command="{Binding ChangePageCommand }"/>
</ListView.Behaviors>
</ListView>
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<ContentPage>
<AbsoluteLayout
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<ActivityIndicator
Color="#69d2e7"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}"
IsVisible="{Binding IsBusy}"
IsRunning="{Binding IsBusy}"
/>
</AbsoluteLayout>
</ContentPage>
</MasterDetailPage.Detail>
This is my MasterDetail xaml cs
public SMasterDetail()
{
InitializeComponent();
Menu.ItemSelected += async (s, e) =>
{
Menu.SelectedItem = null;
IsPresented = false;
await Task.Delay(200);
};
}
When im clicking on The Sync button in the toolbar the ViewModel gets the datas from the backend and populate an ObservableCollection. Im setting IsBusy to true and after that to false.
But I cant see the overlay. Is their any solution how to show the activityIndicator overlay on each page by clicking the sync button?