I'm trying to move two UIImageView's together in accordance with a UISlider. Here is a picture for a better understanding:
When the slider's ball is slid to the far left (a value of zero), then only green shall show. When it's slid to the far right (a value of 600), only red should show. If the value of the slider is 480, it should show 80% of the red picture and 20% of the green. The code I'm using to try and achieve this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.slider.minimumValue = 0;
self.slider.maximumValue = 600;
}
- (IBAction)sliderChanged:(id)sender {
[imageViewLeft setFrame:CGRectMake(slider.value - 50, imageViewLeft.frame.origin.y,imageViewLeft.frame.size.width,imageViewLeft.frame.size.height)];
[imageViewRight setFrame:CGRectMake(slider.value + 50, imageViewRight.frame.origin.y,imageViewRight.frame.size.width,imageViewRight.frame.size.height)];
}
This is working decently, but the second I change the slider, the red image (named imageViewLeft) shrinks while the imageViewRight remains the same size. I can't for the life of me figure out why (I'm still very new with programming and iOS in general). Does anyone know what I should change or how to best accomplish this?
You can achieve more or less the same thing by keeping the green background full screen and only adjusting the red view:
- (void)viewDidLoad
{
[super viewDidLoad];
self.slider.minimumValue = 0;
self.slider.maximumValue = 600;
imageViewRight.frame = self.view.bounds;
}
- (IBAction)sliderChanged:(id)sender {
[imageViewLeft setFrame:CGRectMake(0, 0,(self.slider.value/self.slider.maximumValue)*sliderimageViewRight.frame.size.width,imageViewRight.frame.size.height)];
}
Or if you'd still rather have both views edge-to-edge then you can do:
- (void)viewDidLoad
{
[super viewDidLoad];
self.slider.minimumValue = 0;
self.slider.maximumValue = 600;
}
- (IBAction)sliderChanged:(id)sender {
[imageViewLeft setFrame:CGRectMake(0, 0,(self.slider.value/self.slider.maximumValue)*self.view.bounds.size.width,self.view.bounds.size.height)];
[imageViewRight setFrame:CGRectMake(imageViewLeft.frame.size.width, 0,self.view.bounds.size.width-imageViewLeft.frame.size.width,self.view.bounds.size.height)];
}
[self.red setFrame:CGRectMake(slider.value+50-self.view.frame.size.width, imageViewLeft.frame.origin.y,self.view.frame.size.width, imageViewLeft.frame.size.height)];
[self.green setFrame:CGRectMake(slider.value+50, imageViewRight.frame.origin.y,self.view.frame.size.width, imageViewRight.frame.size.height)];
And set maximum slider value to its width:
self.slider.maximumValue = self.slider.frame.size.width;
Related
I am trying to use the Inneractive Ad SDK 5+ in my application and I'd like to position the ad on the bottom. In every case I've tried it will always be in the middle of the screen, centred horizontally and vertically.
Code:
self.myAdView = [[IaAdView alloc]
initWithAppId:#"MyAppID_iPhone" adType:IaAdType_Banner delegate:self];
self.myAdView.adConfig.refreshIntervalInSec = 30;
[[InneractiveAdSDK sharedInstance] loadAd:self.myAdView];
Delegate method:
- (void)InneractiveAdLoaded:(IaAd *)adView {
NSLog(#"AD LOADED METHOD CALLED");
// Here I tried many things I found online without any effect
[self.view addSubview:self.myAdView];
}
Here how i implement the property at the top of the viewcontroller.m file:
#interface ViewController () <InneractiveAdDelegate>
#property (nonatomic, retain) IaAdView* myAdView;
#end
#implementation ViewController
#synthesize myAdView = _myAdView;
I am sure it must be just a tiny thing but I can't figure it out. I found many solutions that include initWithFrame but this is not usable in this case.
Any help would be appreciated.
Update 1:
I've tried:
- (void)InneractiveAdLoaded:(IaAd *)adView {
NSLog(#"AD LOADED METHOD CALLED");
self.myAdView.frame=CGRectMake(x,y,width,height); // With any number and random number
and
self.myAdView.frame=CGRectOffset(self.myAdView.frame, 0, yOffset); // With any number and random number
[self.view addSubview:self.myAdView];
}
Nothing helped. Ad stays absolutely centred. I am starting to think there is something wrong with the setup but besides the positioning everything is working fine. See photo below.
Update 2:
Tried the following without success. ios8 shows banner centred on screen and ios7 for some reason not at all once the line has been added.
- (void)InneractiveAdLoaded:(IaAd *)adView {
NSLog(#"AD LOADED METHOD CALLED");
self.myAdView.frame = CGRectMake(0, self.view.frame.size.height - self.myAdView.frame.size.height , self.view.frame.size.width, self.myAdView.frame.size.height);
[self.view addSubview:self.myAdView];
}
Here's a working solution:
You have two options here -
Wrapping your adView in the external UIView and then you have the full control
Updating the frame of adView on the 'InneractiveAdLoaded:' event
ANYWAY: adView must be added to it's superView before calling 'loadAd:' SDK method.
Let me know, if you have any questions.
Update:
Option 2:
#import "ViewController.h"
#import "InneractiveAdSDK.h"
#interface ViewController () <InneractiveAdDelegate>
#property (nonatomic, strong) IaAdView *adView;
#end
#implementation ViewController {}
- (void)viewDidLoad {
[super viewDidLoad];
self.adView = [[IaAdView alloc] initWithAppId:#"<Your ad unit ID>" adType:IaAdType_Banner delegate:self];
[self.view addSubview:self.adView];
[[InneractiveAdSDK sharedInstance] loadAd:self.adView];
}
- (void)positionAd {
const CGFloat x = (self.view.bounds.size.width - self.adView.frame.size.width) / 2.0f;
const CGFloat y = self.view.bounds.size.height - self.adView.frame.size.height;
self.adView.frame = CGRectMake(x, y, self.adView.frame.size.width, self.adView.frame.size.height);
}
#pragma mark - InneractiveAdDelegate
- (void)InneractiveAdLoaded:(IaAd *)adView {
[self positionAd];
}
- (void)InneractiveDefaultAdLoaded:(IaAd *)adView {
[self positionAd];
}
- (UIViewController *)viewControllerForPresentingModalView { return self; }
#end
Try setting its frame this way:
self.myAdView.frame=CGRectMake(x,y,width,height);
Where x,y,width,height is your desired position and size.
Or if its already positioned nicely by X coordinate, width and height you could use:
self.myAdView.frame=CGRectOffset(self.myAdView.frame, 0, yOffset);
Where yOffset is how much you want it moved on that coordinate. Be sure you calculate it using self.view.frame and not with exact number, so its on bottom on every device.
To position your banner at the bottom of your UIView you need to change its frame.
self.myAdView.frame = CGRectMake(x, y, width, height);
self.myAdView.frame = CGRectMake(0, self.view.frame.size.height - self.myAdView.frame.size.height , self.view.frame.size.width, self.myAdView.frame.size.height);
x - Set to origin of 0
y - Set origin to the UIView's height. But this will make it appear off the bottom of the screen. So, we must subtract the height of our self.myAdView to move it up onto the screen: self.view.frame.size.height - self.myAdView.frame.size.height
width - Set it to the width of the UIView: self.view.frame.size.width
height - Set it to the height of our self.myAdView: self.myAdView.frame.size.height
I'm trying to use a CCLabelTTF in the upper part of the screen, while drawing a line in the lower part using ccDrawLine. When the app starts, the label is empty, and after a while it's updated with some text. The line is drawn constantly in the draw method like that:
- (void)draw {
ccDrawColor4B(0, 255, 0, 0);
glLineWidth(40.0f);
ccDrawLine(ccp(0, 0), ccp(200, 200));
}
Thing is, the second the label is updated with text and actually displays something, the line disappears and is not drawn again, even if the label goes empty again. I'm not using any background at the moment, so it's not hiding it. I tried playing around with zOrders (even though the label and the line are in different areas of the screen) and still the line disappears. I even tried creating a CCSprite subclass with only an init and a draw method, and using it to draw the line. Here's what I have in this class:
#implementation DrawingSprite
- (id)init {
if (self = [super init]) {
}
return self;
}
- (void)draw {
ccDrawColor4B(0, 255, 0, 0); //Color of the line RGBA
glLineWidth(40.0f); //Stroke width of the line
ccDrawLine(ccp(0, 0), ccp(200, 200));
}
#end
And here's what I add to my main layer:
_topLabel = [CCLabelTTF labelWithString:#"" fontName:#"Helvetica" fontSize:24];
_topLabel.position = ccp(winSize.width/2, winSize.height - 100);
_topLabel.color = ccc3(255,255,255);
_topLabel.zOrder = -1;
[self addChild:_topLabel];
_drawingSprite = [DrawingSprite node];
_drawingSprite.zOrder = 10;
[self addChild:_drawingSprite];
What am I missing?
I think you should add
[super draw];
att the begiining of your draw method when you override the draw method of CCSprite. Only then a subclassed CCSprite does “sprite rendering” for its overridden method.
In Xcode 5.1 I have created a very simple single view app for iPhone and put the source code at GitHub:
I have disabled Autolayout and put the following views in each other: scrollView -> contentView -> imageView (here fullscreen):
For the contentView and imageView I've disabled Autoresizing and set their frames to {0, 0, 1000, 1000} - both in the Storyboard and in the viewDidLoad method.
I have enabled double tap and pinch gestures for zooming.
For double tap the image is zoomed at 100% or 50% width.
This works initially, but after device rotation it breaks:
The zoom doesn't work properly and the image is offset - you can't scroll to its top left corner:
Here is my very short code in ViewController.m, please advice how to fix it:
- (void)viewDidLoad
{
[super viewDidLoad];
_imageView.frame = CGRectMake(0, 0, 1000, 1000);
_contentView.frame = CGRectMake(0, 0, 1000, 1000);
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
float scale = _scrollView.frame.size.width / 1000;
_scrollView.minimumZoomScale = scale;
_scrollView.maximumZoomScale = 2 * scale;
_scrollView.zoomScale = 2 * scale;
_scrollView.contentSize = CGSizeMake(1000, 1000);
}
- (UIView*)viewForZoomingInScrollView:(UIScrollView*)scrollView
{
return _contentView;
}
- (IBAction)scrollViewDoubleTapped:(UITapGestureRecognizer*)sender
{
if (_scrollView.zoomScale < _scrollView.maximumZoomScale)
[_scrollView setZoomScale:_scrollView.maximumZoomScale animated:YES];
else
[_scrollView setZoomScale:_scrollView.minimumZoomScale animated:YES];
}
UPDATE: I've tried using Reveal app (here fullscreen), but couldn't find anything useful for me:
My source code seems to be okay, but in Interface Builder I had to disable "Autoresize Subviews" for the scrollView:
I'm very new to landscape adaptations. My UIScrollView with an embedded UIImageView works perfect in portrait, but when I switch to landscape it's incredibly messed up.
I tried the following:
- (void)viewDidLayoutSubviews {
self.scrollView.frame = self.view.frame;
}
But it's to no avail. When I rotate the view it still throws the image into the bottom left corner.
How do I layout a UIScrollView so when I shift to landscape, it stays centered? (Pretty much identical behavior to Photos.app is what I'm striving for.)
In my scrollViewDidZoom: I have the following as well, if relevant (it keeps it centered as the user scrolls):
CGRect newImageViewFrame = self.imageView.frame;
// Center horizontally
if (newImageViewFrame.size.width < CGRectGetWidth(scrollView.bounds)) {
newImageViewFrame.origin.x = (CGRectGetWidth(scrollView.bounds) - CGRectGetWidth(self.imageView.frame)) / 2;
}
else {
newImageViewFrame.origin.x = 0;
}
// Center vertically
if (newImageViewFrame.size.height < CGRectGetHeight(scrollView.bounds)) {
newImageViewFrame.origin.y = (CGRectGetHeight(scrollView.bounds) - CGRectGetHeight(self.imageView.frame)) / 2;
}
else {
newImageViewFrame.origin.y = 0;
}
self.imageView.frame = newImageViewFrame;
I'm a bit stuck with a problem that i've got when rotating a UIView.
I have a method called 'updatePositions' that sets the view's current frame to either the left or the right of the superview, and then calls a rotation function to rotate the entire UIView. However when I call this, the frame is set fine, but the rotation corrupts the view completely.
In my layout subviews, I create a label and bezier path, each of which are only created if the label doesn't exist and are laid out using the bounds property of the view.
Am I calling CGAffineTransformMakeRotation in the wrong place?
- (void)updatePosition
{
// If the join overview orientates to north set position
if (self.joinOverview.doesOrientateToNorth)
// If the approach track is not south west place the north indicator in the lower left of the diagram
// if approach track is south west place north indicator in lower right
if (self.joinOverview.dataItem.approachTrack != VDApproachTrackSouthWest)
[self setFrame:CGRectMake(-self.superview.frame.origin.x, self.superview.frame.size.height - VIEW_SIZE, VIEW_SIZE, VIEW_SIZE)];
else
[self setFrame:CGRectMake(self.superview.frame.size.width - VIEW_SIZE, self.superview.frame.size.height - VIEW_SIZE, VIEW_SIZE, VIEW_SIZE)];
}
else // If the join overview orientates to the approach track set rotation and position
{
// Set the position to the lower left of the view
[self setFrame:CGRectMake(-self.superview.frame.origin.x, self.superview.frame.size.height - VIEW_SIZE, VIEW_SIZE, VIEW_SIZE)];
// Rotate
self.transform = CGAffineTransformMakeRotation(DegreesToRadians(50));
}
}
- (void)layoutSubviews
{
// Super
[super layoutSubviews];
// set background colour to transparent
self.backgroundColor = [UIColor clearColor];
if (!self.northSymbol) {
// Add 'N' symbol label
self.northSymbol = [[UILabel alloc]initWithFrame:CGRectMake(0, self.bounds.size.height / 2, self.bounds.size.width, self.bounds.size.height / 2)];
[self.northSymbol setText:#"N"];
[self.northSymbol setTextAlignment:NSTextAlignmentCenter];
[self.northSymbol setFont:[UIFont boldSystemFontOfSize:18]];
[self addSubview:self.northSymbol];
self.arrow = [UIBezierPath bezierPathWithThreePointArrowFromPoint:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2)
toPoint:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 20)
headWidth:self.bounds.size.width / 2.5];
}
}
Either you're using auto layout which doesn't like transforms, or you're calling updatePosition more than once, and thus you're changing frame of already transformed view, which will cause you a lot of pain. Add
self.transform = CGAffineTransformIdentity;
as the first line of updatePosition.