UILabel overlap in UICollectionView Xamarin.ios - xamarin.ios

I needed to create a UICollectionView containing the profiles of users searched in my database.
The UICollectionView must contain a UILabel and a UIImage, the name and image must be taken from PHP. I currently get both, but when I go to do a new search, the old information overlaps the new, creating a confusing effect like this:
I am developing on xamarin.ios, I am attaching the portion of code that deals with the visual output of the UILabel and UIImage elements.
public void UpdateCell(string elemento)
{
img = new UIImageView(UIImage.FromBundle("ProfiloImgNotFound"));
UILabel name = new UILabel { Text = elemento, TextColor = UIColor.SecondaryLabelColor, TextAlignment = UITextAlignment.Center };
Console.WriteLine(name.Text);
name.Font = UIFont.FromName(".AppleSystemUIFont", 20);
var labelHeight = 20;
var labelWidth = img.Bounds.Width;
name.Frame = new CGRect(0, img.Bounds.Height + 10, labelWidth, labelHeight);
AddSubviews(new UIView[] { img, name });
}

Related

Replacing System.Drawing with ImageSharp for Barcode .net core 6

As we have upgraded to net core 6 we are rewriting some of our code base. We have a tag helper in AspNet Core which generates a barcode. This currently uses System.Drawing and ZXing.
TagHelper Old version using System.Drawing - working (top barcode)
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var margin = 0;
var qrCodeWriter = new ZXing.BarcodeWriterPixelData
{
Format = ZXing.BarcodeFormat.PDF_417,
Options = new ZXing.Common.EncodingOptions
{
Height = this.Height > 80 ? this.Height : 80,
Width = this.Width > 400 ? this.Width : 400,
Margin = margin
}
};
var pixelData = qrCodeWriter.Write(QRCodeContent);
// creating a bitmap from the raw pixel data; if only black and white colors are used it makes no difference
// that the pixel data ist BGRA oriented and the bitmap is initialized with RGB
using (var bitmap = new Bitmap(pixelData.Width, pixelData.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb))
using (var ms = new MemoryStream())
{
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, pixelData.Width, pixelData.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
try
{
// we assume that the row stride of the bitmap is aligned to 4 byte multiplied by the width of the image
System.Runtime.InteropServices.Marshal.Copy(pixelData.Pixels, 0, bitmapData.Scan0,
pixelData.Pixels.Length);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
// save to stream as PNG
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
output.TagName = "img";
output.Attributes.Clear();
output.Attributes.Add("width", Width);
output.Attributes.Add("height", Height);
output.Attributes.Add("alt", Alt);
output.Attributes.Add("src",
$"data:image/png;base64,{Convert.ToBase64String(ms.ToArray())}");
}
}
TagHelper new version using ImageSharp - almost working but not exactly (bottom barcode)
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var margin = 0;
var barcodeWriter = new ZXing.ImageSharp.BarcodeWriter<SixLabors.ImageSharp.PixelFormats.La32>
{
Format = ZXing.BarcodeFormat.PDF_417,
Options = new ZXing.Common.EncodingOptions
{
Height = this.Height > 80 ? this.Height : 80,
Width = this.Width > 400 ? this.Width : 400,
Margin = margin
}
};
var image = barcodeWriter.Write(QRCodeContent);
output.TagName = "img";
output.Attributes.Clear();
output.Attributes.Add("width", Width);
output.Attributes.Add("height", Height);
output.Attributes.Add("alt", Alt);
output.Attributes.Add("src", $"{image.ToBase64String(PngFormat.Instance)}");
}
The issue is as mentioned the 2nd barcode is very slightly different at the end seems to extend the last bar.
What am I missing?
That is a bug in the renderer implementation of the ZXing.Net binding to ImageSharp.
https://github.com/micjahn/ZXing.Net/issues/422
It is fixed in the newest nuget package of the bindings.
https://www.nuget.org/packages/ZXing.Net.Bindings.ImageSharp/
https://www.nuget.org/packages/ZXing.Net.Bindings.ImageSharp.V2/

How do I change the background color of a tabbed page in Xamarin iOS?

I need to change the background color of the currently tabbed page in my UITabBarController. I've searched through every stackoverflow post I could find but nothing worked for me. I thought there would be something like UITabBar.Appearance.SelectedImageTintColor, just for the background color but it doesn't seem so.
For example, I want to change the color of that part when I am on the right tab:
Does someone know how to do that?
You could invoked the following code in your UITabBarController
public xxxTabBarController()
{
//...set ViewControllers
this.TabBar.BarTintColor = UIColor.Red;
}
Update
//3.0 here is if you have three child page in tab , set it as the current value in your project
//
var size = new CGSize(TabBar.Frame.Width / 3.0, IsFullScreen());
this.TabBar.SelectionIndicatorImage = ImageWithColor(size,UIColor.Green);
double IsFullScreen()
{
double height = 64;
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
if (UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom > 0.0)
{
height = 84;
}
}
return height;
}
UIImage ImageWithColor(CGSize size, UIColor color)
{
var rect = new CGRect(0, 0, size.Width, size.Height);
UIGraphics.BeginImageContextWithOptions(size, false, 0);
CGContext context = UIGraphics.GetCurrentContext();
context.SetFillColor(color.CGColor);
context.FillRect(rect);
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return image;
}
The trick is to use the SelectionIndicatorImage Property of the UITabBar and generate a completely filled image with your desired color using the following method:
private UIImage ImageWithColor(CGSize size)
{
CGRect rect = new CGRect(0, 0, size.Width, size.Height);
UIGraphics.BeginImageContext(size);
using (CGContext context = UIGraphics.GetCurrentContext())
{
context.SetFillColor(UIColor.Green); //change color if necessary
context.FillRect(rect);
}
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return image;
}
To initialize everything we override ViewWillLayoutSubviews() like this:
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
// The tabbar height will always be 49 unless we force it to reevaluate it's size on runtime ...
myTabBar.InvalidateIntrinsicContentSize();
double height = myTabBar.Frame.Height;
CGSize size = new CGSize(new nfloat(myTabBar.Frame.Width / myTabBar.Items.Length, height));
// Now get our all-green image...
UIImage image = ImageWithColor(size);
// And set it as the selection indicator
myTabBar.SelectionIndicatorImage = image;
}
As mentioned in this article (google translating it step by step when necessary lol) calling InvalidateIntrinsicContentSize() will force the UITabBar to reevaluate it's size and will get you the actual runtime height of the tab bar (instead of the constant 49 height value from XCode).

Xamarin iOS : Center UILabel inside UICollectionView Header created programmatically

The solution for centering any subview within a parent is usually simple, however, it doesn't seem to work in my case.
I'm working with a UICollectionView and have added a Header class programmatically. I have this constructor, where I also try to center the label within the screen:
[Export("initWithFrame:")]
public Header(System.Drawing.RectangleF frame) : base(frame)
{
label = new UILabel
{
Frame = new System.Drawing.RectangleF(frame.Size.Width / 2, 50, 200, 50),
BackgroundColor = UIColor.Clear,
TextColor = UIColor.White,
Font = UIFont.FromName("HelveticaNeueLTStd-ThCn", 35f),
Text = DateTime.Now.ToString("Y")
};
AddSubview(label);
}
And I initialize the class inside the UICollectionViewSource 's constructor like this:
public MyCollectionViewDataSource(MainController mainController, DateTime currentDate)
{
try
{
controller = mainController;
new Header(new RectangleF(0, 0, (float)mainController.View.Frame.Size.Width, 200));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + ex.StackTrace);
}
}
What exactly am I missing because this usually works in other instances but seems to fail here?
This is what it looks like :
I found an explanation here iOS Layout Gotchas by Adam Kemp which helped me resolve this issue.
The first solution
One very common mistake I made was adding the layout definition code in the constructor, instead of doing it in the rightful place : the LayoutSubviews override in this case.
Giving the label the frame size in the constructor assumes a static size set at the time of construction, which may later change depending on the screen size.
The second solution
He explains that :
Frame sets the position of a view within its parent while Bounds is in the coordinate system of the view itself (not its parent).
So, to center the UILabel, I used bounds and center together and this worked for me.
[Export("initWithFrame:")]
public Header(CGRect bounds) : base(bounds)
{
label = new UILabel
{
BackgroundColor = UIColor.Clear,
TextColor = UIColor.White,
Font = UIFont.FromName("HelveticaNeueLTStd-ThCn", 35f),
Text = DateTime.Now.ToString("Y"),
TextAlignment = UITextAlignment.Center
};
rectangle = bounds;
AddSubview(label);
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
label.Bounds = new CGRect (rectangle.Size.Width / 2, 50, 200, 50);
label.Center = new PointF((float)rectangle.Size.Width/2,50);
}

Can't get new iOS 7 camera to scale inside UIPopoverController

My iOS 6 code to show the camera in a UIPopoverController works fine but iOS won't scale the camera view. Please see images below. Any suggestions would be appreciated.
Edit
public class NoRotationUIImagePickerController : UIImagePickerController
{
public override bool ShouldAutorotate ()
{
return false;
}
}
//place imagePicker into a container so that we can control the size of the popover
container = new UIViewController();
container.ContentSizeForViewInPopover = new SizeF(parentViewController.View.Frame.Width, parentViewController.View.Frame.Height);
container.View.AddSubview(_imagePicker.View);
_popOver = new UIPopoverController (container);
//If no camera is available, return false and do nothing.
if (IsCameraHardwareAvailable())
{
_imagePicker.Delegate = new PopUpGalleryPickerDelegate (_popOver, _imageSelected);
_imagePicker.SourceType = UIImagePickerControllerSourceType.Camera;
_imagePicker.AllowsEditing = false;
_imagePicker.MediaTypes = new string[] {"public.image"};
RectangleF popRectangle = new RectangleF (new PointF(parentViewController.View.Frame.Width/2, parentViewController.View.Frame.Height/2), new SizeF (1, 1));
_popOver.PresentFromRect(popRectangle, parentViewController.View, 0, true);
_imagePicker.View.Frame = container.View.Frame; //change to frame must come after popover is presented.
}
else
{
cameraAvailable = false;
}
The solution I ended up with was to make the camera full screen instead of using a popover controller.

Change color title UITable static section

I have two UITable static sections in my application with both different headers.
The color of the header must be changed because the custom background.
How can I do this solution like ( link ) in my MonoTouch application?
Because I use static sections, I don't have a UITableViewSource where I can do stuff in.
My solution (thanks to Krumelur)
[Export("tableView:viewForHeaderInSection:")]
UIView GetViewForHeaderInSecion (UITableView tableview, int section)
{
UIView view = new UIView (new RectangleF (0, 0, 300, 0));
view.BackgroundColor = UIColor.Clear;
UILabel label = new UILabel (new RectangleF (15, 5, 300, 25));
label.BackgroundColor = UIColor.Clear;
label.TextColor = UIColor.White;
label.ShadowColor = UIColor.Black;
label.ShadowOffset = new SizeF(0, 1);
label.Font = UIFont.BoldSystemFontOfSize(18);
if (section == 0) {
label.Text = "First section";
} else {
label.Text = "Second section";
}
view.AddSubview(label);
return view;
}
You'll have to export the missing method in your controller. Something like:
[Export("tableView:viewForHeaderInSection:")]
UIView GetViewForHeaderInSection(UITableView tableview, int section
{
// return your UIView with whatever background color here
}
Note that you cannot change the color of the predefined view but have to return an entire view instead.

Resources