I have Tried with PancakeView and Frame But i did't create the type of
shape in red anyone please can make this red shaped background in
Xamarin.forms with Xaml.
In your case you could use Shapes . Xamarin.Forms Shapes is currently experimental and can only be used by setting the Shapes_Experimental flag. So add the line Forms.SetFlags("Shapes_Experimental"); in all platforms .
in iOS -> AppDelegate.cs
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Forms.SetFlags("Shapes_Experimental");
Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
in Android -> MainActivity
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Forms.SetFlags("Shapes_Experimental");
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
in xaml
<StackLayout VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand">
<BoxView BackgroundColor="Red" HeightRequest="200" />
<Ellipse Fill="Red"
Margin="0,-90,0,0"
HeightRequest="180"
WidthRequest="1000"
/>
</StackLayout>
Effect
Related
I am converting my Xamarin Forms Application to .NET MAUI.
I am trying to migrate the Custom renderer from Xamarin to MAUI following this link Using Custom Renderers in .NET MAUI
Here is my Code:
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCompatibility()
.ConfigureMauiHandlers(handlers =>
{
handlers.AddCompatibilityRenderer(typeof(CustomFrame), typeof(CustomShadowFrameRenderer));
});
return builder.Build();
}
CustomFrame:
public class CustomFrame : Frame
{
public CustomFrame()
{
}
}
Below is the Custom Renderer Class
public class CustomShadowFrameRenderer : FrameRenderer
{
public CustomShadowFrameRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null && e.OldElement == null)
{
e.NewElement.HeightRequest = 1000;
e.NewElement.VerticalOptions = LayoutOptions.FillAndExpand;
}
}
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp1.MainPage" BackgroundColor="Red"
xmlns:local="clr-namespace:MauiApp1.Controls">
<local:CustomFrame BackgroundColor="Blue" HeightRequest="1000" Padding="20">
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Label
Text="Hello, World!"
SemanticProperties.HeadingLevel="Level1"
FontSize="32"
HorizontalOptions="Center" />
<Label
Text="Welcome to .NET Multi-platform App UI"
SemanticProperties.HeadingLevel="Level2"
SemanticProperties.Description="Welcome to dot net Multi platform App U I"
FontSize="18"
HorizontalOptions="Center" />
<Button
x:Name="CounterBtn"
Text="Click me"
SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnCounterClicked"
HorizontalOptions="Center" />
</VerticalStackLayout>
</local:CustomFrame>
</ContentPage>
The Frame is not accepting the height Request in MAUI but the same works fine in Xamarin forms.
Below is the image for the same
I have create a sample to test your code and met the same problem. In addition, I even can't click the button in the CustomFrmae. It seems there are some compatibility issues about the FrameRender in the maui.
So I try to change the CustomRender to the CustomHandler. It worked well and you just need to change two place code.
In the CustomShadowFrameRenderer class, make it such as public class CustomShadowFrameRenderer : Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer
In the MauiProgram.cs:
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler(typeof(CustomFrame), typeof(CustomShadowFrameRenderer));
})
I have a webview When this webview is tapped I need to make visible of a button the problem Is Gesture recognition is not working
my Xaml
<customRenderer:CustomWebView Uri="{Binding SelectedJournal.Uri}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" x:Name="CustomWebView" AbsoluteLayout.LayoutBounds="0,50,1,1" AbsoluteLayout.LayoutFlags="SizeProportional" >
<customRenderer:CustomWebView.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped2" NumberOfTapsRequired="1" ></TapGestureRecognizer>
</customRenderer:CustomWebView.GestureRecognizers>
</customRenderer:CustomWebView>
<customRenderer:NavigationImageButton ItemTapped="FullScreenOnTapped" Source="full.jpg" AbsoluteLayout.LayoutBounds="0.5,1,-1,-1" AbsoluteLayout.LayoutFlags="PositionProportional" HeightRequest="60" WidthRequest="60" x:Name="FullScreenBtn" IsVisible="False" >
In the code behind i called like this
private void TapGestureRecognizer_OnTapped2(object sender, EventArgs e)
{
FullScreenBtn.IsVisible = true;
}
This should work but this is not working
also my custom rendering web view class
public class CustomWebView : WebView
{
public static readonly BindableProperty UriProperty = BindableProperty.Create<CustomWebView, string>(p => p.Uri, default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
}
How to Achive this
Instead of using the gesture recognizer on your webview, you can use the 'Focused' event of your view to display your button. You can do something like this:
var wb = new WebView
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Source = "https://stackoverflow.com/questions/56320611/webview-gesturerecognition-not-working-in-xamarin-forms",
};
wb.Focused += (s, e) =>
{
//Handle your logic here!
wb.Unfocus();
};
Here, Unfocus() is used if you wish to implement your logic everytime the webview is tapped.
A WebView is used in my application to display formatted text. Tapping the text should open an editor to modify the text. The suggested Focused event works on Android but not iOS (as of iOS 15.0 simulator at least). I found the solution in the comments for https://bugzilla.xamarin.com/42/42596/bug.html#c4. Adding an empty label to the xaml as a transparent overlay of the WebView registers the tap event and enables the gesture recogniser.
<Grid HeightRequest="132">
<WebView Grid.Column="0" Grid.Row="0"
Source="{Binding FormattedDescription, Converter={tr:StringToWebViewSourceConverter}}"
HeightRequest="132"/>
<Label Grid.Column="0" Grid.Row="0" Text=""
HeightRequest="132" HorizontalOptions="Fill">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding EditDescriptionCommand}"/>
</Label.GestureRecognizers>
</Label>
</Grid>
The interface of my app is divided into a header (it is a webview) and absolute content, which among other things contains a second webview.
In vertical orientation it works and looks perfect.
But when I turn the device horizontally the header stops measuring 70 and measures something like 30 ....
The header reduces the height although it has a fixed height.
Why this happen? Any solution?
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PruebaHeight"
x:Class="PruebaHeight.MainPage">
<ContentPage.Content>
<StackLayout Spacing="0">
<WebView x:Name="webview_header" HorizontalOptions="FillAndExpand" HeightRequest="70" BackgroundColor="Red"/>
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="Black">
<!-- other things -->
<ScrollView AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All" BackgroundColor="Green">
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Padding="0" BackgroundColor="Purple">
<WebView x:Name="webview" AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All" BackgroundColor="Blue" />
</AbsoluteLayout>
</ScrollView>
</AbsoluteLayout>
</StackLayout>
</ContentPage.Content>
You could try to custom a view like following code.
XamWebView.cs
public class XamWebView: WebView
{
}
Then use it in your code.
var webview= new XamWebView();
webview.HorizontalOptions = LayoutOptions.Fill;
webview.VerticalOptions = LayoutOptions.StartAndExpand;
webview.WidthRequest = 70;
webview.HeightRequest = 70;
webview.Source = "https://www.google.com/";
Creating the Custom Renderer on Android(you could get the value of heightrequest when you running)
using WebView = Android.Webkit.WebView;
[assembly: ExportRenderer (typeof(XamWebView), typeof(XamWebViewRenderer))]
namespace Core.Droid
{
public class XamWebViewRenderer : WebViewRenderer
{
static XamWebView _xwebView = null;
WebView _webView;
public XamWebViewRenderer(Context context) : base(context)
{
}
class XamWebViewClient : Android.Webkit.WebViewClient
{
public override async void OnPageFinished(WebView view, string url)
{
if (_xwebView != null)
{
int i = 10;
while (view.ContentHeight == 0 && i-- > 0)
await System.Threading.Tasks.Task.Delay(100);
_xwebView.HeightRequest = view.ContentHeight;
}
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
_xwebView = e.NewElement as XamWebView;
_webView = Control;
if (e.OldElement == null)
{
_webView.SetWebViewClient(new XamWebViewClient());
}
}
}
}
I have the following XAML. I want to target phones with a scrollview, and want scrolling disabled on a tablet.
<ScrollView InputTransparent="False" Orientation="Both" >
<ScrollView.IsEnabled>
<OnIdiom x:TypeArguments="x:Boolean">
<OnIdiom.Phone>True</OnIdiom.Phone>
<OnIdiom.Tablet>True</OnIdiom.Tablet>
</OnIdiom>
</ScrollView.IsEnabled>
<StackLayout VerticalOptions="FillAndExpand" BackgroundColor="White" >
<StackLayout.HorizontalOptions>
<OnIdiom x:TypeArguments="LayoutOptions">
<OnIdiom.Tablet>FillAndExpand</OnIdiom.Tablet>
<OnIdiom.Phone>Start</OnIdiom.Phone>
</OnIdiom>
</StackLayout.HorizontalOptions>
<Grid BackgroundColor="White" HeightRequest="65" MinimumHeightRequest="65">
<Grid.HorizontalOptions>
<OnIdiom x:TypeArguments="LayoutOptions">
<OnIdiom.Tablet>CenterAndExpand</OnIdiom.Tablet>
<OnIdiom.Phone>Start</OnIdiom.Phone>
</OnIdiom>
</Grid.HorizontalOptions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<WebView x:Name="webViewBtn1" HeightRequest="65" Grid.Column="0" Grid.ColumnSpan="1" VerticalOptions="FillAndExpand" BackgroundColor="White">
<WebView.HorizontalOptions>
<OnIdiom x:TypeArguments="LayoutOptions">
<OnIdiom.Tablet>CenterAndExpand</OnIdiom.Tablet>
<OnIdiom.Phone>Start</OnIdiom.Phone>
</OnIdiom>
</WebView.HorizontalOptions>
<WebView.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Tablet>770</OnIdiom.Tablet>
<OnIdiom.Phone>300</OnIdiom.Phone>
</OnIdiom>
</WebView.WidthRequest>
</WebView>
<Button Grid.Column="0" Grid.ColumnSpan="1" x:Name="btn1" Clicked="btn1_Clicked" BackgroundColor="Transparent" TextColor="Transparent" BorderColor="White" />
</Grid>
</StackLayout>
</ScrollView>
the buttons no longer allow the user to click on them if I set ScrollView.IsEnabled the following way:
<OnIdiom.Tablet>False</OnIdiom.Tablet>
My assumption that using InputTransparent was not correct. Is there a way to make the buttons clickable inside a scroll view that has scrolling disabled?
I essentially am looking for something like Orientation=None, but that is not an option.
You need to write a CustomRenderer for disabling the scroll.
On iOS UIScrollView has a ScrollEnabled property
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
// IsScrollEnabled just a custom property
// handled it in OnPropertyChanged too
ScrollEnabled = Element.IsScrollEnabled;
}
Android it is a bit tricky, there is not direct property. We intercept the touch event and return without handling it.
public override bool OnInterceptTouchEvent(MotionEvent ev)
{
if (Element.IsScrollEnabled)
{
return base.OnInterceptTouchEvent(ev);
}
else
{
return false;
}
}
public override bool OnTouchEvent(MotionEvent ev)
{
if (Element.IsScrollEnabled)
{
return base.OnTouchEvent(ev);
}
else
{
return false;
}
}
I ended up using this approach to disable vertical scrolling on an iPad, which is my target device. Not perfect for android 7 inch tablets, but oh well:
<ScrollView.Orientation>
<OnPlatform x:TypeArguments="ScrollOrientation">
<On Platform="iOS">
<OnIdiom x:TypeArguments="ScrollOrientation">
<OnIdiom.Phone>Both</OnIdiom.Phone>
<OnIdiom.Tablet>Horizontal</OnIdiom.Tablet>
</OnIdiom>
</On>
<On Platform="Android">
<OnIdiom x:TypeArguments="ScrollOrientation">
<OnIdiom.Phone>Both</OnIdiom.Phone>
<OnIdiom.Tablet>Both</OnIdiom.Tablet>
</OnIdiom>
</On>
<On Platform="UWP">Both</On>
</OnPlatform>
</ScrollView.Orientation>
In the latest version of Xamarin Forms, you can set the Orientation to Neither.
scrollV.Orientation = ScrollOrientation.Neither;
Cool and compact way to disable scrolling in Xamarin Forms without affecting it's children through ScrollEnabled extension method:
public static class ScrollViewEx
{
/// <summary>
/// Disables scrollview by modifying Scrolled Event and attaching itself to ScrollView's binding context
/// Scrolled event sends it back to the original x,y
/// </summary>
public class DisabledScrollClass : IDisposable
{
private double ScrollX;
private double ScrollY;
private object OldContext;
private ScrollView Parent;
public DisabledScrollClass(ScrollView parent)
{
Parent = parent;
ScrollX = parent.ScrollX;
ScrollY = parent.ScrollY;
OldContext = parent.BindingContext;
parent.Scrolled += Scrolled;
parent.BindingContext = this;
}
private void Scrolled(object sender, ScrolledEventArgs e)
{
(sender as ScrollView)?.ScrollToAsync(ScrollX, ScrollY, false);
}
public void Dispose()
{
Parent.Scrolled -= Scrolled;
Parent.BindingContext = OldContext;
}
}
public static ScrollView ScrollEnabled(this ScrollView scroll, bool isEnabled)
{
DisabledScrollClass binding = scroll.BindingContext as DisabledScrollClass;
if (isEnabled && binding != null)
binding.Dispose();
if (!isEnabled && binding == null)
_ = new DisabledScrollClass(scroll);
return scroll;
}
}
I am trying to build a marquee for ios so I have written a custom Label render and used animation to achieve marquee and I am calling custom Label inside a stackLayout(stackLayout is inside a ViewCell of List). this StackLayout has a gesture Recogniser.
On click I want Marquee to get called every time so I can start and stop marquee on the gesture click.Renderer is not being called every time we click the view?
It only gets called when the ViewModel constructor is called. How do I make the renderer get called everytime I click on the gesture of Stack Layout. Below is the code I have tried.
Xaml Page:
<DataTemplate>
<ViewCell>
<StackLayout x:Name="MarqueeLabelGestureView" HorizontalOptions="FillAndExpand">
<controls:MarqueeLabelLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference ResourceListView}, Path=BindingContext.OnMarqueeClicked}" CommandParameter="{Binding .}" />
</StackLayout.GestureRecognizers>
</StackLayout>
</ViewCell>
</DataTemplate>
Custom Render Code:
namespace VCS.FieldManager.UI.iOS.CustomRenderer
{
public class CustomLabelRender:LabelRenderer
{
public CustomLabelRender()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
UILabel marqueelabel = Control;
marqueelabel.Frame = new CGRect(40, 40, marqueelabel.Frame.X + 200, 40);
MessagingCenter.Send("", "OpenMarqueeLabel");
if (!GridEntryViewModel.isMarqueeClicked)
{
UIView.Animate(6, 0, UIViewAnimationOptions.CurveLinear| UIViewAnimationOptions.Repeat,
() =>
{
UIView.SetAnimationRepeatCount(1);
marqueelabel.Transform = CoreGraphics.CGAffineTransform.MakeTranslation(-100,0);
}, null);
// marqueelabel.Lines = 1200;
}
}
}
}
}