I know how to add UIButton to a UIView programmatically. But I'm stuck in adding the UIButton in the new YPosition after a certain number of UIButtons are added in the previous YPosition.
Here is my case:
Number of UIButtons to be added comes from NSArray - Let's take 20
UIView is already added in the UIViewController - Let's call
'buttonView'
I'm creating UIButton using the loop (up to 20). I have set the
buttonWidth as 70 and buttonHeight as 45
I'm getting the screen size and dividing this by the buttonWith, so
as to calculate the number of items that can be accommodated per line
or per Y position.
If the screen width is 414, then 414/70 = ~5.9 and I'm taking it as
First 5 UIButton's YPosition as 0 and XPosition starts from 0 and adding buttonWidth for subsequent buttons.
Next 5 UIButtons (6-10) should have the new YPosition as 1-5 UIButton
Yposition(0)+buttonHeight(45)+somespace(10)= 55 and XPostion should
start with 0.
For the next set of UIButtons(11-15), the YPosition should be
Yposition(55)+buttonHeight(45)+somespace(10)= 100 and XPosition
starts with 0
How to achieve this? Below is my code
xPos = 8.0f;
yPos = 0.0f;
totalSlots =timeslots.Count - //Total Number UIButtons to be creted
buttonWidth = 70;
buttonHeight = 45;
buttonViewWidth = this.view.frame.size.width // I'm getting the screen
buttonPerLine = scrollViewWidth / (buttonWidth + 10); // This calculates no.of.buttons per line/Y Position. I'm rounding off as said before
numberOfLine = totalSlots / buttonPerLine // This gives how many lines needed
for (int i = 0; i < totalSlots; i++)
{
timeSlotbtn[i] = new UIButton();
timeSlotbtn[i] = new UIButton();
timeSlotbtn[i].Frame = new CGRect(xPos, yPos, buttonWidth, buttonHeight);
timeSlotbtn[i].SetTitle(buttonText, UIControlState.Normal);
timeSlotbtn[i].Layer.BorderWidth = 2.0f;
timeSlotbtn[i].Layer.CornerRadius = 3;
timeSlotbtn[i].Tag = i;
timeSlotbtn[i].TitleLabel.Font = UIFont.FromName("HelveticaNeue-bold", 14.0f);
xPos = timeSlotbtn[i].Frame.Location.X + buttonWidth + buttonSpace;
timeslotScrollView.AddSubview(timeSlotbtn[i]);
}
Pleas be noted the above code is written in Xamarin.iOS. If you know the solution, then probably you can write in Objective-c. Anyhow, the logic should be same.
int buttonWidth = 65;
int buttonSpace = 5;
int buttonHeight = 30;
int totalSlots = timeslots.Count;
nfloat screenSize = firstViewController.screenSize;
nfloat buttonPerLine = screenSize / (buttonWidth + buttonSpace );
int roundedButtonPerLine = Convert.ToInt32(Math.Floor(buttonPerLine));
nfloat totalLines = totalSlots / buttonPerLine;
int roundedTotalLines = Convert.ToInt32(Math.Ceiling(totalLines));
nfloat determineXPosition = (screenSize - (8 + (buttonWidth * roundedButtonPerLine) + (buttonSpace*(roundedButtonPerLine-1))))/2;
nfloat xPos;
if (roundedTotalLines > 1)
{
xPos = determineXPosition;
}
else
{
xPos = 8.0f;
}
nfloat yPos = 0.0f;
int currentLine = 1;
int loopCount = 1;
for (int i = 0; i < room.timeslots.Count; i++)
{
var buttonText = room.timeslots[i].startDate.ConvertDateToStanfordLocalTime();//hour + ":" + minute + "p";
timeSlotbtn[i] = new UIButton();
timeSlotbtn[i].Frame = new CGRect(xPos, yPos, buttonWidth, buttonHeight);
timeSlotbtn[i].SetTitle(buttonText, UIControlState.Normal);
timeSlotbtn[i].Layer.BorderWidth = 2.0f;
timeSlotbtn[i].Layer.CornerRadius = 3;
timeSlotbtn[i].Tag = i;
timeSlotbtn[i].TitleLabel.Font = UIFont.FromName("HelveticaNeue-bold", 14.0f);
xPos = timeSlotbtn[i].Frame.Location.X + buttonWidth + buttonSpace;
timeslotScrollView.AddSubview(timeSlotbtn[i]);
if (loopCount == roundedButtonPerLine)
{
if (roundedTotalLines > 1)
{
xPos = determineXPosition;
}
else
{
xPos = 8.0f;
}
currentLine++;
yPos = timeSlotbtn[i].Frame.Location.Y + buttonHeight + buttonSpace;
loopCount = 0;
}
loopCount++;
}
Related
I am using a for loop to make 7 rope link sprites, can't figure out how to make rope out of them with SKPhysicsJointLimit. :'(
-(void)ropeStuff {
int i ;
int y;
SKSpriteNode *ropes;
SKPhysicsJointLimit * ropeLink;
NSMutableArray *ropeArray;
for (i = 0 ; i < 7; ++i) {
if (i) {
int x = 16;
y = (x * i);
ropes.position = CGPointMake(_cat.position.x, _cat.position.y + (x * i) );
}
ropes = [SKSpriteNode node];
ropes = [SKSpriteNode spriteNodeWithImageNamed:#"rope link.png"];
ropes.position = CGPointMake(_cat.position.x, _cat.position.y +5);
ropes.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:1];
ropes.physicsBody.affectedByGravity = YES;
ropes.physicsBody.dynamic = YES;
ropes.name = #"rope";
[_worldNode addChild:ropes];
if (i) {
ropeLink = [SKPhysicsJointLimit jointWithBodyA:ropes.physicsBody
bodyB:ropes.physicsBody anchorA:ropes.position anchorB:ropes.position];
[_worldNode.scene.physicsWorld addJoint:ropeLink];
}
}
}
Thank you all for the help! :D
Why are you using SKPhysicsJointLimit? The rope is a group of segments that rotate relatively each other. You should use SKPhysicsJointPin with or without rotation limits.
in the init-method I initialize a NSMutableArray holding 4 images. I use this code to radomly place out the sprites (images):
_obstacles = [[NSMutableArray alloc] initWithCapacity:TOTAL_OBSTACLES_PER_WALL];
for (int i = 0; i < TOTAL_OBSTACLES_PER_WALL; i++)
{
obstacle = [CCSprite spriteWithTexture:obstaclesTxt];
int minX = obstacle.contentSize.width/2;
int maxX = winSize.width-obstacle.contentSize.width/2;
int xRange = maxX-minX;
int minY = obstacle.contentSize.height/2;
int maxY = winSize.height-obstacle.contentSize.height/2;
int yRange = maxY - minY;
randomXloc = (arc4random() % xRange) + minX;
randomYloc = (arc4random() % yRange) + minY;
obstacle.position = ccp(randomXloc, randomYloc);
[_wall2 addChild:obstacle];
}
Then, in an update-method, if _wall2 leaves screen to the left (it is continously scrolling from right to left) the obstacles should be removed.
if (_wall2.position.x+_wall2.boundingBox.size.width <- 0)
{
_wall2.position = ccp(_wall.boundingBox.origin.x+_wall.boundingBox.size.width+1, 0);
[obstacle removeFromParentAndCleanup:YES];
}
When I run the app, the images are placed out randomly, but when the _Wall2 leaves the screen the app crashes. My question is if it is anything wrong with this code?
I am creating a rubber band in Box2d. Here is my code.
// init physics
[self initPhysics];
// Create ball body
CCSprite *ball = [CCSprite spriteWithFile:#"rubberband.png"];
ball.position = ccp(100, 100);
ball.tag = 1;
// [self addChild:ball];
//=======Params
// Position and size
b2Vec2 lastPos = b2Vec2(154.0/PTM_RATIO,65.0/PTM_RATIO); //set position first body
float widthBody = 2.0/PTM_RATIO;
float heightBody = 2.0/PTM_RATIO;
// Body params
float density = 0.0;
float restitution = 0.5;
float friction = 0.5;
// Distance joint
float dampingRatio = 0.85;
float frequencyHz = 10;
// Rope joint
float kMaxWidth = 50.0/PTM_RATIO;
// Bodies
int countBodyInChain = 68;
b2Body* prevBody;
//========Create bodies and joints
for (int k = 0; k < countBodyInChain; k++) {
b2BodyDef bodyDef;
if(k==0 || k==countBodyInChain-1) bodyDef.type = b2_staticBody; //first and last bodies are static
else bodyDef.type = b2_dynamicBody;
bodyDef.position = lastPos;
bodyDef.fixedRotation = YES;
b2Body* body = world->CreateBody(&bodyDef);
b2PolygonShape distBodyBox;
distBodyBox.SetAsBox(widthBody, heightBody);
b2FixtureDef fixDef;
fixDef.density = density;
fixDef.restitution = restitution;
fixDef.friction = friction;
fixDef.shape = &distBodyBox;
body->CreateFixture(&fixDef);
if(k>0) {
b2RevoluteJointDef armJointDef;
armJointDef.Initialize(prevBody, body, lastPos);
armJointDef.enableMotor = true;
armJointDef.enableLimit = true;
armJointDef.maxMotorTorque = 1;
world->CreateJoint(&armJointDef);
//Create rope joint
b2RopeJointDef rDef;
rDef.maxLength = (body->GetPosition() - prevBody->GetPosition()).Length() * kMaxWidth;
rDef.localAnchorA = rDef.localAnchorB = b2Vec2_zero;
rDef.bodyA = prevBody;
rDef.bodyB = body;
rDef.collideConnected = false;
world->CreateJoint(&rDef);
} //if k>0
lastPos += b2Vec2(widthBody, 0); //modify b2Vect for next body
prevBody = body;
} //for -loop
[self scheduleUpdate];
}
return self;
}
Problem is that when the app starts, rubber band appears in stretched form in U shape and then it gradually start contracting and coming to become straight horizontally. Can anyone please tell me why it is happening? I want the rubber band to be without being stretched in the beginning.
Best Regards
You don't update lastPos so all bodies occupy the same position initially. Box2D will force them apart and this could lead to the problem.
Here is an image in iPhoto:
Here is it zoomed in to the top left corner in iPhoto:
Here is the same image in my app:
Here it is zoomed in to the top left corner in my app:
How can I lose the excess grey space surrounding my image and restrict the scrolling to the bounds of the UIImage like iPhoto?
Thanks
You could use a library that does that. Try MWPhotoBrowser.
So, aside from using a 3rd party library, I solved this problem using:
iOS. How do I restrict UIScrollview scrolling to a limited extent? , adapting the answer to the following methods, which are I hope self explanatory:
- (CGRect) methodThatGetsImageSizeOnScreen
{
float frameHeight;
float frameWidth;
float frameXOrigin;
float frameYOrigin;
float threshold;
BOOL thisImageTouchesLeftAndRight;
UIInterfaceOrientation thisOrientation = self.interfaceOrientation;
if (UIInterfaceOrientationIsLandscape(thisOrientation)){
threshold = 748.0/1024.0;
if ((self.imageToPresent.size.height == self.imageToPresent.size.width) | ((self.imageToPresent.size.height/self.imageToPresent.size.width) > threshold)){
thisImageTouchesLeftAndRight = NO;
frameWidth = (748/self.imageToPresent.size.height)*self.imageToPresent.size.width;
frameHeight = 748;
frameXOrigin = (1024-frameWidth)/2;
frameYOrigin = 0;
}
else
{
thisImageTouchesLeftAndRight = YES;
frameWidth = 1024;
frameHeight = (1024/self.imageToPresent.size.width)*self.imageToPresent.size.height;
frameXOrigin = 0;
frameYOrigin = (748-frameHeight)/2;
}
}
else {
threshold = 768.0/1004.0;
if ((self.imageToPresent.size.height == self.imageToPresent.size.width) | ((self.imageToPresent.size.width/self.imageToPresent.size.height) > threshold)){
thisImageTouchesLeftAndRight = YES;
frameWidth = 768;
frameHeight = (768/self.imageToPresent.size.width)*self.imageToPresent.size.height;
frameXOrigin = 0;
frameYOrigin = (1004-frameHeight)/2;
}
else
{
thisImageTouchesLeftAndRight = NO;
frameWidth = (1004/self.imageToPresent.size.height)*self.imageToPresent.size.width;
frameHeight = 1004;
frameXOrigin = (768-frameWidth)/2;
frameYOrigin = 0;
}
}
CGRect theRect = CGRectMake(frameXOrigin, frameYOrigin, frameWidth, frameHeight);
return theRect;
}
#pragma mark - UIScrollViewDelegate
- (void) scrollViewDidScroll:(UIScrollView*)scroll{
UIInterfaceOrientation thisOrientation = self.interfaceOrientation;
float largeDimension;
float smallDimension;
if (UIInterfaceOrientationIsLandscape(thisOrientation)){
largeDimension = 1024;
smallDimension = 748;
}
else{
largeDimension = 1004;
smallDimension = 768;
}
CGPoint offset = scroll.contentOffset;
CGRect results = [self methodThatGetsImageSizeOnScreen];
float frameHeight = results.size.height;
float frameYOrigin = results.origin.y;
float frameWidth = results.size.width;
float frameXOrigin = results.origin.x;
//So, we start the limiting of a landscape image in portrait (in the y direction) when we exceed the following criteria:
if((frameHeight*self.scrollView.zoomScale) > largeDimension){
if(offset.y < self.scrollView.zoomScale*frameYOrigin) offset.y = self.scrollView.zoomScale*frameYOrigin;
if(offset.y > ((self.scrollView.zoomScale*frameYOrigin)+(frameHeight*self.scrollView.zoomScale)-largeDimension)) offset.y = ((self.scrollView.zoomScale*frameYOrigin)+(frameHeight*self.scrollView.zoomScale)-largeDimension);
}
if((frameWidth*self.scrollView.zoomScale) > largeDimension){
if(offset.x < self.scrollView.zoomScale*frameXOrigin) offset.x = self.scrollView.zoomScale*frameXOrigin;
if(offset.x > ((self.scrollView.zoomScale*frameXOrigin)+(frameWidth*self.scrollView.zoomScale)-largeDimension)) offset.x = ((self.scrollView.zoomScale*frameXOrigin)+(frameWidth*self.scrollView.zoomScale)-largeDimension);
}
// Set offset to adjusted value
scroll.contentOffset = offset;
//Remember you may want your minimum zoomScale set in viewDidLoad or viewWillAppear
}
I'm a little confused at the moment, first time poster here on stack overflow. I'm brand new to objective C but have learned a lot from my coworkers. What I'm trying to do is traverse a bmContext vertically shifting horizontally by 1 pixel after every vertical loop. Heres some code:
NSUInteger width = image.size.width;
NSUInteger height = image.size.height;
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = width * bytesPerPixel;
NSUInteger bytesPerColumn = height * bytesPerPixel;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = height}, image.CGImage);
UInt8* data = (UInt8*)CGBitmapContextGetData(bmContext);
const size_t bitmapByteCount = bytesPerRow * height;
struct Color {
UInt8 r;
UInt8 g;
UInt8 b;
};
for (size_t i = 0; i < bytesPerRow; i += 4) //shift 1 pixel
{
for (size_t j = 0; j < bitmapByteCount; j += bytesPerRow) //check every pixel in column
{
struct Color thisColor = {data[j + i + 1], data[j + i + 2], data[j + i + 3]};
}
}
in java it looks something like this, but I have no interest in the java version it's just to emphasis my true question. I only care about the objective c code.
for (int x = 0; x = image.getWidth(); x++)
{
for (int y = 0; y = image.getHeight(); y++)
{
int rgb = image.getRGB(x, y);
//do something with pixel
}
}
Am I really shifting one unit horizontally and then checking all vertical pixels and then shifting again horizontally? I thought I was but my results seem to be a little off. In java and c# achieving a task was rather simple, if anyone knows a simpler way to do this in Objective C please let me know. Thanks in advance!
The way you are getting at the pixels seems to be off.
If I'm understanding correctly, you just want to iterate through every pixel in the image, column by column. Right?
This should work:
for (size_t i = 0; i < CGBitmapContextGetWidth(bmContext); i++)
{
for (size_t j = 0; j < CGBitmapContextGetHeight(bmContext); j++)
{
int pixel = j * CGBitmapContextGetWidth(bmContext) + i;
struct Color thisColor = {data[pixel + 1], data[pixel + 2], data[pixel + 3]};
}
}