Swipe to refresh on ScrollView - android

I want to do something like facebook, when we drag the scroll view until a negative y, the activity indicator will show up and refresh the view.
When i implement the following code, it is working on IOS. However, when run on Android devices, the scroll y seem only possible to have 0 or more than 0 value and cannot scroll be scroll to the negative area.
async void ContentScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
if (!hold)
{
if (ContentScrollView.ScrollY < -70)
{
hold = true;
scrollLoadingBar.IsRunning = true;
scrollLoadingBar.IsVisible = true;
netStructure structure = await Net.getWebServicesData("chart.asmx/GetCampaignChart?username=" + App.username + "&password=" + App.password + "&campid=" + App.campid + "&noOfChart=1&callback=");
if (structure.status)
{
App.chart1 = structure.returnObject;
setcampaignchart();
}
else
{
await DisplayAlert("Loading Chart Error", structure.errorMessage, "Ok");
}
scrollLoadingBar.IsVisible = false;
scrollLoadingBar.IsRunning = false;
}
}
if (hold)
{
if (ContentScrollView.ScrollY == 0)
{
hold = false;
}
}
}
How can I get this to work on Android?

Update as on 09/09/2020: As #johan-franzén has commented, RefreshView should be used. Here is the official documentation on how to use RefreshView
I'm guessing you want a Xamarin.Forms solution even though you haven't mentioned so in your question, because of the Xamarin.Forms tag. You needn't code that by hand. James Montemagno has done all the hard work for us. Here is the link to PullToRefreshLayout github page. You just need to add PullToRefreshLayout at the place of ScrollView in Xaml and set the ScrollView as it's Content.
Edit : Explaining usage as suggested by #cheesebaron .
You can install the plugin Nuget package Refractored.XamForms.PullToRefresh .
Then we can implement PullToRefresh action by Adding PullToRefreshLayout as parent to the ScrollView. I am quoting the example given in Github 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="RefreshSample.Views.ScrollViewXamlPage"
xmlns:controls="clr-namespace:Refractored.XamForms.PullToRefresh;assembly=Refractored.XamForms.PullToRefresh"
Title="Xaml Scroll">
<controls:PullToRefreshLayout
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsBusy}"
RefreshColor="Blue">
<ScrollView
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<StackLayout
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Blue"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Red"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Yellow"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Purple"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Maroon"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Blue"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Red"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Yellow"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Purple"/>
<BoxView HeightRequest="100" WidthRequest="100" BackgroundColor="Maroon"/>
</StackLayout>
</ScrollView>
</controls:PullToRefreshLayout>
</ContentPage>

Related

xamarin.forms ImageSource set from code sometimes disappears, doesnt work on iOS at all

I have this xaml class:
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
HeightRequest="130"
WidthRequest="90"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="InteriorCircle.Pages.MainMenu.CV_PinStyle">
<ContentView.Content>
<StackLayout BackgroundColor="Transparent">
<Frame
HeightRequest="130"
WidthRequest="90"
VerticalOptions="Start"
HasShadow="False"
HorizontalOptions="Start"
BackgroundColor="#565656"
Padding="0"
CornerRadius="25"
IsClippedToBounds="true">
<StackLayout Padding="5">
<Grid VerticalOptions="Center" Margin="10,10,0,0" HorizontalOptions="Center">
<Image x:Name="img_pic"
Margin="3,0,0,0"
HorizontalOptions="Center"
VerticalOptions="Center">
<Image.Clip>
<EllipseGeometry
Center="27,27"
RadiusX="27"
RadiusY="27"/>
</Image.Clip>
</Image>
<Ellipse Stroke="#60CED3"
StrokeThickness="6"
WidthRequest="60"
HeightRequest="60"
HorizontalOptions="Start" />
</Grid>
<Label
Margin="0,0,0,0"
x:Name="label_title"
TextColor="White"
LineBreakMode="TailTruncation"
FontFamily="JakartaReg"
VerticalOptions="Start"
FontSize="12"
HorizontalOptions="Center"/>
<Label
x:Name="label_price"
TextColor="White"
FontFamily="JakartaBold"
VerticalOptions="Start"
FontSize="10"
HorizontalOptions="Center"/>
</StackLayout>
</Frame>
</StackLayout>
</ContentView.Content>
</ContentView>
I retrieve content from another class (event) and set it to the properties from here:
private async Task SetContent(EventType events)
{
InitializeComponent();
byte[] bt = Converters.StringToByteArray(events.eventPictureThumb);
label_title.Text = events.name;
label_price.Text = Converters.GetDecimalPriceFromCents(events.priceInCents) + " €";
Device.BeginInvokeOnMainThread(() =>
{
var source = Converters.ReturnImageSourceFromString(Converters.ByteArrayToString(bt));
img_pic.Source = source;
});
}
However, this does not work sometimes on Android, on iOS not at all.
When I set an image directly in xaml, it is always displayed. On iOS, when the image comes from code, it is never displayed. On Android, it is displayed most of the times, but fails sometimes. When multiple objects load into the view the old ones lose their images.
I am adding the view like so:
var startPin = BitmapDescriptorFactory.FromView(new CV_PinStyle(currentEvent));
Pin pin = new Pin
{
Label = currentEvent.name,
Tag = currentEvent.tblEventID+Constants.DELIMITER+currentEvent.userID,
Icon = startPin,
Type = PinType.Place,
Position = position
};
gMap?.Pins?.Add(pin);
So I am doing somethign wrong here,
can you help me?

Xamarin forms webview takes all the screen height

I have a webview in one of my page and I want to add a stacklayout from the top then the webview. But Webview take whole screen and the stacklayout never get shown. I want to hide default navigation bar and create my own one. I still couldn't test for the apple side
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns:other="clr-namespace:CustApp.CusApp.Dushan.Other"
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"
EnableBackButtonOverride="True"
x:Class="CustApp.Views.GeneralPayments.MotorPayments.hnb.HNBmotorPayment">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" VerticalOptions="Start" HorizontalOptions="FillAndExpand" Orientation="Horizontal" Padding="10,5,10,5">
<Image HorizontalOptions="StartAndExpand" Source="pdfDown.png"/>
<Label HorizontalOptions="CenterAndExpand" Text="ALL"/>
<Image HorizontalOptions="EndAndExpand" Source="pdfDown.png"/>
</StackLayout>
<WebView Grid.Row="1" x:Name="webView"
HorizontalOptions="CenterAndExpand"
Navigating="webView_Navigating"
Navigated="MywebView_Navigated"/>
</Grid>
</ContentPage.Content>
</ContentPage>
Code behind
protected override void OnAppearing()
{
base.OnAppearing();
NavigationPage.SetHasNavigationBar(this, false);
if (isFirstRun)
{
jsonOutput = JsonConvert.SerializeObject(payData);
//var htmlSource = new HtmlWebViewSource();
var urlSource = new UrlWebViewSource();
string url = DependencyService.Get<IBaseUrl>().Get();
TempUrl = Path.Combine(url, "xamarinhtmlmotor.html");
urlSource.Url = TempUrl;
webView.Source = urlSource;
isFirstRun = false;
Content = webView;
}
}
The cause is you set the Content = webView in code behind which means the the whole content is webview and those code in the Xaml will be overwritten.
Solution:
Remove Content = webView; and try again.

Sliding Drawer open from right to left in xamarin android

I am getting issue to open sliding drawer from right to left for
xamarin android . but below code working for show sliding
drawer from left to right. if any property of MasterDetailPage to
open sliding from right to left
please share your views with me. Here Sliding Drawer open from left to right but i want to open from right to left for Xamarin
Android
Any idea regarding this. please share your idea's.
We are also using MenuRootPage for add items in Sliding Drawer :
Code for items view:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
>
<ContentPage.Content>
<StackLayout BackgroundColor="{StaticResource ToolbarStatusBackgroundColor}" Orientation="Vertical" Spacing="20">
<StackLayout>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{mm:Command SliderClose}" />
</StackLayout.GestureRecognizers>
<Image Source="menu.png" HorizontalOptions="Start" Margin="10,40,0,0" />
</StackLayout>
<BoxView HorizontalOptions="EndAndExpand" HeightRequest="1" WidthRequest="1000" Color="{StaticResource SeparatorColor}" />
<Label Text="My account" Style="{StaticResource ToolbarStatusDescriptionLabel}" Margin="10" >
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{mm:Command SliderClose}" />
</Label.GestureRecognizers>
</Label>
<BoxView HorizontalOptions="EndAndExpand" HeightRequest="1" WidthRequest="1000" Color="{StaticResource SeparatorColor}" />
<Label Text="Settings" Style="{StaticResource ToolbarStatusDescriptionLabel}" Margin="10">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{mm:Command SliderClose}" />
</Label.GestureRecognizers>
</Label>
<BoxView HorizontalOptions="EndAndExpand" HeightRequest="1" WidthRequest="1000" Color="{StaticResource SeparatorColor}" />
<Label Text="Logout" Style="{StaticResource ToolbarStatusDescriptionLabel}" HorizontalTextAlignment="Center" VerticalOptions="EndAndExpand" Margin="10">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{mm:Command Logout}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ContentPage.Content>
</ContentPage>
In MenuRootPage .xaml file we are declare master page only UI section
In MenuRootPage .cs file: here we are inherit MasterDetailPage properties
Using code:
Root page in MenuRootPage .xaml file:
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Ansible.Vektor.App.Shared.Views.MenuRootPage" >
</MasterDetailPage>
Root MenuRootPage .cs file:
public partial class MenuRootPage : MasterDetailPage
{
public MenuRootPage ()
{
InitializeComponent();
MasterBehavior = MasterBehavior.Popover;
}
}
App.xaml.cs:
var menuPage = new MenuPages() { BindingContext = MenuPagesViewModel };
NavigationPage = new NavigationPage(new MainView() {
BindingContext = MainViewModel });
MenuRootPage = new MenuRootPage();
MenuRootPage.Master = menuPage;
MenuRootPage.Detail = NavigationPage;
MenuIsGestureEnabled = false;
MainPage = MenuRootPage;
Here Sliding Drawer open from left to right but i want to open from right to left for Xamarin Android
Any idea regarding this. please share your idea's.
Make custom render for Master Detail Page in Android.
public class MyMasterDetailPageRenderer : MasterDetailPageRenderer
{
protected override void OnElementChanged(VisualElement oldElement, VisualElement newElement)
{
base.OnElementChanged(oldElement, newElement);
var fieldInfo = GetType().BaseType.GetField("_masterLayout", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
var _masterLayout = (ViewGroup)fieldInfo.GetValue(this);
var lp = new DrawerLayout.LayoutParams(_masterLayout.LayoutParameters);
lp.Width = 300;
lp.Gravity = (int)GravityFlags.Right;
_masterLayout.LayoutParameters = lp;
}
}

TapGestureRecognizer not responding in xamarin forms

I'm facing a pretty weird problem trying to catch taps on certain images on my screen first here is my xaml code for a popup window implemented as a View :
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="NumbersRaceXamarin.YesNoPopupMessages">
<ContentView.Content>
<RelativeLayout HeightRequest="190" WidthRequest="280">
<Image x:Name="bg" Source="compbar_01.png" Aspect="Fill" HeightRequest="190" WidthRequest="330" Opacity="0.9" InputTransparent ="true"/>
<StackLayout WidthRequest="280" Spacing="0" RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width , Factor=0.1,Constant=0}" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height , Factor=0.02,Constant=0}">
<Label x:Name="message" FontSize="15"></Label>
<StackLayout WidthRequest="70" HeightRequest="30" Orientation="Horizontal" HorizontalOptions="Center">
<RelativeLayout WidthRequest="30" HeightRequest="30" VerticalOptions="Center">
<Image x:Name="minus" Source="startbottuns_01.png" Aspect="Fill" HeightRequest="30" WidthRequest="30"/>
<Label x:Name="minusTB" Text="-" FontSize="16" HeightRequest="30" WidthRequest="30" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"></Label>
</RelativeLayout>
<Label x:Name="qtyTB" Text="1" FontSize="8" HeightRequest="30" WidthRequest="30" BackgroundColor="White" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"></Label>
<RelativeLayout WidthRequest="30" HeightRequest="30" VerticalOptions="Center">
<Image x:Name="plus" Source="startbottuns_01.png" Aspect="Fill" HeightRequest="30" WidthRequest="30" IsEnabled="true"/>
<Label x:Name="plusTB" Text="+" FontSize="16" HeightRequest="30" WidthRequest="30" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"></Label>
</RelativeLayout>
</StackLayout>
<StackLayout x:Name="coinAmountSeg" HeightRequest="40" WidthRequest="90" Orientation="Horizontal" HorizontalOptions="Center" IsVisible="true">
<Label x:Name="coinsAmountTB" Text="1200" HeightRequest="35" WidthRequest="40" VerticalTextAlignment="Center" HorizontalTextAlignment="End"/>
<Image x:Name="coinsPackIM" Source="coins_01.png" HeightRequest="35" WidthRequest="25"/>
</StackLayout>
<StackLayout x:Name="yesNoBtSeg" HeightRequest="32" WidthRequest="150" Orientation="Horizontal" HorizontalOptions="Center" IsVisible="true">
<RelativeLayout HorizontalOptions="Center" >
<Image x:Name="yesBt" x:Uid="yesBt" Source="startbottuns_01.png" Aspect="Fill" HeightRequest="32" WidthRequest="80"></Image>
<Label x:Name="yesTB" Text="OK" FontSize="20" HeightRequest="32" TextColor="Yellow" WidthRequest="80" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"></Label>
</RelativeLayout >
<RelativeLayout HorizontalOptions="Center" >
<Image x:Name="noBt" x:Uid="noBt" Source="startbottuns_01.png" Aspect="Fill" HeightRequest="32" WidthRequest="80"></Image>
<Label x:Name="noTB" Text="CANCEL" FontSize="20" HeightRequest="32" TextColor="Yellow" WidthRequest="80" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"></Label>
</RelativeLayout>
</StackLayout>
</StackLayout>
</RelativeLayout>
</ContentView.Content>
</ContentView>
and here is how I try to catch the events from plus and minus ok and cancel images:
var minusTap = new TapGestureRecognizer();
var plusTap = new TapGestureRecognizer();
var okTap = new TapGestureRecognizer();
var cancelTap = new TapGestureRecognizer();
minusTap.Tapped += minusBtn_Click;
plusTap.Tapped += plusBtn_Click;
okTap.Tapped += okBtn_Click;
cancelTap.Tapped += cancelBtn_Click;
noBt.GestureRecognizers.Add(cancelTap);
plus.GestureRecognizers.Add(plusTap);
minus.GestureRecognizers.Add(minusTap);
yesBt.GestureRecognizers.Add(okTap);
private void okBtn_Click(object sender, EventArgs e)
{
tcs.SetResult(1);
}
private void cancelBtn_Click(object sender, EventArgs e)
{
tcs.SetResult(0);
}
private void minusBtn_Click(object sender, EventArgs e)
{
if (int.Parse(qtyTB.Text) > 1)
{
coinsAmountTB.Text = "" + (int.Parse(coinsAmountTB.Text) - itemCost);
qtyTB.Text = (int.Parse(qtyTB.Text) - 1) + "";
}
}
private void plusBtn_Click(object sender, EventArgs e)
{
if (int.Parse(qtyTB.Text) < max)
{
coinsAmountTB.Text = "" + (int.Parse(coinsAmountTB.Text) + itemCost);
qtyTB.Text = (int.Parse(qtyTB.Text) + 1) + "";
}
}
the problem is really strange the tap events work fine on the ok cancel and minus buttons but won't fire when taping the plus image for some reason.
I thought something was overlapping and "stealing" the taps on the plus button but I can't find anything like that .
BTW I'm trying this on android not trying on other devices.
anyone have any idea how and why this happens?
Ok so I found the silly problem thought I'd share my solution in case anyone encounter the same issue.
the problem was that the stacklayout that contains the buttons had less width than the elements it contained so the last element the plus in this case was out of the stacklayout bounds and that caused it to not get the tap gesture
<StackLayout WidthRequest="70" HeightRequest="30" Orientation="Horizontal" HorizontalOptions="Center">
<RelativeLayout WidthRequest="30" HeightRequest="30" VerticalOptions="Center">
this line here I just changed the WidthRequest to 100 instead of 70 because it has 3 elements 30 width each .
Hope this helps someone
I had the same problem, also caused by the parent element having less size than the tap-enabled child.
In my case, I had an absolute layout (Inner) inside another absolute layout (Outer). I was then adding the tap-enabled child elements programmatically to Inner in the code-behind.
<AbsoluteLayout x:Name="Outer">
<AbsoluteLayout x:Name="Inner" />
</AbsoluteLayout>
Because Inner had no AbsoluteLayout.LayoutBounds specified, it seems the interaction cycle ignored the children. This was not obvious to me because the child elements were visible.
This worked:
<AbsoluteLayout x:Name="Outer">
<AbsoluteLayout x:Name="Inner"
AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
AbsoluteLayout.LayoutFlags="All" />
</AbsoluteLayout>
However, I ended up putting my tap target elements in the Outer container, which also resolved the issue, as Outer is enclosed by a ContentPage.

Xamarin Forms - Webview is not showing up within my StackLayout

why isn't the WebView showing ? I have tried FillAndExpand and CenterAndExpand , but it still not working!
<?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:views="clr-namespace:MyApp.Views;assembly=MyApp"
x:Class="MyApp.Pages.Main">
<StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="Start">
<!-- top controls -->
</StackLayout>
<StackLayout x:Name="WebViewLayout" VerticalOptions="CenterAndExpand">
<WebView Source="https://www.google.com/" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand"/>
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="End">
<views:AdMobView WidthRequest="400" HeightRequest="50" />
</StackLayout>
</StackLayout>
</ContentPage>
Change the Vertical Options of the StackLayout (which holds the WebView) from CenterAndExpand to FillAndExpand and the WebView itself.
I hope this helps. :)
<StackLayout x:Name="WebViewLayout" VerticalOptions="FillAndExpand">
<WebView Source="https://www.google.com/" VerticalOptions = "FillAndExpand"/>
</StackLayout>
I would suggest taking the WebView out of the parent StackLayout and the change the outer most StackLayout to a Grid.
That being said, I think that might help solve the issue without doing that:
public override void OnAppearing() {
SizeChanged += (sender, e) => {
WebViewItem.WidthRequest = Width;
WebViewItem.HeightRequest = 200; //Or what ever
}
OnSizeChanged(null, null); //Make it run at least once
}
I can't say exactly why but setting the VerticalOptions on the stack layout seemed to solve it for me. The following results in the web view being drawn:
var webView = new WebView();
webView.Source = "https://www.xamarin.com";
webView.MinimumWidthRequest = 200;
webView.MinimumHeightRequest = 200;
webView.HorizontalOptions = LayoutOptions.FillAndExpand;
webView.VerticalOptions = LayoutOptions.FillAndExpand;
var stackLayout = new StackLayout;
this.Content = stackLayout;
stackLayout.Children.Add(webView);
stackLayout.HorizontalOptions = LayoutOptions.FillAndExpand;
stackLayout.VerticalOptions = LayoutOptions.FillAndExpand;
I admit the layout behavior for StackLayout is pretty confusing.

Categories

Resources