[solved]scrolling in .NET MAUI sometimes not possible in webview - c#

I am showing 2 different documents of the same length in a webview, however 1 document respects the heightrequest(kinda) and is scrollable, the other ignores it and does not scroll.
I am uncertain as to what is the cause of this.
EDIT: I have created a github with the (slightly edited) documents this way you guys can just clone it. To change the contract you can just change the htmlwebviewsource html https://github.com/MaoUyen/wtf
In my xaml i have the following code in my content
<VerticalStackLayout>
<HorizontalStackLayout Spacing="200" VerticalOptions="Start" HorizontalOptions="Center">
<Button Text="Cancel" Clicked="Cancel_Clicked" BackgroundColor="#8244E7" TextColor="White" FontSize="Large" WidthRequest="120" HorizontalOptions="Center"/>
<Button Text="Sign" Clicked="Sign_Clicked" BackgroundColor="#8244E7" TextColor="White" FontSize="Large" WidthRequest="120" HorizontalOptions="Center"/>
</HorizontalStackLayout>
<WebView x:Name="Pagina" HeightRequest="50000">
</WebView>
in my cs i have the following code
protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
string string1 = "long html doc i cant fit in here";
string string2 = "long htmldoc2 that i cant fit either";
Pagina.Source = new HtmlWebViewSource { Html = string1 };
}
private async void Sign_Clicked(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("page");
}
private async void Cancel_Clicked(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("page2");
}
can anyone help me make heads or tails of why it doesnt just show the content completely of both?
i tried to add some parameters to the webview like heightrequest, i tried to put in a scrollview (it stopped scrolling)
without anything else the webview seems to work correctly but i need to have buttons to be able to go to the signing page...
i just want to be able to see my 2 page htmldoc in my webview and then click on the sign button.
EDIT: I have created a github with the (slightly edited) documents this way you guys can just clone it. To change the contract you can just change the htmlwebviewsource html https://github.com/MaoUyen/wtf
thank you for your time

alright so i took a long break and tried something else this seems to work
i don't understand why a verticalstacklayout generates so much problems but the grid seems to resolve this issue
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<HorizontalStackLayout Spacing="200" VerticalOptions="Start" HorizontalOptions="Center">
<Button Text="Cancel" Clicked="Cancel_Clicked" BackgroundColor="#8244E7" TextColor="White" FontSize="Large" WidthRequest="120" HorizontalOptions="Center"/>
<Button Text="Sign" Clicked="Sign_Clicked" BackgroundColor="#8244E7" TextColor="White" FontSize="Large" WidthRequest="120" HorizontalOptions="Center"/>
</HorizontalStackLayout>
<WebView x:Name="Pagina" Grid.Row="1">
</WebView>
</Grid>

Related

Navigation.PushAsync is not working inside User Control in Xamarin forms

I have a ListView in my ContentPage. Inside ListView.ItemTemplate, I have user control. In user control, there are image buttons. On Click of ImageButton, I want to move another page but it's not working. The code is run without error but nothing happened. The same code of PushAsync is working from all other content pages but not in user control. Please help me in this regard to what should I do.
ListView Code inside ContentPage:
<ListView x:Name="lvPosts" HasUnevenRows="True" SeparatorVisibility="None"
IsVisible="False">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10">
<controls:CardView/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
UserControl CardView:
<Frame xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:MyApp.General"
VerticalOptions="Start"
x:Class="MyApp.Controls.CardView">
<Frame.Content>
<Grid Padding="10" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="0"
Grid.ColumnSpan="4"
Grid.Row="0"
Text="{Binding Title}"
HorizontalOptions="FillAndExpand"
TextColor="#479774"
FontSize="Medium"
Style="{StaticResource DefaultFontStyle}"
Opacity="0.8">
</Label>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="0">
<ImageButton
x:Name="imgPdf"
Source="pdf.png"
Aspect="AspectFill"
Clicked="imgPdf_Clicked"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="1">
<ImageButton
x:Name="imgContent"
Source="document2.png"
Aspect="AspectFill"
Clicked="imgContent_Clicked"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="2">
<ImageButton
x:Name="imgSummary"
Source="document.png"
Aspect="AspectFill"
Clicked="imgSummary_Clicked"/>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.Row="1" Grid.Column="3">
<ImageButton
x:Name="imgVideo"
Source="video1.png"
Aspect="AspectFill"
Clicked="imgVideo_Clicked"/>
</StackLayout>
</Grid>
</Frame.Content>
</Frame>
And Code behind on ImageButton:
private async void imgVideo_Clicked(object sender, EventArgs e)
{
Post post = this.BindingContext as Post;
await Navigation.PushAsync(new WebViewPage(post));
}
The above answer isn't quite correct, and makes some assumptions. Navigation is available and can be used by any Xamarin Forms component that inherits NavigableElement and has a NavigationPage as an ancestor in its parental hierarchy. It's not limited to ContentPage by any means. Internal to Xamarin Forms, NavigableElements access their ancestral NavigationPage's Navigation stack via a series of internal NavigationProxy classes that get set and bound to their parent's NavigationProxy when each element's parent is set. Externally, we see these proxies as their interface type of INavigation, typically as the Navigation property of whatever element we're using.
ViewCell does not inherit NavigableElement (why, I'm not entirely sure, since it's parented to its container like any other component), and thus doesn't have a Navigation property. In your case, your ViewCell contains another View, which does inherit NavigableElement, but because its parent (ViewCell) isn't a NavigableElement, the chain of NavigationProxies is broken. Thus, you can try to make calls to Navigation on your CardView, but it's not hooked up to anything, and thus won't do anything.
The solution of directly accessing the Application's Navigation property (I assume the above poster meant Application.Current.MainPage.Navigation, as Application doesn't have a Navigation property itself) only works if your Application's MainPage is the only NavigationPage in your app. However, this isn't guaranteed to be the case; for example, a TabbedPage component could contain its own NavigationPages for each of its tabs, and accessing Application.Current.MainPage.Navigation will only get you the NavigationProxy for navigating the MainPage. ViewCells in a tabbed NavigationPage would be unable to navigate within their tab via this solution.
What you can do instead is something like this:
public MyViewCell : ViewCell
{
private INavigation Navigation { get; set; }
protected override void OnParentSet()
{
base.OnParentSet();
Navigation = (Parent as NavigableElement)?.Navigation;
}
}
Your ViewCell now has access to its parent's navigation stack, which you can do with as you please. You could pass it into your cell's child View, if you wanted, or just do your navigation here. Why ViewCell doesn't already do this under the hood, I don't fully understand.
Note: Depending on the CacheStrategy you set on your ListView (or whatever View component is using your ViewCell as a template), it's possible your custom ViewCell may be handed a null Parent from time to time, which would yield a null Navigation property. Usually this shouldn't be a problem, as a null Parent generally indicates the cell isn't actively being displayed, but it's worth keeping in mind in case your custom ViewCell could potentially try to access Navigation without user input via some automated business logic.
We could only invoke the method Navigation.PushAsync in a ContentPage . In your case , CardView is a subclass of a Frame , so it will never work .
The best solution is to invoke the method in Code Behind (ViewModel or ContentPage) . Since you had used Custom View . It would be better to handle the logic by using Data-binding .
If you do want to invoke the method in CardView, you could define a property in App and pass the current Navigation from ContentPage .
in App.xaml.cs
public INavigation navigation { get; set; }
in ContentPage
Note : You need to invoke the following lines in each ContentPage .
public xxxContentPage()
{
InitializeComponent();
var app = App.Current as App;
app.navigation = this.Navigation;
}
in CardView
var app = App.Current as App;
var navigation = app.navigation;
navigation.PushAsync(xxx);

Is there a way to animate the width of button programmatically from both sides

I want to be able to resize animatedly the button from both sides for now I was able to do it from one side right to left.
Code ->
double Height = Button1.Height;
bool x = await Button1.LayoutTo(new Rectangle(new Point(Button1.X, Button1.Y), new Size(150, Height)), 1200,Easing.Linear);
Button ->
<StackLayout VerticalOptions="Center">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="Button1" Grid.Row="0" Clicked="Button1_Clicked" BorderRadius="20" HorizontalOptions="CenterAndExpand" WidthRequest="1500" />
<!--<ActivityIndicator Grid.Row="1" IsRunning="true" ></ActivityIndicator>-->
</Grid>
</StackLayout>
(Before animation) ->
(After animation) ->
(I want) ->
If Resize is all you intend to do, use ScaleXTo with AnchorX set to 0.5(default).
Set AnchorX in XAMl:
<Button
x:Name="Button1"
Grid.Row="0"
Clicked="Button1_Clicked"
BorderRadius="20"
AnchorX="0.5"
HorizontalOptions="CenterAndExpand"
WidthRequest="1500" />
Use ScaleXTo in cs
void Button1_Clicked(System.Object sender, System.EventArgs e)
{
if (Button1.ScaleX < 1)
{
Button1.ScaleXTo(1);
}
else
{
Button1.ScaleXTo(0.5);
}
}
Give it a whirl and comment if further info is needed. Hope it helps.
After reading about LayoutTo method i found this Article
Quoting:
First what it is meant for. LayoutTo is actually used cause a child to
be layed out in a series of animated steps to a new location. This
sounds useful but there are a couple important things to note.
It was only intended to be used by Xamarin.Forms.Layout subclasses,
not externally.
It is stupidly exposed in the same way the other
animation methods are.
It will initially appear to do what you want,
but anything that triggers a relayout will cause your views position
to reset to where it started.
So i'm guessing that LayoutTo doesn't take take in acount the LayoutOptions for that element, so a better solution would be using other animation methods like TranslateTo or Animation

Display text while Page is loading in Xamarin Forms

I have a page that is quite heavy and its loading for about 1-2 sec after click. During this time I see loading page header and old page content, it looks so irresponsive. All I want to achive is to display temporary Label with content like "Loading..." or activityindicator as long as new page is loading but I have no idea how to do this. What is the better way to achive this? Thanks in advance
Based on your comments, you just want to display Busy indicator while you are loading the Data from your Api. You didn't posted your UI but I hope you understand how to use the below:
<Grid>
<YOUR-UI>
.....
.........
</YOUR-UI>
<ActivityIndicator VerticalOptions="Center" IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}"/>
</Grid>
In your ViewModel, Add IsBusy Property as below:
private bool _isBusy;
public bool IsBusy
{
get{return _isBusy;}
set { _isBusy=value; RaisePropertyChanged(); }
}
Then when you are Calling the API to load your Data do something like:
public async void LoadDataFromApi()
{
IsBusy=true; //Show the Indicator
var response= await YourService.Method(); //this is where you calling your api
//do other stuffs if you need to do;
IsBusy=false; //Hide the Indicator
}
Let me know if you need anymore help.
Based on your comments on other answer - instead of ActivityIndicator - you could use a simple frame that covers all the layout and make it visible only when data are loading i.e. Binding IsVisible to IsBusy property. Then set IsBusy to true before doing the heavy load job and set back to false afterwards as shown in previous answer.
For instance, assuming your UI is based on a Grid layout (in this example 3 rows/2 columns):
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Some XAML for the grid content -->
<!-- Here, Frame covers all the possible space defined using RowSpan/ColumnSpan -->
<Frame Grid.RowSpan="3" Grid.ColumnSpan="2" IsVisible="{Binding IsBusy}" BackgroundColor="LightGray">
<Label VerticalOptions="Center" HorizontalOptions="Center" Text="Loading Samples..." />
</Frame>
</Grid>
-------------------------------------------------
EDIT based on OP comments:
Bases on the code you provided (better paste it in SO next time ;)), you could try this:
Add a grid layout and a frame to the xaml page:
<?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="MyApp.Namespace"
xmlns:tabView="clr-namespace:Syncfusion.XForms.TabView;assembly=Syncfusion.SfTabView.XForms"
xmlns:sfPopup="clr-namespace:Syncfusion.XForms.PopupLayout;assembly=Syncfusion.SfPopupLayout.XForms"
BackgroundColor="#d4d4d4">
<ContentPage.ToolbarItems>
<ToolbarItem Icon="search_white_90.png"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<Grid>
<tabView:SfTabView x:Name="ProductsTabView" VisibleHeaderCount="3" TabHeaderBackgroundColor="#A74B40" Items="{Binding}">
<tabView:SfTabView.SelectionIndicatorSettings>
<tabView:SelectionIndicatorSettings
Color="#fff" StrokeThickness="3"/>
</tabView:SfTabView.SelectionIndicatorSettings>
</tabView:SfTabView>
<Frame x:Name="theFrame" BackgroundColor="White">
<Label VerticalOptions="Center" HorizontalOptions="Center" Text="Loading Samples..." />
</Frame>
</Grid>
</ContentPage.Content>
</ContentPage>
ProductsTabView and theFrame will cover the same space on screen and frame will be available in code behind. Then you can show/hide theFrame before/afrer the hard work using IsVisible property:
public partial class ProviderPage : ContentPage
{
public ProviderPage()
{
InitializeComponent();
theFrame.IsVisible = true; // Show the Frame on top of tabView
ProductsTabView.Items = GetTabItemCollection();
theFrame.IsVisible = false; // Hide the Frame
}
...
As a side note, you don't use ViewModel at all. I strongly recommand you to check about what a ViewModel is and how to use them with MVVM pattern. It will make your life easier in the long run using Binding!
HIH & Happy coding!
Try https://github.com/aritchie/userdialogs, It's make you easily to implement loading
for example:
using (this.Dialogs.Loading("Loading text"))
{
//Do something i.e: await Task.Delay(3000);
}
OR
this.Dialogs.ShowLoading("Loading text");
//Do something i.e: await Task.Delay(3000);
this.Dialogs.HideLoading();
OR
https://github.com/aritchie/userdialogs/blob/master/src/Samples/Samples/ViewModels/ProgressViewModel.cs
I have a project for advanced page transitions in Xamarin.Forms that may help you. Try this:
Install this nuget: http://www.nuget.org/packages/Xamarin.Forms.Segues (it is currently only prerelease, so you'll need to check the box to see it)
Add this sample to your project: https://github.com/chkn/Xamarin.Forms.Segues/blob/master/Sample/Shared/Custom%20Segues/SpinnerSegue.cs
In the DoWork method of SpinnerSegue add the code to load the data.
In your code that navigates to the other page, replace Navigiation.PushAsync(new MyNewPage()) with new SpinnerSegue().ExecuteAsync(this, new MyNewPage())

ActivityIndicator not showing in XAML or CodeBehind

I have a weird situation on my Xamarin.Forms app. I´m trying to show an ActivityIndicator, but it is not showing in any condition. I´ve set all conditions on XAML and then I tried on code behind. But I could not get it to work. This is the code:
<StackLayout HorizontalOptions="Center"
VerticalOptions="Center">
<ActivityIndicator x:Name="actIndicator"
Color="Blue"
IsVisible="True"
IsRunning="True"/>
<Label x:Name="lblCargando"
Text="Cargando..." />
<Label x:Name="lblStatus"/>
<Button x:Name="btnCerrar"
Text="Cerrar"
IsVisible="False"
Clicked="Cerrar_Clicked"/>
</StackLayout>
Is there something missing?.
Thanks.
Finally, it seems that there was an issue with the emulator that was executing an old version of code.
I deleted the emulator and re create it and get rid of the problem.

How to partially cut ViewCell separator line in Xamarin Forms?

I am using ViewCell to create rows in my table settings page. I have a setting to select a Light or Dark theme.
<ViewCell Height="50">
<StackLayout x:Name="darkTheme" VerticalOptions="FillAndExpand" Padding="20,0,20,0">
<StackLayout Orientation="Horizontal" VerticalOptions="CenterAndExpand">
<Label Text="Dark" XAlign="Center" FontSize="15"/>
<Label x:Name="darkThemeCheckmark" Text="{x:Static local:FontAwesome.FACheck}" FontFamily="FontAwesome" XAlign="Center" IsVisible="false" FontSize="12" HorizontalOptions="EndAndExpand"/
</StackLayout>
</StackLayout>
</ViewCell>
<ViewCell Height="50">
<StackLayout x:Name="lightTheme" VerticalOptions="FillAndExpand" Padding="20,0,20,0">
<StackLayout Orientation="Horizontal" VerticalOptions="CenterAndExpand">
<Label Text="Light" XAlign="Center" FontSize="15"/>
<Label x:Name="lightThemeCheckmark" Text="{x:Static local:FontAwesome.FACheck}" FontFamily="FontAwesome" XAlign="Center" IsVisible="false" FontSize="12"/>
</StackLayout>
</StackLayout>
</ViewCell>
Whenever I switch from dark to light theme, there is faint light line on the left side between my rows that I can't seem to get rid of. Please refer to the images below:
In my renderer I have set the following:
tableView.LayoutMargins = new UIEdgeInsets() { Left = 20 };
cell.SeparatorInset = new UIEdgeInsets() { Left = 20 };
cell.LayoutMargins = new UIEdgeInsets() { Left = 20 };
Anyone knows how to get rid of this line?
Edit:
I wanted it to look like below:
I am novice to xamarin but, According to this post you need to do this on the UITableView and on your UITableViewCell subclasses.
I hope this will help you. :)
Apologies in advance incase you have already considered this but I believe what you're looking for is 'TableView.SeparatorInset' this would apply to your renderer rather than the xaml your using in your PCL. You can find the documentation around styling the tableviews at this link.
E.G.
TableView.SeparatorInset.InsetRect(new CGRect(4, 4, 150, 2));
Moving the inset of the seperator will get around the problem I saw you mention in the comments of the other answer about the whole table shifting. Please let me know if you've tried this already, it's the simplest solution but there are other options available to you. (They just aren't as nice).
Edit: Example of a way of achieving your goals by creating your own seperators, not my favourite but would also resolve the issue you've highlighted as you'd have complete control over the styling of a seperator. Refer to this Link

Categories