Get width of Entry in Xamarin.Forms - c#

How do I get the width of an Entry view in Xamarin.Forms? I'm trying to make an entry in iOS look like the default entry in Android (the one with the line underneath).
Custom Renderer:
void SetBorderWidth(Controls.Entry control)
{
Control.BorderStyle = UITextBorderStyle.None;
var myBox = new UIView(new CGRect(0, 40, <INSERT WIDTH HERE>, 1));
myBox.BackgroundColor = control.BorderColor.ToUIColor();
Control.AddSubview(myBox);
}
Whenever I try to insert either control.Width, control.WidthRequest, control.MinimumWidthRequest nothing happens. But if I put a number the line underneath suddenly shows.
Additionally when I print out the width and widthrequest they have a value of -1.

In your iOS Entry renderer, override the Draw method and use the CGRect provided as the current Frame size of the UITextField, since this method can be called multiple times (screen rotations, resizes, etc... Save your UIView after its initial creation and just update its Frame.
Something like (I do not have my personal code with me, but this should be "close"):
UIView myBox;
public override void Draw(CGRect rect)
{
base.Draw(rect);
switch (myBox)
{
case null:
myBox = new UIView(new CGRect(0, 40, rect.Width, 1));
Control.AddSubview(myBox);
break;
default:
myBox.Frame = new CGRect(0, 40, rect.Width, 1);
break;
}
}

Related

.net Maui Collectionview padding issue

I created a collectionview acting like a barchart diagram. For the bar display in the center of the screen, I am showing the current value for that center item. Everything works fine so far, but to be able to scroll the first or last item in the chart, to the center of the screen, i have to add padding to the beginning and end of the collection.
This chart is a migration of an old xamarin.forms app, where the padding was handle by a customerender and worked fine.
The issue i am currently seeing, is that when the collectionview´s ItemsLayout is
ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal)
the handler that i made, doesn't set the padding.
But if the
ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical)
it works fine.
I tried different approach with handlers
Microsoft.Maui.Controls.Handlers.Items.CollectionViewHandler.Mapper[nameof(IView)] = (h, v) =>
{
if (v is CollectionViewChart)
{
#if ANDROID
(h.PlatformView as Android.Views.View).SetPadding(375,0,375,0);
var recycleView = h.PlatformView;
recycleView.SetClipToPadding(false);
recycleView.SetPadding(375, 0, 375, 0);
#endif
}
#if IOS
h.PlatformView.SemanticContentAttribute = UISemanticContentAttribute.ForceRightToLeft;
((UICollectionView)h.PlatformView.Subviews[0]).CollectionViewLayout.CollectionView.ContentInset = new UIEdgeInsets(0, 375, 0, (float)375);
((UICollectionView)h.PlatformView.Subviews[0]).CollectionViewLayout.CollectionView.ContentOffset = new CoreGraphics.CGPoint(0, 0);
#endif
};
or like handlers that looks more like the old customrenders that i have from the xamarin.forms project, like this.
public partial class CollectionViewChartHandler : CollectionViewHandler
{
protected override void ConnectHandler(RecyclerView platformView)
{
platformView.RootView.SetPadding(375, 375, 375, 375);
platformView.SetClipToPadding(false);
platformView.SetPadding(375, 375, 375, 375);
base.ConnectHandler(platformView);
}
}
and for iOS
public partial class CollectionViewChartHandler : CollectionViewHandler
{
protected override void ConnectHandler(UIView platformView)
{
base.ConnectHandler(platformView);
platformView.SemanticContentAttribute = UISemanticContentAttribute.ForceRightToLeft;
(((UICollectionView)platformView.Subviews[0]).CollectionViewLayout.CollectionView).ContentInset = new UIEdgeInsets(0, 375, 0, (float)375);
((UICollectionView)platformView.Subviews[0]).CollectionViewLayout.CollectionView.ContentOffset = new CoreGraphics.CGPoint(0, 0);
}
}
But none seems to work, when the itemslayout of the collectionView is set to Horizontal, but works fine if the itemslayout is set to Vertical
Any idea why?

Dynamically draw lines with SkiaSharp in Xamarin

I'm trying to dynamically draw lines by using the package SkiaSharp.
I've defined the control in my xaml like this:
<skia:SKCanvasView x:Name="CanvasView" PaintSurface="OnCanvasViewPaintSurface" />
This is my code behind class:
private SkiaSharp.SKCanvas canvas;
private SkiaSharp.SKSurface surface;
void OnCanvasViewPaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs args)
{
SkiaSharp.SKImageInfo info = args.Info;
surface = args.Surface;
canvas = surface.Canvas;
canvas.Clear();
SkiaSharp.SKPaint thinLinePaint = new SkiaSharp.SKPaint
{
Style = SkiaSharp.SKPaintStyle.Stroke,
Color = SkiaSharp.SKColors.Blue,
StrokeWidth = 6
};
canvas.DrawLine(0, 0, 50, 50, thinLinePaint);
}
The part above works fine, and a blue line will be drawn when loading the view at startup. But what I want to do is to dynamically draw new lines and remove the old ones.
public void DrawNewLine()
{
canvas.Clear();
SkiaSharp.SKPaint thickLinePaint = new SkiaSharp.SKPaint
{
Style = SkiaSharp.SKPaintStyle.Stroke,
Color = SkiaSharp.SKColors.Red,
StrokeWidth = 16
};
canvas.DrawLine(0, 0, 50, 50, thickLinePaint);
}
I am using the canvas field that was declared before, but it's not working. Application will crash at runtime when using the canvas object.
What am I doing wrong?
You need to use SKCanvasView.InvalidateSurface() method to recall OnCanvasViewPaintSurface() internally.

Custom ListView control will not paint when first shown

I have created a custom ListView control to suit my needs and I'm having an issue that causes the ListView not to show any contents (not drawing anything, just white) when the form first loads.
If I resize the form or click on my control (anything that forces a repaint on the ListView) then it shows up as expected.
As a side note, it used to work just fine until I made a small change today and rebuilt the control. I removed all the changes I made and rebuilt again but the issue still happens. Any ideas as to why it will not show up (paint) when the form is first loaded?
This is what I use to do the custom drawing on my custom ListView control...
protected override void OnDrawItem(DrawListViewItemEventArgs e)
{
Image image = e.Item.ImageList.Images[e.Item.ImageIndex];
Size textSize = new Size((int)e.Graphics.MeasureString(e.Item.Text, e.Item.Font).Width, (int)e.Graphics.MeasureString(e.Item.Text, e.Item.Font).Height);
//Get the area of the item to be painted
Rectangle bounds = e.Bounds;
bounds.X = 0;
bounds.Width = this.Width;
//Set the spacing on the list view items
int hPadding = 0;
int vPadding = 0;
IntPtr padding = (IntPtr)(int)(((ushort)(hPadding + bounds.Width)) | (uint)((vPadding + bounds.Height) << 16));
SendMessage(this.Handle, (uint)ListViewMessage.LVM_SETICONSPACING, IntPtr.Zero, padding);
//Set the positions of the image and text
int imageLeft = (bounds.Width / 2) - (image.Width / 2);
int imageTop = bounds.Top + 3;
int textLeft = (bounds.Width / 2) - (textSize.Width / 2);
int textTop = imageTop + image.Height;
Point imagePosition = new Point(imageLeft, imageTop);
Point textPosition = new Point(textLeft, textTop);
//Draw background
using (Brush brush = new SolidBrush(e.Item.BackColor))
e.Graphics.FillRectangle(brush, bounds);
//Draw selected
if (e.Item.Selected)
{
using (Brush brush = new SolidBrush(m_SelectedColor))
e.Graphics.FillRectangle(brush, bounds);
}
//Draw image
e.Graphics.DrawImage(image, imagePosition);
//Draw text
e.Graphics.DrawString(e.Item.Text, e.Item.Font, new SolidBrush(e.Item.ForeColor), textPosition);
}
I also set the following things in the Constructor of my custom control...
public MyListView()
{
this.DoubleBuffered = true;
this.OwnerDraw = true;
this.View = View.LargeIcon;
this.Cursor = Cursors.Hand;
this.Scrollable = false;
}
I also inherit the ListView class...
public class MyListView : ListView
{
//All my source
}
You need to set the set the control to redraw itself when resized. So add this code in constructor of your control:
this.ResizeRedraw = true;
My apologies:
Doing the below reset my event handlers and the problem went away. However, once I hooked them up, I found the Resize event handler that I used to set the ColumnWidth was causing the issue. Why setting the ColumnWidth is causing this, I do not know.
Arvo Bowen's comment on this answer fixed it for me also (.NET 4.8 Framework, VS2022). To be clear, not requiring this.ResizeRedraw = true; from the answer.
So after much headache and time I found that I had absolutely nothing wrong with my control. It was your answer that made me create another control just like my existing one and test it. To my surprise it worked great. I simply copied my existing non-working control and pasted it on the form and then new one worked! Sometimes VS just does weird things... Somehow I managed to muck up the control's creation object or something..

Set orientation of signaturepad to landscape mode always in IOS MVVMCROSS application

I have implemented signaturepad for my ios application. (Its not a native application. I am developing using MVVMCROSS platform. I wish to set the orientation of this signature pad in landscape view always. I am unable to find any parameters for the signaturepad frame.
var signature = new SignaturePadView(View.Frame);
View.AddSubview(signature);
signature.Frame = new RectangleF(0, 135, 320, 130);
//signature.Frame = new RectangleF(0, 135, this.View.Frame.Width, 140);
signature.BackgroundColor = UIColor.Gray;
I am not able to make sure that it always opens in landscape view and adjusts to the width of the screen. Would be glad if you anyone could help
Try adding following code to your ViewController of SignaturePadView
public override bool ShouldAutorotate()
{
return true;
}
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
{
return UIInterfaceOrientationMask.AllButUpsideDown;
}
It overrides orientation methods

Display text with no rectangle

I am developing a Android Cell phone application using MonoDevelop for Android and the MapsAndLocationDemo. I am wanting to display some text under each overlay item. I have overridden the Draw method to do this.
Here is my code:
public override void Draw (Android.Graphics.Canvas canvas, MapView mapView, bool shadow)
{
base.Draw (canvas, mapView, shadow);
var paint = new Paint ();
paint.AntiAlias = true;
var gp = overlayDetailsForThisOverlay.overlayGeoPoint;
var pt = mapView.Projection.ToPixels (gp, null);
canvas.DrawRect (pt.X, pt.Y, pt.X + 50, pt.Y + 50, paint);
canvas.DrawText("Test", pt.X, pt.Y, paint);
}
I am only wanting to display the text. However, if I remove the canvas.DrawRect line of code, no text is displayed at all.
Can I please have some help to display some desired text under an overlay item without having a rectangle drawn at all?
try this inside your xml layout
android:background="#android:color/transparent"

Categories

Resources