I'm new with Xamarin. I'm actually trying to set the background image of a view and stretch it.
The image is a 2048x1536 pixels png.
nfloat vpHeight = View.Bounds.Height;
nfloat vpWidth = View.Bounds.Width;
Console.WriteLine(vpWidth);
Console.WriteLine(vpHeight);
The above code will return me 1024x768 (it's a landscape position).
var img = UIImage.FromFile("pages/p1.png");
UIImageView imgView = new UIImageView(img);
imgView.ContentMode = UIViewContentMode.ScaleAspectFit;
var prevPage = new UIView()
{
Frame = new CoreGraphics.CGRect(0, 0, vpWidth, vpHeight)
};
prevPage.Add(imgView);
this is the code where I set the background, but the result is just the half of the image in x and y just like the image bellow:
So, how to make the image to adjust to the width and height of the view ?
ty !!
I would create an UIImageView as a background like so:
var img = UIImage.FromFile("pages/p1.png");
UIImageView imgView = new UIImageView(img);
imgView.ContentMode = UIViewContentMode.ScaleAspectFit;
then add this to whatever view you are using.
ContentMode can be used like so:
Update
I would add it to the prevPage like so:
var prevPage = new UIView()
{
Frame = new CoreGraphics.CGRect(0, 0, vpWidth, vpHeight)
};
var img = UIImage.FromFile("pages/p1.png");
UIImageView imgView = new UIImageView(new CGRect(0,0,vpWidth,vpHeight));
imgView.Image = img;
imgView.ContentMode = UIViewContentMode.ScaleAspectFit; // or ScaleAspectFill
prevPage.Add(imgView);
Also its worth noting that using the View.Bounds to position the view is bit clunky. I would take a look into Autolayout as you will encounter problems on different devices and orientations. These are some good tutorials on Autolayout they might be native code but you are looking for the relationships of the views rather than the code.
Raywenderlich tutorial
Other Tutorial
Any probs with autolayout just ask another question.
I would recommend you stay away from FromPatternImage unless you are really using a pattern.
For the lowest memory consumption and best UI performance, this is what I do:
1st) Resize your image using an image context to match the size of the view:
UIGraphics.BeginImageContext(View.Frame.Size);
UIImage.FromBundle("bg.jpg").Draw(View.Bounds);
var bgImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
2nd) Display the resized image in a UIImageView and send it to the lowest Z-order:
var uiImageView = new UIImageView(View.Frame);
uiImageView.Image = bgImage;
View.AddSubview(uiImageView);
View.SendSubviewToBack(uiImageView);
Related
I've run into a simple problem, that I can not solve even after looking everywhere..
I made a grey table view, and at the top I have a cell with white background.
Is it possible to whenever the user refreshes, make it also white (on the top)?
Try this code
let refresh = UIRefreshControl()
let backgroundColor = UIColor.red
refresh.backgroundColor = backgroundColor
refresh.addTarget(self, action: #selector(self.refreshs), for: .valueChanged)
tableView.addSubview(refresh)
var frame = tableView.bounds
frame.origin.y = -frame.size.height
let backgroundView = UIView(frame: frame)
backgroundView.autoresizingMask = .flexibleWidth
backgroundView.backgroundColor = backgroundColor // background color pull to refresh
tableView.insertSubview(backgroundView, at: 0)
I successfully get out the two images in my resources folder in my project like this.
string BackGroundImage = "background_image";
string ObjectImage = "object_image";
var TheBackGroundImage = BitmapFactory.DecodeResource(Resources, Resources.GetIdentifier(BackGroundImage, "drawable", PackageName));
var TheObjectImage = BitmapFactory.DecodeResource(Resources, Resources.GetIdentifier(ObjectImage, "mipmap", PackageName));
What i have done after is very the tricky part comes in and I do not know how to quite get it right. What i try to do is create a new Bitmap where the BackgroundImage is the base. Then i create a canvas with my second image (ObjectImage) that is the image that will be on top of the BackgroundImage and try to merge it all together.
Bitmap Result = Bitmap.CreateBitmap(TheBackGroundImage.Width, TheBackGroundImage.Height, TheBackGroundImage.GetConfig());
Canvas canvas = new Canvas(Result);
canvas.DrawBitmap(ObjectImage, new Matrix(), null);
canvas.DrawBitmap(ObjectImage, 79, 79, null);
This does not work as anticipated, is canvas the way to go or is there somethinig else i should look at?
If we look at my iOS solution then i do it like this:
UIImage PhoneImage = UIImage.FromFile(PhonePath);
UIImage IconImage = UIImage.FromFile(IconPath);
UIImage ResultImage;
CGSize PhoneSize = PhoneImage.Size;
CGSize IconSize = IconImage.Size;
UIGraphics.BeginImageContextWithOptions(IconSize, false, IconImage.CurrentScale); //UIGraphics.BeginImageContextWithOptions(IconSize, false, IconImage.CurrentScale);
UIGraphics.BeginImageContext(PhoneSize);
CGRect Frame = (new CoreGraphics.CGRect(25, 29.5, 79, 79));
UIBezierPath RoundImageCorner = new UIBezierPath();
RoundImageCorner = UIBezierPath.FromRoundedRect(Frame, cornerRadius: 15);
PhoneImage.Draw(PhoneImage.AccessibilityActivationPoint);
RoundImageCorner.AddClip();
IconImage.Draw(Frame);
UIColor.LightGray.SetStroke();
RoundImageCorner.LineWidth = 2;
RoundImageCorner.Stroke();
ResultImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
var documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string jpgFilename = System.IO.Path.Combine(documentsDirectory, "app.png");
NSData image = ResultImage.AsPNG();
And it works beautifully with a border around my second image as well.
How can i adjust my code to successfully merge two images together and position the second image preferably like a CGRect?
Try this:
public Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap)
{
Bitmap bitmap = backBitmap.Copy(Bitmap.Config.Argb8888, true);
Canvas canvas = new Canvas(bitmap);
Rect baseRect = new Rect(0, 0, backBitmap.Width, backBitmap.Height);
Rect frontRect = new Rect(0, 0, frontBitmap.Width, frontBitmap.Height);
canvas.DrawBitmap(frontBitmap, frontRect, baseRect, null);
return bitmap;
}
Update:
Here is the DrawBitmap method's introduce. I add annotations in the method.
public Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap)
{
Bitmap bitmap = backBitmap.Copy(Bitmap.Config.Argb8888, true);
Canvas canvas = new Canvas(bitmap);
//this Rect will decide which part of your frontBitmap will be drawn,
//(0,0,frontBitmap.Width, frontBitmap.Height) means that the whole of frontBitmap will be drawn,
//(0,0,frontBitmap.Width/2, frontBitmap.Height/2) means that the half of frontBitmap will be drawn.
Rect frontRect = new Rect(0, 0, frontBitmap.Width, frontBitmap.Height);
//this Rect will decide where the frontBitmap will be drawn on the backBitmap,
//(200, 200, 200+ frontBitmap.Width, 200+frontBitmap.Height) means that
//the fontBitmap will drawn into the Rect which left is 200, top is 200, and its width and
//height are your frontBitmap's width and height.
//I suggest the baseRect's width and height should be your fontBitmap's width and height,
//or, your fontBitmap will be stretched or shrunk.
Rect baseRect = new Rect(200, 200, 200+ frontBitmap.Width, 200+frontBitmap.Height);
canvas.DrawBitmap(frontBitmap, frontRect, baseRect, null);
return bitmap;
}
There're lot of Watch apps which has rounded corners for their WKInterfaceImages. I'm trying to round even some WKInterfaceImages in my test app but I can't understand how to do that.
I can't work with imageView.layer. ... as with normal iPhone apps and I can't find an alternative to do that using code or storyboard.
Do I have to mask all PNGs or there's a simpler way?
I solved removing the WKInterfaceImage from storyboard then replacing it with an WKInterfaceGroup which I set with same sizes of previous Image then, from attribute inspector, I setted his radius (yes, with groups it's possible!) then I declared group in controller and setted the image using row.flagView.setBackgroundImageNamed(imageName).
You are right CALayer and UIView are not directly available on watchOS 2. But you are able to use graphic functions and for instance this approach is perfectly acceptable on Watch.
The analogue in Swift:
class ImageTools {
class func imageWithRoundedCornerSize(cornerRadius:CGFloat, usingImage original: UIImage) -> UIImage {
let frame = CGRectMake(0, 0, original.size.width, original.size.height)
// Begin a new image that will be the new image with the rounded corners
UIGraphicsBeginImageContextWithOptions(original.size, false, 1.0)
// Add a clip before drawing anything, in the shape of an rounded rect
UIBezierPath(roundedRect: frame, cornerRadius: cornerRadius).addClip()
// Draw the new image
original.drawInRect(frame)
// Get the new image
let roundedImage = UIGraphicsGetImageFromCurrentImageContext()
// Lets forget about that we were drawing
UIGraphicsEndImageContext()
return roundedImage
}
}
Somewhere in your WKInterfaceController class:
let originalImage = UIImage(named: "original-image")!
let roundedImage = ImageTools.imageWithRoundedCornerSize(60, usingImage: originalImage)
// Set `UIImage` for your `WKInterfaceImage`
imageOutlet.setImage(roundedImage)
I want to merge two images,one image is of 300x300 and other is 100x100, First i have created a canvas and then i created two images which i have added to the both the images to canvas and the canvas is added to the content panel, then i created a writeablebitmap and render the canvas and created a method savejpeg which saves the image to isolated stoarage,but isolated storage is not showing the whole image it save a black screen.
First i created a canvas through code set its height width and background color then i created two images programmatically which i have added to the canvas and then canvas is added to the contentpanel
my code is:
public void CreateImage()
{
Canvas canvas = new Canvas();
canvas.Height = 400;
canvas.Width = 400;
canvas.Background = new SolidColorBrush(Colors.Red);
Image img1 = new Image();
img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("Image/Desert.jpg");
img1.Height = 300;
img1.Width = 300;
img1.Margin = new Thickness(0, 10, 0, 0);
Image img2 = new Image();
img2.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("Image/Jellyfish.jpg");
img2.Height = 50;
img2.Width = 50;
img2.Margin=new Thickness(0,10,300,0);
canvas.Children.Add(img1);
canvas.Children.Add(img2);
ContentPanel.Children.Add(canvas);
WriteableBitmap wb = new WriteableBitmap(400, 400);
wb.Render(canvas, new MatrixTransform());
MemoryStream ms = new MemoryStream();
wb.SaveJpeg(ms,400,400,0,100);
using (var isoFileStream = new IsolatedStorageFileStream("myPicture.jpg", FileMode.OpenOrCreate, IsolatedStorageFile.GetUserStoreForApplication()))
{
wb.SaveJpeg(isoFileStream, 400, 400, 0, 100);
}
}
When i save the image then i am getting a black screen in isolated storage.
How to save both images on canvas?
Like Stephan said, I think you are not getting the image to your source. Any way I created a sample application for you. In that you can find two partitions, you can add image to that by double tapping on the container. After that try save and check your saved image. I tested the app and every thing is working for me. Still you face any kind of issues please leave a comment.
https://www.dropbox.com/s/1vjbbou96w0r15r/SaveImageApp.zip
Please check weather you are getting image or not to image source. If you are getting the image; try this method to take snapshot from control and save that to Iso store.
http://stackoverflow.com/questions/13837148/how-can-i-take-a-screenshot-full/13990649#13990649
Is there a way to get a .png height without creating ImageView?
The methods I found on google require createImageView first and then doing a .height.
I want to avoid creating ImageView because I'm going to createImageView after I get the height of the png and perform some changes.
Or rather, I will be using the height value during the var imagevariablename = Ti.UI.createImageView itself, so I can't using imagevariablename.height because the declaration of var imagevariablename is not done yet.
I don't know of any way to get the height / width of an image without creating an imageView in Titanium. In my app, I create a temporary image view and read the attributes without ever adding it to a view / window. Then you can create the 'real' image view once you know the size:
var imageTemp = Ti.UI.createImageView({
image : someFile.read(),
height:'auto',
width:'auto'
});
Ti.API.info( "height=" + imageTemp.size.height);
Ti.API.info( "width=" + imageTemp.size.width);
imageTemp = null;
Try this code
var imageTemp = Ti.UI.createImageView({
image : <image>,
height:'auto',
width:'auto'
}),
imageSize = imageTemp.toImage();
Ti.API.info( "height=" + imageSize.height);
Ti.API.info( "width=" + imageSize.width);
imageTemp = imageSize = null;
If you create a Blob from your image you can get width and height from the blob
From Titanium docs:
If this blob represents an image, this is the height of the image in pixels.
In my condition this is run like this.
var imageTemp = Ti.UI.createImageView({
image : someFile.read(),
height:'auto',
width:'auto'
});
alert( "height=" + imageTemp.toBlob().height);
alert( "width=" + imageTemp.toBlob().width);
imageTemp = null;
I was working on this and had trouble with the code above using 3.2.2, testing on Android. Various attempts would just give me 1, 0 or SIZE for the width and height values. This DOES use an imageView, but the following gets me everything I need in this environment. I also am using the load event instead of postLayout. Hopefully this helps someone.
$.map.image = 'http://getyourownimage.com/dev/8fac94c6-872b-4bda-a56a-7dba09188c66.png';
$.map.zIndex = 1;
$.map.width = 'auto';
$.map.height = 'auto';
$.map.addEventListener('load',function(e){
var rect = $.map.getRect();
Ti.API.info(rect.width); //actual width of imageView
Ti.API.info(rect.height); //actual height of imageView
Ti.API.info($.map.getWidth()); //returns auto/SIZE, doesn't work
Ti.API.info($.map.getHeight()); //returns auto/SIZE, doesn't work
Ti.API.info($.map.toImage().width); //some scaled value, not useful
Ti.API.info($.map.toImage().height); //some scaled value, not useful
Ti.API.info($.map.toBlob().width); //image original/full size width
Ti.API.info($.map.toBlob().height); //image original/full size height
alert('rectX:'+rect.width+',rectY:'+rect.height+',mapGW:'+$.map.getWidth()+',mapGH:'+$.map.getHeight()+',tiX:'+$.map.toImage().width+',tiY:'+$.map.toImage().height+',tbX:'+$.map.toBlob().width+',tbY:'+$.map.toBlob().height);
});