I wish to create a grid-like photo gallery, where there are 3 photos in each row which has same frame size. When user taps on any photo, it has to zoom as given in the attached image & other photos has to get aligned accordingly.
I am new to UICollectionView. However I have managed to display 3 cells in a single row as given in the below screenshot.
I have done this similar to the display of UITableview. I have created a new UICollectionviewCell Class in which the frame of a single cell is declared.
bigBoxIndex is the indexpath.row in which the cell has to be expanded.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
if (bigBoxIndex == indexPath.row) {
return CGSizeMake(bigBoxWidth, bigBoxHeight);
}
else {
return CGSizeMake(boxWidth, boxHeight);
}
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
DealListCVCell *cell = (DealListCVCell*)[collectionView cellForItemAtIndexPath:indexPath];
DealListCVCell *expandedCell = (DealListCVCell*)[collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:bigBoxIndex inSection:0]];
if (bigBoxIndex == indexPath.row) {
bigBoxIndex = -1;
}
else {
bigBoxIndex = indexPath.row;
}
if (bigBoxIndex == -1) {
[collectionView performBatchUpdates:^{
for (NSInteger i = 0; i < NUMBER_OF_ITEMS; i++) {
NSIndexPath *fromIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
NSInteger j = i;
NSIndexPath *toIndexPath = [NSIndexPath indexPathForRow:j inSection:0];
[collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
}
} completion:^(BOOL finished) {}];
[UIView beginAnimations:#"Zoom" context:NULL];
[UIView setAnimationDuration:0.3];
[expandedCell.dealImg setFrame:CGRectMake(2.0f, 2.0f, boxWidth-4.0f, boxHeight-4.0f)];
[UIView commitAnimations];
}
else {
[UIView beginAnimations:#"Zoom" context:NULL];
[UIView setAnimationDuration:0.3];
[cell.dealImg setFrame:CGRectMake(2.0f, 2.0f, (2 * boxWidth)-4.0f, (2 * boxHeight)-4.0f)];
[UIView commitAnimations];
[collectionView performBatchUpdates:^{
[expandedCell.dealImg setFrame:CGRectMake(2.0f, 2.0f, boxWidth-4.0f, boxHeight-4.0f)];
for (NSInteger i = 0; i < [[self.entries objectAtIndex:0] count]; i++) {
NSIndexPath *fromIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
NSInteger j = i;
NSIndexPath *toIndexPath = [NSIndexPath indexPathForRow:j inSection:0];
[collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
}
} completion:^(BOOL finished) {}];
}
}
As per my code, when user taps on an image, it gets enlarged as given in the below screenshot.
How can I manage the layout of a single row?
Related
I've implemented a AutoComplete in google app maker. It's working fine. But the problem is when I try to save a data by writing half part of it and then just select from the list of autocomplete, it doesn't save the whole part that I selected. It just saves whatever I typed. Example: I have typed "United" and then select the options "United States" from my autocomplete options. But it only saves "United" It doesn't save the rest.
This is my Client Script.
function autocomplete(inp, arr) {
/*the autocomplete function takes two arguments,
the text field element and an array of possible autocompleted values:*/
var currentFocus;
/*execute a function when someone writes in the text field:*/
inp.addEventListener("input", function(e) {
var a, b, i, val = this.value;
/*close any already open lists of autocompleted values*/
closeAllLists();
if (!val) { return false;}
currentFocus = -1;
/*create a DIV element that will contain the items (values):*/
a = document.createElement("DIV");
a.setAttribute("id", this.id + "autocomplete-list");
a.setAttribute("class", "autocomplete-items");
/*append the DIV element as a child of the autocomplete container:*/
this.parentNode.appendChild(a);
/*for each item in the array...*/
for (i = 0; i < arr.length; i++) {
/*check if the item starts with the same letters as the text field value:*/
if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase()) {
/*create a DIV element for each matching element:*/
b = document.createElement("DIV");
/*make the matching letters bold:*/
b.innerHTML = "<strong>" + arr[i].substr(0, val.length) + "</strong>";
b.innerHTML += arr[i].substr(val.length);
/*insert a input field that will hold the current array item's value:*/
b.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";
/*execute a function when someone clicks on the item value (DIV element):*/
b.addEventListener("click", function(e) {
/*insert the value for the autocomplete text field:*/
inp.value = this.getElementsByTagName("input")[0].value;
/*close the list of autocompleted values,
(or any other open lists of autocompleted values:*/
closeAllLists();
});
a.appendChild(b);
}
}
});
/*execute a function presses a key on the keyboard:*/
inp.addEventListener("keydown", function(e) {
var x = document.getElementById(this.id + "autocomplete-list");
if (x) x = x.getElementsByTagName("div");
if (e.keyCode == 40) {
/*If the arrow DOWN key is pressed,
increase the currentFocus variable:*/
currentFocus++;
/*and and make the current item more visible:*/
addActive(x);
} else if (e.keyCode == 38) { //up
/*If the arrow UP key is pressed,
decrease the currentFocus variable:*/
currentFocus--;
/*and and make the current item more visible:*/
addActive(x);
} else if (e.keyCode == 13) {
/*If the ENTER key is pressed, prevent the form from being submitted,*/
e.preventDefault();
if (currentFocus > -1) {
/*and simulate a click on the "active" item:*/
if (x) x[currentFocus].click();
}
}
});
function addActive(x) {
/*a function to classify an item as "active":*/
if (!x) return false;
/*start by removing the "active" class on all items:*/
removeActive(x);
if (currentFocus >= x.length) currentFocus = 0;
if (currentFocus < 0) currentFocus = (x.length - 1);
/*add class "autocomplete-active":*/
x[currentFocus].classList.add("autocomplete-active");
}
function removeActive(x) {
/*a function to remove the "active" class from all autocomplete items:*/
for (var i = 0; i < x.length; i++) {
x[i].classList.remove("autocomplete-active");
}
}
function closeAllLists(element) {
/*close all autocomplete lists in the document,
except the one passed as an argument:*/
var x = document.getElementsByClassName("autocomplete-items");
for (var i = 0; i < x.length; i++) {
if (element != x[i] && element != inp) {
x[i].parentNode.removeChild(x[i]);
}
}
}
/*execute a function when someone clicks in the document:*/
document.addEventListener("click", function (e) {
closeAllLists(e.target);
// saveData();
});
}
And this is my OnAttach Function of the Text Box:
var countries = ["China", " France", "United States", "England"];
autocomplete(widget.getElement().children[1], countries);
I need to view the segments and handles of the path that defines a SymbolItem. It is a related issue to this one but in reverse (I want the behavior displayed on that jsfiddle).
As per the following example, I can view the bounding box of the SymbolItem, but I cannot select the path itself in order to view its segments/handles. What am I missing?
function onMouseDown(event) {
project.activeLayer.selected = false;
// Check whether there is something on that position already. If there isn't:
// Add a circle centered around the position of the mouse:
if (event.item === null) {
var circle = new Path.Circle(new Point(0, 0), 10);
circle.fillColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
var circleSymbol = new SymbolDefinition(circle);
multiply(circleSymbol, event.point);
}
// If there is an item at that position, select the item.
else {
event.item.selected = true;
}
}
function multiply(item, location) {
for (var i = 0; i < 10; i++) {
var next = item.place(location);
next.position.x = next.position.x + 20 * i;
}
}
Using SymbolDefinition/SymbolItem prevent you from changing properties of each symbol items.
The only thing you can do in this case is select all symbols which share a common definition.
To achieve what you want, you have to use Path directly.
Here is a sketch showing the solution.
function onMouseDown(event) {
project.activeLayer.selected = false;
if (event.item === null) {
var circle = new Path.Circle(new Point(0, 0), 10);
circle.fillColor = Color.random();
// just pass the circle instead of making a symbol definition
multiply(circle, event.point);
}
else {
event.item.selected = true;
}
}
function multiply(item, location) {
for (var i = 0; i < 10; i++) {
// use passed item for first iteration, then use a clone
var next = i === 0 ? item : item.clone();
next.position = location + [20 * i, 0];
}
}
I am trying to have the borders for the buttons change once buttons are pressed, here is how the code currently looks:
[m_btnEthinic addObject:btnEthnicity1];
[m_btnEthinic addObject:btnEthnicity2];
[m_btnEthinic addObject:btnEthnicity3];
[m_btnEthinic addObject:btnEthnicity4];
[m_btnEthinic addObject:btnEthnicity5];
[m_btnEthinic addObject:btnEthnicity6];
[m_btnEthinic addObject:btnEthnicity7];
[m_btnEthinic addObject:btnEthnicity8];
[m_btnEthinic addObject:btnEthnicity9];
for (UIButton* btn in m_btnEthinic) {
btn.layer.borderWidth = 1;
btn.layer.cornerRadius = 13;
btn.layer.borderColor = COLOR_GRAYBORDERBTN.CGColor;
[btn setBackgroundColor: COLOR_PURP];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]
With storyboard, you can do like this:
drag and place the button into viewcontroller
set the button Tag as per the buttons
drag the buttons into .h and create IBOutletCollection NSArray for buttons. Link all buttons into same outlet.
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *btn;
set IBAction common for all the buttons.
- (IBAction)btnActions:(UIButton *)sender;
once created IBAction, btnActions: method will be created in .m
-(IBAction) btnActions: (UIButton * ) sender {
for (UIButton * b in self.btn) {
//checking if already have borders for the buttons
if (b.layer.cornerRadius == 13) {
b.layer.borderWidth = 0;
b.layer.cornerRadius = 0;
}
//setting the borders for the selected button
if (b.tag == sender.tag) {
b.layer.borderWidth = 2;
b.layer.cornerRadius = 13;
b.layer.borderColor = [UIColor yellowColor].CGColor;
}
}
}
You can add a selector to you button, and use a BOOL property to track the button status and witch the color in the selector. If you have an array of buttons you will need an array of status flags. The code below should work (sorry for any typo. I am not in front of my computer at this time).
#property (strong, nonatomic) borderStatus;
-(void)viewDidLoad {
borderStatus = NO;
[btn addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)buttonPressed:(id)sender {
if(borderStatus){
((UIButton*)sender).layer.borderColor = [UIColor redColor];
borderStatus = NO;
} else {
((UIButton*)sender).layer.borderColor = [UIColor greenColor];
borderStatus = YES;
}
}
will, I guess you maybe need this. You can add two events for the buttons. So set border when the event UIControlEventTouchDown response, and recover it when the event UIControlEventTouchUpInsideresponse.
All this on my Github name 'T_yunButtonBorder' git#github.com:xmy0010/DemoForCSDN.git
Like this:
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *m_btnEthinic = #[].mutableCopy;
for (int i = 0; i < 8; i++) {
UIButton *btnEthnicity = [UIButton buttonWithType:UIButtonTypeCustom];
[btnEthnicity setTitle:[NSString stringWithFormat:#"btn%d", i] forState:UIControlStateNormal];
btnEthnicity.frame = CGRectMake(50, 50 + 40 * i, 50, 20);
btnEthnicity.backgroundColor = [UIColor redColor];
[btnEthnicity addTarget:self action:#selector(btnEthnicityTouchDown:) forControlEvents: UIControlEventTouchDown];
[btnEthnicity addTarget:self action:#selector(btnEthnicityTouchUp:) forControlEvents: UIControlEventTouchUpInside];
[self.view addSubview:btnEthnicity];
[m_btnEthinic addObject:btnEthnicity];
}
}
- (void)btnEthnicityTouchDown:(UIButton *)sender {
NSLog(#"down");
sender.layer.borderWidth = 2;
sender.layer.cornerRadius = 10;
sender.layer.borderColor = [UIColor greenColor].CGColor;
}
- (void)btnEthnicityTouchUp:(UIButton *)sender {
NSLog(#"up");
sender.layer.borderWidth = 0;
sender.layer.cornerRadius = 0;
}
for some reason when I run the game the sprite is in its jump animation and not its idle at the start even when moving left and right the sprite is still the jump animation. i followed a tutorial on youtube i know that the right and left animations work any help would be appreciated thanks.
///platform "physics"
var rkey = keyboard_check(vk_right);
var lkey = keyboard_check(vk_left);
var jkey = keyboard_check_pressed(vk_up);
//Check for ground
if (place_meeting(x, y+1, obj_solid))
{
airjump = 1;
vspd = 0;
//Jumping
if (jkey)
{
vspd = -jspd;
}
}
else
{
//Gravity
if (vspd < 10 )
{
vspd += grav;
}
//Check For airjump
if(airjump > 0)
{
if(jkey)
{
vspd = -jspd;
airjump -= 1;
}
}
}
//Moving Right
if(rkey)
{
hspd = spd;
//Left Wall-Jump
if(place_meeting(x-1, y, obj_solid) && !place_meeting(x, y+1, obj_solid)
&& !lkey)
{
vspd = -jspd;
}
}
//Moving Left
if(lkey)
{
hspd = -spd;
//Right Wall-Jump
if(place_meeting(x+1, y, obj_solid) && !place_meeting(x, y+1, obj_solid)
&& !rkey)
{
vspd = -jspd;
}
}
//Check for not moving
if((!rkey && !lkey) || (rkey & lkey))
{
hspd = 0 ;
}
//Horizontal Collisions
if(place_meeting(x + hspd, y, obj_solid))
{
while(!place_meeting(x+sign(hspd), y,obj_solid))
{
x += sign(hspd);
}
hspd = 0;
}
//Move Horizontally
x += hspd;
//Vertical Collisions
if(place_meeting(x, y+vspd, obj_solid))
{
while(!place_meeting(x, y+sign(vspd),obj_solid))
{
y += sign(vspd);
}
vspd = 0;
}
//Move Vertically
y += vspd;
//Control The Sprites
if(vspd != 0)
{
sprite_index = spr_player_jump;
image_speed = 1;
//use the next line if you have a falling animation as well but the
falling animation should be the second one
//image_index = y>yprevious;
}
else
{
if(hspd != 0)
{
sprite_index = spr_player_walk;
image_speed = .15;
}
else if(hspd = 0)
{
sprite_index = spr_player_stand;
}
}
if (!place_meeting(x,y+1, obj_solid))
{
sprite_index=spr_player_jump;
}
//Control the direction that the player is facing
if(hspd > 0)
{
image_xscale = 1;
}
else if (hspd < 0)
{
image_xscale = -1;
}
First, in the create event, set image_speed = 0; Then you have to play the animation once.
Then once you're in the step event, when the player jumps:
`while (image_index != image_number)
{
image_index++;
}
//Or you can replace image_number with the end
//value of your jump animation, if you also have other animations like
//walking then set image index to the start value before running the loop`
Also, a check to make sure the player is on the ground too (so pressing the space bar in the air doesn't make the animation play. Unless you want that.)
How to add margins to the grid elements in grid manager layout of blackberry.I want it to appear exactly like it looks on a sqlite table with rows and columns having neat margins.Also i would like to add color to each row of the grid.The elements in the grid have been fetched from sqlite table string by string.
I have the following code:
GridFieldManager grid = new GridFieldManager(10,5,0);
grid.add(new LabelField("Date"));
grid.add(new LabelField("Bill"));
grid.add(new LabelField("Receipt"));
grid.add(new LabelField("Narration"));
grid.add(new LabelField("ID"));
grid.setColumnPadding(15);
grid.setRowPadding(20);
for (int i = 1; i < grid.getRowCount(); i++) {
System.out.println("Inside for first loops");
for (int j = 0; j < grid.getColumnCount() ; j++) {
System.out.println("Inside for second loops");
while(c.next()) {
System.out.println("Inside while");
Row r;
r = c.getRow();
for (int k = 4; k >=0; k--) {
System.out.println("Inside for loops");
if(k==0 || k==3) {
System.out.println("Retrieving date or narration");
grid.insert(new LabelField(r.getString(k)) {
public void paint(Graphics graphics) {
graphics.setColor(Color.BROWN);
super.paint(graphics);
}
},i,j);
} else {
System.out.println("Retrieving other values");
String p = "" + r.getInteger(k);
grid.insert(new LabelField(p) {
public void paint(Graphics graphics) {
graphics.setColor(Color.BROWN);
super.paint(graphics);
}
},i,j);
}
grid.setBackground(
BackgroundFactory.createLinearGradientBackground(
Color.GOLD,Color.CHOCOLATE,Color.GOLDENROD,Color.CORAL));
}
System.out.println("Exiting while");
}
System.out.println("Exiting sec for");
break;
}
System.out.println("Exiting first for");
break;
}
With the above code I am getting a linear gradient background color being applied to the whole screen. Also the elements of the grid excluding the headings are in brown color.
What I now want to achieve is separate colors for each row.
Anyone aware on the solution to this please share. Thanks.
To add color to the fetched rows you could use this code:
for (int k = 4; k >=0; k--)
{
System.out.println("Inside for loops");
//Check for whether column retrieved is date or naraation
if(k==0 || k==3)
{
System.out.println("Retrieving date or narration");
grid.insert(new LabelField(r.getString(k))
{
public void paint(Graphics graphics)
{
graphics.setColor(Color.GOLD);
super.paint(graphics);
}
},i,j);
}
else
{
//Check for whether column retrieved is bills,rec or id
System.out.println("Retrieving other values");
String p = "" + r.getObject(k);
//if(r.getString(k) != null)
//{
grid.insert(new LabelField(p)
{
public void paint(Graphics graphics)
{
graphics.setColor(Color.GOLD);
super.paint(graphics);
}
},i,j);
// }
}
Using it in if else manner may help your solution.
You can achieve the color part in two ways:
Override the grid manager paint method (difficult)
Add a custom VerticalFieldManager containing exactly one label field to each cell, instead of adding the labelfield directly. This is the easiest approach IMHO.