The following code is working for the most part, however sometimes after being changed into a blob, the image view does not display the image.
//store in temp image view, convert to blob
imageViewTemp.image = "imagename.jpg"
blob = imageViewTemp.toBlob();
albumTitle = data[x].name + ' (' + numberPhotos + ')';
var row = Titanium.UI.createTableViewRow({
titleAlb : data[x].name,
width : '100%',
height : 'auto'
});
var image = Titanium.UI.createImageView({
top : 0,
left : 0,
width : '75',
height : '75'
});
var title = Titanium.UI.createLabel({
text : albumTitle,
top : 0,
left : 110,
width : 'auto',
height : 'auto'
});
var width = blob.width;
var height = blob.height;
//crop so it fits in image view
if (width > height) {
image.image = ImageFactory.imageAsCropped(blob, {
width : height,
height : height,
x : 60,
y : 0
});
} else {
image.image = ImageFactory.imageAsCropped(blob, {
width : (width - 1),
height : (width - 1),
x : 60,
y : 0
});
}
row.add(image);
row.add(title);
rows.push(row);
}
In order to change the dimension of the image, I am using a module called image factory. Before I can change it, I have to store the image inside a tempory image view which I then convert into a blob:
blob = imageViewTemp.toBlob();
The problem is after the screen is rendered sometimes this will not work:
image.image = ImageFactory.imageAsCropped(blob, {
width : height,
height : height,
x : 60,
y : 0
});
Othertimes it will.
I have read online that the problem might be linked to the post layout cycle, but I am not sure, or how to proceed
http://developer.appcelerator.com/question/174329/what-are-the-difference-between-toblob--toimage
All help appreciated.
Solved the problem.
You have to download the image first using a REST API method (GET) before placing it into the temporary image view, otherwise the temp image view will be rendered before the file has been fully downloaded (.toImage is an async call back method), making way for a useless blob and no image.
The only problem with this method, is that you are reliant on your REST API calls to not fail.
Related
I am relatively new to iOS so go easy on me! In my app I need to have a button which contains an image a title. The image needs to go above the title. The image is defined dynamically from a base64 string.
My problem is I can’t work out how to display the title and the image in the button at the same time. I can display them individually but not together. I have tried following the approach in the below link but I have been unable to get it to work:
Display Button With Text & Image In Xamarin IOS
This is how the button needs to look:
In Xamarin iOS I am using the below code to set the image and lay out the controls in the button:
DeviceMenuItems m_menuItem = HHMenuContainer.Instance.GetMenuItems().DeviceMenuItems.SingleOrDefault(l => l.LineNo.ToString() == m_lineNo);
if (m_menuItem != null && m_menuItem.Base64Picture != null)
{
byte[] bytes = Convert.FromBase64String(m_menuItem.Base64Picture);
NSData data = NSData.FromArray(bytes);
UIImage uiimage = UIImage.LoadFromData(data);
//this line is not relevant to the problem
uiimage = ChangeImageBackground(uiimage);
if (uiimage != null)
{
//m_control is the UIButton
//commenting this out removes the image and shows the text
m_control.SetImage(uiimage, UIControlState.Normal);
float titleLabelHeight = (float)(m_control.TitleLabel.Frame.Size.Height + 10);
m_control.ImageEdgeInsets = new UIEdgeInsets(-(titleLabelHeight), 0, titleLabelHeight, 0 );
float imageHeight = (float)(m_control.ImageView.Frame.Size.Height * 0.5);
imageHeight -= titleLabelHeight;
m_control.TitleEdgeInsets = new UIEdgeInsets(imageHeight, 0, -(imageHeight), 0);
}
}
With the above code I get the following button (without the required text):
If I comment the ‘SetImage’ line out I get the following button:
Does anyone have any ideas why the above approach isn’t working?
From the shared link , it show left title and right image.If want up and down layout, you can try this:
button.TitleEdgeInsets = new UIEdgeInsets(0, -button.ImageView.Frame.Size.Width, -button.ImageView.Frame.Size.Height - 5,0);
button.ImageEdgeInsets = new UIEdgeInsets( -button.TitleLabel.Frame.Size.Height - 5, 0 , 0, -button.TitleLabel.Frame.Size.Width);
Note: If the button's frame is set and the width of the button is not enough to display the size of the image and text at the same time, the size of the titleLabel will get an error. So if you need to set the frame, it is recommended to set the width of the button to frame.size.width * 2, and then set the frame after the titleEdgeInsets and imageEdgeInsets are all set.
I wanna have a listener ( or something ) to check if the size of the window changes, do something ( like re-rendering entire view page ).
How should I do this?
You can use the resize event like so:
window.on('resize', function () {
var size = window.getSize();
var width = size[0];
var height = size[1];
console.log("width: " + width);
console.log("height: " + height);
});
Docs here
To clarify the above answer. You have to set the resize event on the main window you created. Further, if you want to access the width or height inside another file, you can emit another event and pass the width or height as a parameter. Here is a simple example of what I have done.
mainWindow.on("resize", function () {
var size = mainWindow.getSize();
var width = size[0];
var height = size[1];
mainWindow.webContents.send("resized", height);
console.log(size);
console.log("width: " + width);
console.log("height: " + height);
});
I have 10 image views stacked on one another. (for loop)
9 of them are set to visible = false.
1 of them is set to visible = true.
I was wondering if there is a way to only load the image when the imageview visibility is set to true. i.e. after an image view is removed off the stack.
The trouble I am having is that it is loading all the images at the same time in the stack, slowing everything down.
for (var i = 0; i < peopleJson.users.length; i++) {
//create containers to store every child object
containers[i] = Titanium.UI.createView({
id : 'container',
visible : false,
width : '100%',
zIndex : '0',
});
imageSwipeView[i] = Titanium.UI.createImageView({
image : peopleJson.users[i].pictures[0],
visible : true,
containerObj : containers[i],
containerObjPrev : containers[temp],
pictures : peopleJson.users[i].pictures,
indImageView : indImageView[i],
basket : LabelBasket[temp],
top : 0,
zIndex : 2,
width : '100%',
defaultImage : 'images/plainbg.png',
height : 510,
});
containers[i].add(imageSwipeView[i]);
win.add(containers[i]);
if (i == (peopleJson.users.length - 1)) {
//show last container when for loop is executed
containers[i].visible = true;
$.view_indicator.visible = false;
}
[..]
This code snippet basically says stack up the containers ontop of one another, once loop has executed show last container.
Later on I have an onclick event for each image view, if clicked, it removes the container at the top of the stack and makes the one underneath visible.
What I am trying to do , is only LOAD up the imageView remote images when the container becomes visible. Right now, it will try and load the images visible or not visible.
You can try setting path to image to different property:
imageSwipeView[i] = Titanium.UI.createImageView({
_image : peopleJson.users[i].pictures[0],
...
})
and when you are setting up visible = true update image property:
containers[i].visible = true;
if (!imageSwipeView[i].image) {
imageSwipeView[i].image = imageSwipeView[i]._image;
}
$.view_indicator.visible = false;
I'm working on Titanium SDK 3.1.1 and deploying for iOS. What I'm trying to do is to open the camera with an overlay, take a picture, crop the picture and save it. But I'm having trouble to take a picture with an overlay.
If I take a picture in portrait, the image returned is taken in landscape. When taking it in landscape, the result will be a portrait image. No idea why is this happening.
My overlay is really simple, it has three views that act as buttons, one of them closes the camera, another takes the picture and the other opens the gallery (which throws an exception, but that's a problem for a different question):
var testOverlay = Ti.UI.createView({
bottom:0,
height:200,
width: platformWidth,
height : platformHeight,
left:0
});
//just a black view on top to limit upper area
var topbarView = Ti.UI.createView({
width: platformWidth,
height : resultHeight,
top : 0,
left : 0,
backgroundColor : '#363636',
opcatity : 0.6
});
testOverlay.add(topbarView);
// just a black view on bottom to limit bottom area and display custom controls
var bottombarView = Ti.UI.createView({
width: platformWidth,
height : resultHeight,
bottom : 0,
left : 0,
backgroundColor : '#363636',
opcatity : 0.6
});
testOverlay.add(bottombarView);
// container view for custom controls
var cameraButtonHolder = Ti.UI.createView({
width : Ti.UI.FILL,
height : 80 + dpi,
bottom : 0
});
bottombarView.add(cameraButtonHolder);
//a view to close camera
var cancelCameraButton = Ti.UI.createView({
width:80 + dpi,
height:80 + dpi,
left:0,
backgroundColor:"pink"
});
// a view to take picture
var takePictureButton = Ti.UI.createView({
width : 80 + dpi,
height : 80 + dpi,
backgroundColor : 'blue'
});
//a view to open gallery
var galleryButton = Ti.UI.createView({
width:80 + dpi,
height:80 + dpi,
right:0,
backgroundColor:"green"
});
cameraButtonHolder.add(cancelCameraButton);
cameraButtonHolder.add(takePictureButton);
cameraButtonHolder.add(galleryButton);
// event handler to close camera
cancelCameraButton.addEventListener('click', function(e){
Ti.Media.hideCamera();
parentWindow.closeView();
});
//event handler to take picture
takePictureButton.addEventListener('click', function(e){
Ti.Media.takePicture();
});
// event handler to open gallery
galleryButton.addEventListener("click", function(e){
Titanium.Media.openPhotoGallery({
success : function(event) {
Ti.API.info('Returning from gallery');
var filename = 'baby_temp.png';
var tmp = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, (filename));
tmp.write(event.media);
var blob = tmp.read();
Ti.App.fireEvent(callback, {
media_type : 'photos'
});
},
cancel : function() {
Ti.API.info('Cancelled');
},
error : function(error) {
// if error, show message
var message = 'Unexpected error: ' + JSON.stringify(error);
Ti.UI.createAlertDialog({
title : 'Camera',
message : message
}).show();
},
mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]
});
});
My function that opens the camera and handles the photo looks like this:
function showCamera() {
Ti.Media.showCamera({
success : function(event)
{
var tmp;
var mediaType;
if (event.mediaType.indexOf('PHOTO') > -1 || event.mediaType.indexOf('image') > -1)
{
tmp = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, ('baby_temp.png'));
mediaType = 'photos';
}
else
{
tmp = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, ('baby_temp.mp4'));
mediaType = 'videos'
}
Ti.App.Properties.setString('mediaType', mediaType);
if (mediaType == "photos")
{
//If it's a picture then crop it and save it
var image = event.media;
var imageWidth = image.width;
var imageHeight = image.height;
var scaleX = 0;
var scaleY = (imageHeight - imageWidth) / 2;
if(imageHeight > imageWidth)
{
scaleX = (imageWidth - imageHeight) / 2;
scaleY = 0;
}
var croppedImage = image.imageAsCropped({
x : scaleX,
y : scaleY,
width : imageWidth,
height : imageWidth
});
tmp.write(croppedImage);
}
else
{
// video
tmp.write(event.media);
}
Ti.App.fireEvent('changeCreateMoment', {
media_type : mediaType
});
Ti.Media.hideCamera();
},
cancel : function() {
// hide camera and close the window
Ti.Media.hideCamera();
parentWindow.closeView();
},
error : function(error) {
// if error, show message, hide camera and close window
var message;
if (error.code == Ti.Media.NO_CAMERA)
{
message = 'Device does not have camera capabilities';
}
else
{
message = 'Unexpected error: ' + error.code;
}
Ti.UI.createAlertDialog({
title : 'moments',
message : message
}).show();
Ti.Media.hideCamera();
parentWindow.closeView();
},
overlay:testOverlay,
mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO, Ti.Media.MEDIA_TYPE_VIDEO],
videoMaximumDuration : 10000,
videoQuality : Titanium.Media.QUALITY_MEDIUM,
saveToPhotoGallery : false,
showControls : false,
autohide : false
});
}
I have no idea why the photo is taken in landscape instead of portrait and vice versa. Am I missing a property in my showCamera function call? Why am I getting a photo like this?
I have two images one on the above and i want to erase a small part from the top image to show the background image. Is it possible transparent erase using titanium for iOS?
Thanks and regards,
GANESH M
You can do this using the ti.paint module. Specifically, its ability to have an image on the canvas which can be erased. After installing, try this:
// Container window
var win = Ti.UI.createWindow({ backgroundColor: '#fff' });
// Background image
var backgroundImage = Ti.UI.createImageView({
image : 'yourbgimage.png'
width : Ti.UI.FILL,
height : Ti.UI.FILL
});
// Require paint module and add to view with an erasable image
var Paint = require('ti.paint');
var paintView = Paint.createPaintView({
image : 'yourfgimage.png', // This is the image you erase
eraseMode : true,
width : Ti.UI.FILL,
height : Ti.UI.FILL,
strokeColor : '#0f0', strokeAlpha : 255, strokeWidth : 10
});
win.add(backgroundImage);
win.add(paintView);
win.open();