I have different elements, controls and views wrapped in frames in order to apply corner radius, which is working fine on Android. But on the iOS side, even though the frame is round cornered, its contents does not clip to its radius but stays square as if nothing is applied.
Sample:-
<Frame BackgroundColor="{DynamicResource Theme}" CornerRadius="15" Padding="0">
<Image Source="{Binding PImage}" HeightRequest="132.5" Aspect="AspectFill"/>
</Frame>
Expected (Which happens in Android):-
Actual:-
How to make the frame contents respect the corner radius like what happens in Android ?
Clip the content of the frame to its boundaries:
<StackLayout Padding="30">
<Frame CornerRadius="30" Padding="0" IsClippedToBounds="True">
<Image Source="https://aka.ms/campus.jpg" />
</Frame>
</StackLayout>
https://stackoverflow.com/a/55611485/1039935
From shared code works in my local site :
The sample solution : Have a check with the version of Visual Studio and Xamarin Forms .Be sure that have updated to the latest version (Visual Studio: 16.6.5, Xamarin Forms : 4.7.0.1239).
Otherwise , you can create a Custom Frame Renderer in iOS to set CornerRadius .
Create a CustomFrame :
public class CustomFrame: Frame
{
}
Create a Custom renderer in iOS:
public class CustomFrameRenderer : FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
Layer.CornerRadius = Element.CornerRadius;
//Layer.CornerRadius = 15;
Layer.MasksToBounds = true;
}
}
In Xaml use the custom Renderer :
<local:CustomFrame BackgroundColor="CadetBlue"
Padding="0">
<Image Source="XamarinLogo.png"
HeightRequest="132.5"
Aspect="AspectFill" />
</local:CustomFrame>
Related
I'm trying to load street map using Xamarin.Forms.Map plugin in my project for UWP app. For that I have also get the token from MSDN. Here is what I have done:
MapePage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:Map_POC.ViewModels"
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
xmlns:local="clr-namespace:Map_POC.CustomControls"
x:Class="Map_POC.Views.MapePage">
<ContentPage.BindingContext>
<vm:MapePageViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<maps:Map
x:Name="MyMap"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
MapType="Street" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
MapePage.xaml.cs
public MapePage()
{
InitializeComponent();
Position position = new Position(-37.8141, 144.9633);
var pin = new Pin
{
Type = PinType.Place,
Position = position,
Label = "I'm a Pin",
};
MyMap.Pins.Add(pin);
MyMap.MoveToRegion(
MapSpan.FromCenterAndRadius(
position, Distance.FromMiles(1)));
}
MainPage.xaml.cs (In UWP Solution)
public sealed partial class MainPage
{
public MainPage()
{
this.InitializeComponent();
Xamarin.FormsMaps.Init(Keys.UWPMapToken);
Windows.Services.Maps.MapService.ServiceToken = Keys.UWPMapToken;
LoadApplication(new Map_POC.App());
}
}
Output: With hybrid map it shows map but not showing pin and locations properly.
Other thing apart from this it not works in offline mode, can we cache map for offline mode?
Can we draw a polygon and coordinates covered inside the polygon can be clicked individually or not?
Any help on this will be highly appreciated.
I have a StackLayout and a number of elements inside (buttons, texts etc).
I want the ActivityIndicator to overlay the entire screen and make it not able to do anything to those elements.
I have put ActivityIndicator inside the StackLayout but wrapped it with AbsoluteLayout thinking that AbsoluteLayout can easitly overlap everything:
<StackLayout>
<AbsoluteLayout>
<ActivityIndicator ... />
</AbsoluteLayout>
<...other elements...>
</StackLayout>
Instead activity indicator is displayed at the top of the StackLayout and other elements are available for affecting. I'm new in Xamarin and layouts, what am I doing wrong? All samples in the Internet have single ActivityIndicator per page...
It is better said that an AbsoluteLayout's children can easily overlap each other. Just as a StackLayout lets you stack controls inside , vertically or horizontally, an AbsoluteLayout lets you position controls inside using absolute or proportional values, thus if two controls have the same absolute positioning set, they will overlap 100%.
Therefore, you want to wrap your StackLayout and another StackLayout that has your ActivityIndicator inside an AbsoluteLayout using proportional sizing, e.g:
<AbsoluteLayout>
<StackLayout
x:Name="mainLayout"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All" >
<Label Text="Welcome to Xamarin.Forms!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Do Something"
Clicked="DoSomethingBtn_Clicked" />
</StackLayout>
<StackLayout
x:Name="aiLayout"
IsVisible="False"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Gray" Opacity="0.5">
<ActivityIndicator
x:Name="ai"
IsRunning="False"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
Color="Black"/>
</StackLayout>
</AbsoluteLayout>
The above sets the two StackLayouts to both take up the full size of the parent container of the AbsoluteLayout, which is presumably a Page. The StackLayout that has the indicator is initially hidden. IN the page code behind for the above example, I show the second StackLayout and start the activity indicator and show it for 2 seconds, and then hide it again:
private async void DoSomethingBtn_Clicked(object sender, EventArgs e)
{
ai.IsRunning = true;
aiLayout.IsVisible = true;
await Task.Delay(2000);
aiLayout.IsVisible = false;
ai.IsRunning = false;
}
Here is what it looks like:
And since the second StackLayout completely covers the first, none of the controls in the first StackLayout are clickable.
Might be worth going over the docs for the AbsoluteLayout to understand the AbsoluteLayout.LayoutBounds and AbsoluteLayout.LayoutFlags:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/absolute-layout
If you want to "overlap", you need to be outside of the StackLayout. A Grid is the most common control for this:
<Grid>
<StackLayout>
<...other elements...>
</StackLayout>
<ActivityIndicator ... />
</Grid>
Here's a hacked-up control for making things full-screen via the horribly-named RelativeLayout (tested in Android only)
[ContentProperty("ContentInner")]
public class FullScreenLayout : ContentView
{
public View ContentInner
{
get => ((RelativeLayout) Content).Children[0];
set
{
var display = DeviceDisplay.MainDisplayInfo;
var screenWidth = display.Width / display.Density;
var screenHeight = display.Height / display.Density;
var wrapper = new RelativeLayout();
wrapper.Children.Add(value, () => new Rectangle(0, 0, screenWidth, screenHeight));
Content = wrapper;
}
}
}
It can be used like this:
<controls:FullScreenLayout>
<!-- Anything you want fullscreen here -->
</controls:FullScreenLayout>
Unfortunately, if you use NavigationPage, this won't overlap the navigation bar. Every other solution currently on this page has the same issue. According to this question, it's not possible to solve this without using platform-specific customer renderers. Ugh.
If you don't mind the page being dimmed, you can use Rg.Plugins.Popup which implements the custom renderers needed.
I ended up solving my similar problem (dimming most of the screen) by implementing a custom renderer for the navigation page itself.
In our application we have some controls that are Entry controls that take in numbers, so we want the user to be able to type into them. Other controls are popup selections such as a Date, or a Picker control, of which we code as Label controls.
To give the user the same consistency as Entry controls, for iOS we put the same frames around them as an Entry control in iOS such as this:
Standard Entry Control Xaml:
<Entry Grid.Row="0" Grid.Column="1" Keyboard="Numeric" ReturnType="Done" WidthRequest="60"
Text="{Binding SocketItem.QuantityPerSys, Converter={StaticResource IntComma}}"
TextChanged="OnIntegerEntryChanging" Placeholder="0"
AutomationId="SocketQtySysValueEntry" />
Mimic'ed Entry Control for iOS Rendering:
<Frame Grid.Row="1" Grid.Column="1" AutomationId="SocketDecisionDateEntryFrame">
<Label Text="{Binding SocketItem.DecisionDate, StringFormat='{0:M/d/yy}', Converter={StaticResource LocalTime}}"
HorizontalTextAlignment="Center" HorizontalOptions="FillAndExpand" AutomationId="SocketDecisionDateValueEntry"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="OnSocketDateTapped" CommandParameter="DecisionDate" />
</Frame.GestureRecognizers>
</Frame>
However in Android the Entry controls have a line underneath them:
Android Entry Control
We want to render these label controls the same as the Entry controls so they are consistent:
Label and Entry controls
My assumption is that I have to use a custom renderer of which I already have setup, but with just a normal underline of the text (which is of course what I don't want):
class UnderlinedLabelRenderer : LabelRenderer
{
public UnderlinedLabelRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null && Control is FormsTextView textView)
{
textView.PaintFlags |= PaintFlags.UnderlineText;
}
}
}
I've tried investigating the actual Xamarin.Forms renderer code for the Entry control, but I'm not familiar enough with it or know exactly which class to look at to figure it out (I'll continue that route in the mean time). I am assuming I'll have to somehow add a new box control to the label cell or something.
I've also looked at this question: Xamarin Forms Android EntryCell Underline which is related but the opposite of what I want to do.
I also tried making the controls disabled Entry controls:
<StackLayout Grid.Row="1" Grid.Column="1" HorizontalOptions="End" AutomationId="OppApplicationValueFrame">
<controls:ReadonlyEntry Text="{Binding Opportunity.Application}" IsEnabled="False"
AutomationId="OppApplicationValueEntry"/>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="OnApplicationTapped" />
</StackLayout.GestureRecognizers>
</StackLayout>
but that yielded light gray text (due to the disabled). I then created a custom renderer to fix the text:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null && Control is FormsEditText editText)
{
editText.SetTextColor(Android.Graphics.Color.Gray);
//editText.SetBackgroundColor(Android.Graphics.Color.Gray);
}
}
but the underline on the control is still light grey (disabled color). I referenced this question on how to remove the underline: Xamarin Forms Android EntryCell Underline. But doing the opposite of setting it to another color makes the entire cell Gray.
How do I change the color of the underline in the CustomRenderer?
Any help would be great or a place to start looking.
I think the easiest way to achieve your requirement is to use a Entry instead of a Label, disable the edit ability of the entry and add a TapGestureRecognizers there to handle event:
<StackLayout>
<Entry IsEnabled="False" Text="test" HorizontalTextAlignment="Center" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" NumberOfTapsRequired="1" />
</StackLayout.GestureRecognizers>
</StackLayout>
And I don't think you can achieve this by using a custom renderer of Lable, native TextView does not has this feature.
Another way is to create a custom control, like a view contains a label and a view(height =1) with black background color which stay under the label.
Update:
Code in the custom renderer to change the color of underline:
[assembly: ExportRenderer(typeof(myEntry), typeof(MyEntryRenderer))]
namespace App557.Android
{
class MyEntryRenderer : EntryRenderer
{
public MyEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
EditText editText = Control as EditText;
editText.Enabled = false;
editText.SetTextColor(global::Android.Graphics.Color.LightGreen);
editText.Background.SetColorFilter(global::Android.Graphics.Color.LightGreen, PorterDuff.Mode.SrcIn);
editText.SetSingleLine(true);
editText.Ellipsize = TruncateAt.End;
}
}
}
}
I used to use the Frame control of Xamarin.Forms as a CardView for Android, but I updated the Xamarin.Forms package to version 3.1.0 and the frame appearence has changed. It doesn't have elevation and shadows. I tried to create a custom renderer, but doesn't work.
To explain what I'm trying to say, see the pictures below. First picture is the old behaviour of frame. The appearence is exactly like CardView in Android and the second picture is the new behaviour, for the version 3.1.0 of Xamarin.Forms. The frame doesn't have elevation and shadows.
Old behaviour:
New behaviour
Here is my code that I use the Frame (for Android Platform, CardView is a simple frame)
<customViews:CardView>
<StackLayout Spacing="0">
<StackLayout.Margin>
<OnPlatform x:TypeArguments="Thickness" Android="16"/>
</StackLayout.Margin>
<ContentView>
<OnPlatform x:TypeArguments="View">
<OnPlatform.iOS>
<customViews:HeaderDivider/>
</OnPlatform.iOS>
</OnPlatform>
</ContentView>
public class CardView : Frame
{
public CardView()
{
Padding = 0;
if (Device.RuntimePlatform == Device.iOS)
{
HasShadow = false;
OutlineColor = Color.Transparent;
BackgroundColor = Color.Transparent;
}
}
}
<Frame HasShadow="true">
<Label Text="Test"/
</Frame>
I guess after Update default value for HasShadow in Frame is set to false;
I am new to Xamarin. I am trying to create a sample in Xamarin forms with 5 custom horizontallistviews (I have used renderers to achieve the same in different platforms. It works perfectly (scrolls horizontally) when I have only 2 of these controls on screen. When I add all the 5 I have to add these controls inside a ScrollView oriented vertically so that I can see all the controls. When I do that I am only able to scroll the page vertically. I am not able to scroll the individual controls (horizontallistviews) horizontally.
This issue is only with Android. It works fine in Windows Phone.
Below is my code:
<ScrollView Orientation="Vertical">
<StackLayout Padding="5, 25" Orientation="Vertical" VerticalOptions="FillAndExpand">
<Image Source ="label_entertainment.png" HorizontalOptions="Start"/>
<local:HorizontalListViewEntertainment x:Name="entertainmentView" Items="{Binding Entertainment}" HeightRequest="198"/>
<Image Source ="label_music.png" HorizontalOptions="Start"/>
<local:HorizontalListViewMusic x:Name="musicListView" Items="{Binding Music}" HeightRequest="198"/>
<Image Source ="label_movies.png" HorizontalOptions="Start"/>
<local:HorizontalListViewMovies x:Name="movieListView" Items="{Binding Movies}" HeightRequest="198"/>
<Image Source ="label_celebrities.png" HorizontalOptions="Start"/>
<local:HorizontalListViewCelebrities x:Name="celebritiesListView" Items="{Binding Celebrities}" HeightRequest="198"/>
<Image Source ="label_style.png" HorizontalOptions="Start"/>
<local:HorizontalListViewStyle x:Name="styleListView" Items="{Binding Celebrities}" HeightRequest="198"/>
</StackLayout>
</ScrollView>
I found a solution here. However it doesn't work in my case because I don't have inner scroll views. Please help. Thank you!
I found the solution. I just had to add the following code to the CustomRenderer of the horizontallistviews in android.
public override bool DispatchTouchEvent(MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Down:
StartX = e.RawX;
StartY = e.RawY;
this.Parent.RequestDisallowInterceptTouchEvent(true);
break;
case MotionEventActions.Move:
if (IsHorizontal * Math.Abs(StartX - e.RawX) < IsHorizontal * Math.Abs(StartY - e.RawY))
this.Parent.RequestDisallowInterceptTouchEvent(false);
break;
case MotionEventActions.Up:
this.Parent.RequestDisallowInterceptTouchEvent(false);
break;
}
return base.DispatchTouchEvent(e);
}
Referred this
have you tried using both ScrollViewand HorizontalScrollView ? http://android-code-crumbs.blogspot.ro/2011/06/how-to-set-horizontal-and-vertical.html