I have this Xamain.Forms app where I hide page title when the device orientation changes. It all works fine but on Android a white space is showing above the content when I switch to horizontal view. You can see how it looks in the pictures below.
enter image description here
enter image description here
This is my xaml code:
<?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="Kanal10Live.VideoTest">
<ContentPage.Content>
<StackLayout x:Name="VideoStack">
<WebView x:Name="Browser" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></WebView>
</StackLayout>
</ContentPage.Content>
And this is code behind:
private double width = 0;
private double height = 0;
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
switch (Device.RuntimePlatform)
{
case Device.Android:
if (width != this.width || height != this.height)
{
this.width = width;
this.height = height;
if (width > height)
{
NavigationPage.SetHasNavigationBar(this, false);
VideoStack.Orientation = StackOrientation.Horizontal;
}
else
{
NavigationPage.SetHasNavigationBar(this, true);
VideoStack.Orientation = StackOrientation.Vertical;
}
}
break;
}
}
The funny thing is that if I use the below code when the page initializes all is fine.
If someone can help me I would be grateful!
Peter
Try:
<Grid>
<WebView x:Name="Browser" />
</Grid>
Grid by default fills the full page. If you don't set any horizontal or vertical options on the web view it should fill the whole grid.
Related
Give a try to add a label and add a long text against the property FormattedText - and set the LineBreakMode="TailTruncation". You will find that it's not adding the expected ellipses. But if you use the "Text" property it works fine. I still need to stick to this FormattedText property as we are achieving some formatting through this. Is there any alternative way to address this linebreak issue with FormattedText -
Example: "I need to show for long sample text with ellipses like in this example..."
<Grid Padding=" 0,50,0,0" HorizontalOptions="StartAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height ="*"/>
</Grid.RowDefinitions>
<StackLayout>
<Label x:Name="label" FormattedText ="testing this big text as a sample which needs to get truncated at any cost" LineBreakMode="TailTruncation"/>
</StackLayout>
</Grid>
The ellipses will appear when the content of the Label beyond it's border . I set the UnderLine in FormattedText and it works fine in my project .
NSMutableAttributedString str = new NSMutableAttributedString("I need to show for long sample text with ellipses like in this example...");
UIStringAttributes attributes = new UIStringAttributes() { UnderlineStyle = NSUnderlineStyle.Double,UnderlineColor=UIColor.Red, };
str.AddAttributes(attributes, new NSRange(0, str.Length - 1));
label.AttributedText = str;
label.LineBreakMode = UILineBreakMode.TailTruncation;
Update
in Forms you could use Custom Renderer .
Add the following class in your iOS project
using UIKit;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using xxx.iOS;
[assembly:ExportRenderer(typeof(Label),typeof(MyLabelRenderer))]
namespace xxx.iOS
{
public class MyLabelRenderer: LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.LineBreakMode = UILineBreakMode.TailTruncation;
}
}
}
}
I'm fairly new to this, so sorry if this is a dumb question. How do I get my Xamarin.Forms app to start below the status bar or the notch when applicable? I've tried using a NavigationPage, but then it started wear below the top of the screen. I've also seen a few other solutions, but I can't make it work.
Can anyone help?
Thanks!
use UseSafeArea
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
using Xamarin.Forms;
namespace iPhoneX
{
public partial class ItemsPage : ContentPage
{
public ItemsPage()
{
InitializeComponent();
On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true);
}
}
}
You'll need to consider the safe area but have the background colors expand to take the full screen. So you shouldn't use
On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true);
this will box your page with large empty spaces on the bottom and top edges.
Instead, you should measure the safe areas and apply it as padding to your root view.
[assembly: ResolutionGroupName("Enterprise")]
[assembly: ExportEffect(typeof(SafeAreaPaddingEffect), nameof(SafeAreaPaddingEffect))]
namespace Enterprise.iOS.Effects
{
class SafeAreaPaddingEffect : PlatformEffect
{
Thickness _padding;
protected override void OnAttached()
{
if (Element is Layout element)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
_padding = element.Padding;
var insets = UIApplication.SharedApplication.Windows[0].SafeAreaInsets; // Can't use KeyWindow this early
if (insets.Top > 0) // We have a notch
{
element.Padding = new Thickness(_padding.Left + insets.Left, _padding.Top + insets.Top, _padding.Right + insets.Right, _padding.Bottom);
return;
}
}
// Uses a default Padding of 20. Could use an property to modify if you wanted.
element.Padding = new Thickness(_padding.Left, _padding.Top + 20, _padding.Right, _padding.Bottom);
}
}
protected override void OnDetached()
{
if (Element is Layout element)
{
element.Padding = _padding;
}
}
}
}
then in xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Enterprise.View.Features.Authentication.LoginView"
xmlns:effect="clr-namespace:Enterprise.View.Effects">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentView BackgroundColor="Green">
<ContentView.Effects>
<effect:SafeAreaPaddingEffect />
</ContentView.Effects>
<Label Text="Hello, from XamarinHelp.com" />
</ContentView>
</Grid>
</ContentPage>
ref: https://xamarinhelp.com/safeareainsets-xamarin-forms-ios/ Thank Adam, not me!
is it possible to make one thing on the screen expand all the way to the edges?
(from this answer)
Stretching elements out of the bounds of the safe area is arguably a use case in the case you provided. The bar is a mere background element and not content, as the navigation bar is, which also stretches to fill the whole screen.
Having said that, you unfortunately don't get this for free, but have to implement this by yourself. Assume you have the following XAML
<ContentPage ...>
<StackLayout>
<ContentView BackgroundColor="LightSkyBlue" HorizontalOptions="Fill" x:Name="Header">
<!-- Header -->
</ContentView>
<ContentView x:Name="Content">
<!-- Content -->
</ContentView>
</StackLayout>
</ContentPage>
In your code-behind (I would not use it like this, but to make the point it suffices. For a real application I have written a utility class, which is attached to the view and manages the insets.) you can now check for the property SafeAreaInsets being changed
class SafeAreaPage : ContentPage
{
// elided constructor
protected override void OnPropertyChanged(string propertyName)
{
if(propertyName = "SafeAreaInsets")
{
var insets = On<Xamarin.Forms.PlatformConfiguration.iOS>.GetSafeAreaInsets();
var headerInsets = insets; // Thickness is a value type
headerInsets.Bottom = 0;
var contentInsets = insets;
contentInsets.Top = 0;
Header.Padding = headerInsets;
Content.Padding = contentInsets;
}
}
}
How you set the Paddings of your views depends on your layouts, but this way you have a bit more control on how the safe area insets are used, although it is a bit fiddly.
I have a frame in absolutelayout as shown below. I would like that user to be able drag and relocate this frame on the screen. I tried to implement a pan gesture but unfortunately it doesnt work as expected. Can somebody show me the correct way? Is it possible without using any 3rd party library?
<AbsoluteLayout>
<Frame x:Name="frm" Padding="1" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0.5,0,0.3,0.3" IsVisible="{Binding IsSmallTimerVisible}" >
<Frame.GestureRecognizers>
<PanGestureRecognizer PanUpdated="OnPanUpdated" />
</Frame.GestureRecognizers>
<shared:_customControl/>
</Frame>
Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<Grid.RowDefinitions>
<RowDefinition Height="0.1*" />
<RowDefinition Height="0.3*" />
<RowDefinition Height="2.5*" />
</Grid.RowDefinitions>
And in the code behind
double x, y;
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Running:
// Translate and ensure we don't pan beyond the wrapped user interface element bounds.
Content.TranslationX =
Math.Max(Math.Min(0, x + e.TotalX), -Math.Abs(Content.Width - App.ScreenWidth));
Content.TranslationY =
Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs(Content.Height - App.ScreenHeight));
break;
case GestureStatus.Completed:
{
// Store the translation applied during the pan
x = Content.TranslationX;
y = Content.TranslationY;
AbsoluteLayout.SetLayoutBounds(frm, new Rectangle(x, y, .3, .3));
break;
}
}
}
Seem like what you need is a Touch Tracking Effect
This example is very similar with your requirement.
void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{
BoxView boxView = sender as BoxView;
switch (args.Type)
{
case TouchActionType.Pressed:
// Don't allow a second touch on an already touched BoxView
if (!dragDictionary.ContainsKey(boxView))
{
dragDictionary.Add(boxView, new DragInfo(args.Id, args.Location));
// Set Capture property to true
TouchEffect touchEffect = (TouchEffect)boxView.Effects.FirstOrDefault(e => e is TouchEffect);
touchEffect.Capture = true;
}
break;
case TouchActionType.Moved:
if (dragDictionary.ContainsKey(boxView) && dragDictionary[boxView].Id == args.Id)
{
Rectangle rect = AbsoluteLayout.GetLayoutBounds(boxView);
Point initialLocation = dragDictionary[boxView].PressPoint;
rect.X += args.Location.X - initialLocation.X;
rect.Y += args.Location.Y - initialLocation.Y;
AbsoluteLayout.SetLayoutBounds(boxView, rect);
}
break;
case TouchActionType.Released:
if (dragDictionary.ContainsKey(boxView) && dragDictionary[boxView].Id == args.Id)
{
dragDictionary.Remove(boxView);
}
break;
}
}
The Pressed logic sets the Capture property of the TouchEffect object
to true. This has the effect of delivering all subsequent events for
that finger to the same event handler.
The Moved logic moves the BoxView by altering the LayoutBounds
attached property. The Location property of the event arguments is
always relative to the BoxView being dragged, and if the BoxView is
being dragged at a constant rate, the Location properties of the
consecutive events will be approximately the same. For example, if a
finger presses the BoxView in its center, the Pressed action stores a
PressPoint property of (50, 50), which remains the same for subsequent
events. If the BoxView is dragged diagonally at a constant rate, the
subsequent Location properties during the Moved action might be values
of (55, 55), in which case the Moved logic adds 5 to the horizontal
and vertical position of the BoxView. This moves the BoxView so that
its center is again directly under the finger.
You can move multiple BoxView elements simultaneously using different
fingers.
I'm new in using Titanium. I tried to load some images into a scrollview. But only one image is loading into the scrollview area. Codes are here
XML
<Alloy>
<Window class="container">
<ScrollView showHorizontalScrollIndicator="true" id="Scroll" layout="horizontal">
</ScrollView>
</Window>
</Alloy>
JS
var scrollView = $.Scroll;
var URLs = ["http://static.flickr.com/41/81743961_588dafe12d_o_d.jpg", "http://static.flickr.com/26/64914466_eed02e2a71_o_d.jpg"];
var Views = [];
for (i =0; i < URLs.length ; i++){
Views.push(Ti.UI.createImageView({
image : URLs[i],
width : Ti.UI.SIZE,
height : 300,
top : 0,
left : 0,
})
);
}
Views.forEach(function(view){
scrollView.add(view);
});
$.index.open();
TSS
".container": {
backgroundColor:"white"
},
"#Scroll":{
width:Ti.UI.SIZE,
top: 50,
}
Screenshot
I need your help to find out my mistake.
Thanks
Its in your XML file :
<Alloy>
<Window class="container">
<ScrollView showHorizontalScrollIndicator="true" id="Scroll" layout="horizontal">
</ScrollView>
</Window>
you have set the layout to horizontal, If you will scroll horizontally you will find your second Image there.
Or you can change
horizontal to vertical
The Image will appear below the first Image.
checkout the docs.
Hope it helps.
I am using Xamarin.Forms and have created a ScrollView, which contains a horizontal StackLayout. I want to be able to scroll horizontally, so I set:
Orientation = ScrollOrientation.Horizontal;
But I don't get horizontal scroll. The content of the StackLayout is wider than the screen, and I see the content is being clipped at the edge.
How do I achieve horizontal scroll with Xamarin.Forms ?
This is how I got it to work
var scrollView = ScrollView
{
HorizontalOptions = LayoutOptions.Fill,
Orientation = ScrollOrientation.Horizontal,
Content = new StackLayout{
Orientation = StackOrientation.Horizontal,
Children = {}
}
};
This nuget package will work:
https://github.com/SuavePirate/DynamicStackLayout
The property Words is a list of strings:
<ScrollView Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<dynamicStackLayout:DynamicStackLayout ItemsSource="{Binding Words}" HorizontalOptions="Fill" Orientation="Horizontal" Padding="10, -0, 50, 10">
<dynamicStackLayout:DynamicStackLayout.ItemTemplate>
<DataTemplate>
<StackLayout BackgroundColor="Gray" WidthRequest="80" HeightRequest="80">
<Label Text="{Binding .}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" />
</StackLayout>
</DataTemplate>
</dynamicStackLayout:DynamicStackLayout.ItemTemplate>
</dynamicStackLayout:DynamicStackLayout>
</ScrollView>
I hope it helps :)
If you're using the templates in Visual Studio 2013 for Xamarin apps, the version of Xamarin.Forms is a bit outdated and does not support scrolling. To fix this, just nuget 'update-package' and this code
public class MainPage : ContentPage
{
public MainPage()
{
Label label = new Label {
Text = "This is a very long label which I expect to scroll horizontally because it's in a ScrollView.",
Font = Font.SystemFontOfSize(24),
};
this.Content = new ScrollView {
Content = label,
Orientation = ScrollOrientation.Horizontal,
};
}
}
code will work fine on android.
For iOS, the code will work as expected.
Unfortunately, at date, for WP8 there's a bug and the hack is to add a custom renderer.
using System.Windows.Controls;
using App2.WinPhone;
using Xamarin.Forms;
using Xamarin.Forms.Platform.WinPhone;
[assembly: ExportRenderer(typeof(ScrollView), typeof(FixedSVRenderer))]
namespace App2.WinPhone
{
public sealed class FixedSVRenderer : ScrollViewRenderer
{
protected override void OnModelSet()
{
base.OnModelSet();
if (Model.Orientation == ScrollOrientation.Horizontal)
{
// Enable horiz-scrolling
Control.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
}
}
}
}