Titanium Lazy loading only when image view is visible - ios

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;

Related

Jetpack Compose - Row Clipping Children When Width Increases

Here on the right , I have a list of items in a composable , Every item is inside a row , All the items are inside a column
All the children of the are getting clipped to fit the screen which I don't want , I want these items to render completely even if outside of screen since I have a zoomable container above them
As you can see how text in the text field is all in one line vertically rather than expanding the width , This is the problem
Code :
Row(
modifier = modifier.zIndex(3f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
SimpleNodesList(
modifier = Modifier.padding(8.dp),
parentNode = state.center,
nodes = state.center.left,
renderRight = false,
)
SimpleNode(node = state.center, parentNode = null)
SimpleNodesList(
modifier = Modifier.padding(8.dp),
parentNode = state.center,
nodes = state.center.right,
renderLeft = false
)
}
Simple Nodes List is a column of rows , I have one column on left and one on the right , If the width of the left column increases , right row get's clipped by the screen
Using this modifier does the job for the row , In my case I also needed this layout modifier , wrapContentSize(unbounded = true) was working but children weren't clickable for some reason outside the bounds of the zoom container !
I also had to create a modifier zoomable rather than use a zoomable box , so the zoomable touch events would be dispatched on the this composable rather than the parent !
modifier = Modifier
.layout { measurable, constraints ->
val r =
measurable.measure(constraints = constraints.copy(maxWidth = Constraints.Infinity))
layout(r.measuredWidth, r.measuredHeight, placementBlock = {
r.placeWithLayer(0, 0, 0f) {
}
})
}
.wrapContentSize(unbounded = true)
If you are using hard-coded width for the text, applying Modifier.wrapContentSize() on every container might do the job
Use SimpleFlowRow in place of Row. It will fix the clipping issue.

Photoswipe does not close properly in this implementation [with Slick Carousel]

I'm experiencing a problem that seems to be reproduced randomly after closing Photoswipe when there is more than one image in the Slick carousel. Visually, the effect is that Photoswipe closes (disappears without any animation), then the right side of the page changes again to black with last photo viewed in Photoswipe visible, then the black background fades to transparent but seems to be still there (it prevents any buttons from being clicked).
In case it's relevant, the Photoswipe open animation don't behave like the demos either - it doesn't zoom in from the thumbnail, it just simply fades in from the center of the page.
Image of the page after problem occurs: https://i.imgur.com/a4XEMxU.png
Here is my implementation using Slick and Photoswipe together:
var carousel = $('#sc');
var pswpImages = [];
var options = {
history: false
};
var count = 0;
for (var fn in data.images) {
var pieces = fn.split('.');
var fullsize = meta_data['media'] + fn;
var thumbnail = meta_data['cache'] + pieces[0] + '_m.' + pieces[1];
carousel.append('<div><img src="' + thumbnail + '" class="sc" data-id="' + count + '"></div>');
count += 1;
$('.sc').each(function () {
$(this).on('click', function () {
options.index = $(this).data('id');
var pswpElement = document.querySelectorAll('.pswp')[0];
var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, pswpImages, options);
gallery.init();
})
});
pswpImages.push({
src: fullsize,
msrc: thumbnail,
w: data.images[fn]['x'],
h: data.images[fn]['y']
});
}
// TODO: When closing gallery, get image number, and slick.GoTo that slide
carousel.slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
variableWidth: true,
centerMode: true
});
Could you provide a fiddle?
I suspect the $('.sc').each(function () needs to be outside the for loop, otherwise you are creating an on click event for every img previously created by the for loop.
1st iteration:
create 1 div, .each( ..on('click')) on that 1 img
2nd iteration:
create 2nd div, .each( ..on('click')) on the first AND the second img
..and so on.
So, in the end: clicking an image will start multiple instances of PhotoSwipe, but only if there are more than 1 images - just like you observed. The first iteration ist still fine.
A simple fix could be to call .off() before .on(), like:
...
$('.sc').each(function () {
$(this).off().on('click', function () {
options.index = $(this).data('id');
...

Loading image from plist always height and width equals to zero

I'm trying to load an image from a plist already cached and get the height and width of it, but it's always zero.
I found here that this problems is solved by preloading the images but even though I'm preloading the plist like:
cc.game.onStart = function(){
if(!cc.sys.isNative && document.getElementById("cocosLoading")) //If referenced loading.js, please remove it
document.body.removeChild(document.getElementById("cocosLoading"));
// Pass true to enable retina display, disabled by default to improve performance
cc.view.enableRetina(false);
// Adjust viewport meta
cc.view.adjustViewPort(true);
// Setup the resolution policy and design resolution size
cc.view.setDesignResolutionSize(800, 450, cc.ResolutionPolicy.SHOW_ALL);
// The game will be resized when browser size change
cc.view.resizeWithBrowserSize(true);
//load resources
console.log(g_resources);
cc.LoaderScene.preload([{type:'plist', src: "res/tiles.plist"}], function () {
cc.director.runScene(new HelloWorldScene());
}, this); };
It still doesn't show the size:
var HelloWorldLayerTile = cc.Layer.extend({
buildGround: function(){
var tile = new cc.Sprite(cc.spriteFrameCache.getSpriteFrame("yellowTile.png"));
console.log(tile.width); //Always get 0
console.log(tile.getContentSize().height); //Always get 0
this.addChild(tile);
},
ctor:function () {
//////////////////////////////
// 1. super init first
this._super();
this.buildGround();
return true;
}
});
var layer;
var HelloWorldScene = cc.Scene.extend({
onEnter:function () {
this._super();
cc.spriteFrameCache.addSpriteFrames(res.tiles);
layer = new HelloWorldLayerTile();
this.addChild(layer);
}
});
when you tried to get frame by
cc.spriteFrameCache.getSpriteFrame("yellowTile.png")
it returned undefined because you haven't added the frames into frameCache.
you should both load the png file, and add frames into frameCache after loaded
try these:
cc.LoaderScene.preload([{type:'plist', src: "res/tiles.plist"}, {type:'png', src:"tiles.png"}], function () {
cc.spriteFrameCache.addSpriteFrames("res/tiles.plist");
cc.director.runScene(new HelloWorldScene());
}, this);

changing image view into a blob does not always work .toImage();

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.

Set z-index to dynamically generated image label to prevent overlapped label hidden from image

I am implementing drag and drop, user can drag few images and drop them in a div, and I dynamically append a p tag as label to each image once user click on a button.
Currently I meet problem when I have 2 images which is very close to each other (one is on top of another). The appended p tag for the top images will be hidden by the bottom image. I tried to alert the z-index for each dropped image, and found out it is 'auto'. I guess I need to assign a new z-index for each div, but I tried in the function which i append the label, and it dint work as expect:
function generateLabel() {
var current = 5000;
$('#rightframe img').each(function () {
var cImgName = $(this).attr('id');
var width = $(this).width();
// To select the respective div
var temp = "div#" + cImgName;
$.ajax({
url: '/kitchen/generatelabel',
type: 'GET',
data: { containerImgName: cImgName },
async: false,
success: function (result) {
$(temp).append(result);
// I guess the each function loop through each div according to the time it is created, so I try to assign a decreasing z-index
$(temp).css('z-index', current);
current -= 100;
// To select the label for the image
temp += " p";
// Set label width based on image width
$(temp).width(width);
}
});
});
However, what I get is, bottom image which dropped later do NOT hide the label of the image above, but if the above image is dropped after than the bottom image, above image's label is hide by the bottom image.
It's a very specific situation and I hope I do make myself clear...
Hope can get some help here... Appreciate any feedback...
I am so glad that I able to work out a solution for this kinda weird problem. I get to one useful plugin, the jquery-overlaps which check 2 dom whether they are overlapped with each other or not. Then i assign a z-index to the label accordingly.
Just to show my solution here, in case anyone jump into this bottleneck :)
// To assign an increasing z-index to the label
var count = 100;
$('#rightdiv p').each(function () {
// If any label overlaps with the image (used overlaps plugin)
if ($(this).overlaps($('#rightdiv img'))) {
// Increase count (the z-index)
count += 10;
// Set the parent div z-index 1st, if not the label z-index do not have effect
$(this).parent().css('z-index', count);
$(this).css('z-index', count);
}
});
Thanks! :D

Resources