I have managed to create a GridView inside a ScrollView that uses 8 rows of row height 250 (Absolute). This was fine until I realised it would not work on screens with different resolutions. How can I create a grid view where there are 8 rows, but each row takes up half the screen so you have to scroll down to see the rest? Using 8 rows of height "*" just puts 8 rows onto the view with no scrolling. I am using xaml but can use c# if necessary.
You can access the device's screen height, so calculate 0.5 * height and set this as row height:
Create a static variable in app.xaml.cs
static public int ScreenHeight;
Then you need to set the value of your variable for iOS and Android.
Android: MainActivity.cs
protected override void OnCreate(Bundle bundle)
{
base.OnCreate (bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
App MyApp = new App();
App.ScreenHeight = (int)(Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density);
}
iOS: AppDelegate.cs
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
App.ScreenHeight = (int)UIScreen.MainScreen.Bounds.Height;
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
Now, have a property in the view's ViewModel which accesses ScreenHeight and calculate it to your needs
public int HalfScreenHeight
{
get { return App.ScreenHeight / 2; }
}
Finally, you can your row's height to HalfScreenHeight.
Important: If you allow device rotation for Portrait and LandScape mode on your page, you might need to update the binding according to your needs. You can access the screen's width in the same way.
Related
I have been using SkiaSharp for a few month now and having great success on showing my drawing instructions on Android & IOS device. I am using SKCanvasView control which I am placing it inside ScrollView control. On scroll of ScrollView translating SKCanvasView to ScrollTop and ScrollLeft position so that SKCanvasView should intact with Visible region of ScrollView Control.
This is all working smoothly in Android. But in IOS device, scrolling is not smooth. Scrolling is holding by UI thread and it si not smooth. PLease have a look at the code and please suggest if you have any suggestions.
private void View_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
SKRect rect = paginatedViewProvider.GetViewPortRect();
// I have lots of image tiles which I am drawing on skbitmap and returning it. This is taking around 10ms
SKBitmap pageBitmap = GenerateSKBitmapFromIntenseCalculation();
float Top = (float)(rect.Top - scrollTop);
float Left = (float)(rect.Left - scrollLeft);
e.Surface.Canvas.DrawBitmap(pageBitmap, SKRect.Create(Left, Top, rect.Width, rect.Height));
}
private bool OnTimerTick()
{
viewPanel.InvalidateSurface();
return true;
}
In my Xamrin.Forms app i used this method for get the screen resolution: I wrote an interface with height and width properties and in the iOS rendere I used UIScreen.MainScreen.Bounds.Height and UIScreen.MainScreen.Bounds.Width. And it was ok... until about one month ago! Now, if I run my app on iPhone 5c (screen resolution declared 1136x640) the values are 568x320 whit scale 2 and if I run it on iPhone 6 (resolution declared 1334x750) the values are the same, 568x320 whit scale 2!
Does anybody know what is changed?
Thanks
No need to use dependency service to get device width & height.
Best way to get screen width & height, whenever screen height or width changes or screen is rotated OnSizeAllocated() will get fired and you will get new width & height
sample code :
using Xamarin.Forms;
namespace ABC
{
public class MyPage : ContentPage
{
private double _width;
private double _height;
public MyPage()
{
Content = new Label {
Text = "Welcome to Xamarin.Forms!"
};
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
_width = width;
_height = height;
}
}
}
I am creating one Xamarin Forms project and I got stuck in finding the current screen width according to the different device.
I know how it can be done in android and ios but need a way to find the width in portable.
You can try this Application.Current.MainPage.Width in my case this worked and i am able to find the device width in portable project itself.
I know it is an old thread but worth mentioning that recently Xamarin.Essentials NuGet pakage was released and there is a useful class DeviceDisplay in there that should handle this task for you.
The documentation can be found here.
Usage example:
// Get Metrics
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
// Orientation (Landscape, Portrait, Square, Unknown)
var orientation = mainDisplayInfo.Orientation;
// Rotation (0, 90, 180, 270)
var rotation = mainDisplayInfo.Rotation;
// Width (in pixels)
var width = mainDisplayInfo.Width;
// Width (in xamarin.forms units)
var xamarinWidth = width / mainDisplayInfo.Density;
// Height (in pixels)
var height = mainDisplayInfo.Height;
// Screen density
var density = mainDisplayInfo.Density;
Common code (in App.xaml.cs)
public static int ScreenHeight {get; set;}
public static int ScreenWidth {get; set;}
Android part (in MainActivity.cs, in the OnCreate method)
App.ScreenHeight = (int) (Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density);
App.ScreenWidth = (int) (Resources.DisplayMetrics.WidthPixels / Resources.DisplayMetrics.Density);
iOS part (in AppDelegate.cs, in the FinishedLaunching method)
App.ScreenHeight = (int)UIScreen.MainScreen.Bounds.Height;
App.ScreenWidth = (int)UIScreen.MainScreen.Bounds.Width;
So App.ScreenHeight and App.ScreenWidth will be initialized when the App will be launched, then you will be able to use them anywhere in the common code.
You can use the Width property when you are in a ContentPage. For example,
protected override void OnAppearing()
{
base.OnAppearing();
double w = this.Width;
}
Note that this is set during the Layout phase. So, you can only use it after the page is initialized, otherwise it is -1.
https://developer.xamarin.com/api/property/Xamarin.Forms.VisualElement.Width/
I would like to create a static struct in the shared code, so I can access the screen width/height values easily (as well as doing bindings in xAML).
The struct in the app namespace (e.g. in App.xaml.cs):
using System;
using Xamarin.Forms;
namespace YourAppName {
...
public struct Constant {
public static double ScreenWidth = Application.Current.MainPage.Width;
public static double ScreenHeight = Application.Current.MainPage.Height;
}
}
Retrieving screen width in C#:
var labelWidth = Constant.ScreenHeight * 0.2;
// then do something with labelWidth
Retrieving screen width in XAML:
<Label Text="Text with insane font size" FontSize="{Binding Source={x:Static local:Constant.ScreenWidth}}"/>
Another approach would be to use the override "OnSizeAllocated" for your page and then take the height and width according to the changes on the user's screen. You can create a static class to set the height and width of your screen everytime it changes and then access them from this class when needed.
The static class to set and access the device dimension:
public static class ScreenDimensions
{
public static double Height { get; set; }
public static double Width { get; set; }
}
Override to obtain the screen dimensions:
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
ScreenDimensions.Height = height;
ScreenDimensions.Width = width;
}
I Guess that the best way is use the xamarin.forms.Device information.
Size size = Device.Info.PixelScreenSize;
if (size.Width <= 720 && size.Height <= 1280)
{
stkLayoutTop.Margin = new Thickness(5, 30, 10, 0);
}
else
{
stkLayoutTop.Margin = new Thickness(5, 50, 10, 0);
}
I have been developing a Xamarin forms application. I want to increase the height of the progress bar control. I used custom renders to change the color of the progress control. But I couldn't find any way to increase the height. Please help me. following is my Custom render class.
public class MyProgressBarRenderer:ProgressBarRenderer
{
protected override void OnElementChanged (
ElementChangedEventArgs<Xamarin.Forms.ProgressBar> e)
{
base.OnElementChanged (e);
Control.ProgressTintColor = Color.FromHex ("#254f5e").ToUIColor();
}
}
Add this override to MyProgressBarRenderer, and adjust Y as necessary....
using UIKit;
using CoreGraphics;
......
public override void LayoutSubviews()
{
base.LayoutSubviews();
var X = 1.0f;
var Y = 5.0f;
CGAffineTransform transform = CGAffineTransform.MakeScale(X,Y);
this.Transform = transform;
}
There is small issue in the iOS renderer code try using
this.Control.Transform = transform;
instead of
this.Transform = transform;
Is there no possibility to read and set the position of the scrollview? For example, I would like to start the app with the scroll position at the bottom, not at the top.
You can get the X and Y position of a ScrollView from the ScrollX and ScrollY properties of the ScrollView object. Then you can set the position with the ScrollView method ScrollToAsync.
var x = scrollView.ScrollX;
var y = scrollView.ScrollY;
...
bool animate = false;
scrollView.ScrollToAsync(x, y, animate);
I've a better approach to this!
You can add this to your onAppearing() method:
protected override void OnAppearing()
{
base.OnAppearing();
/*Other stuff*/
viewModel.Messages.CollectionChanged += (sender, e) =>
{
var target = viewModel.Messages[viewModel.Messages.Count - 1];
ItemsListView.ScrollTo(target, ScrollToPosition.End, false);
};
}
This means that if your collection change, you get the target which is the last item (the one in the bottom) the you use scrollTo target, position end, with animation false.
when you get to the page it will open in the bottom, you don't see the scrolling because animation is false!
For Android, I have found a solution:
I write a custom renderer and in the OnDraw override Method, I call FullScroll(FocusSearchDirection.Down) the first time when the method is called.
What it makes easy, the Android ScrollViewRenderer is subtype of Android.Widget.ScrollView.
At the moment, I don't need an implementation for iOS, so I have no solution for iOS.