UIButton background image used for animation not aligned across devices - ios

I have a UIButton backgroundImage that I use to display a weather condition image when the loading is complete. I also create a UIImageView that replaces the UIButton to animate a series of images as a progress indicator.
My question: How can fix this animated UIImageView x-axis misalignment across multiple screen sizes?
Here's what the sequence looks like on 4.7" iPhone, the red box indicates the image I'm talking about:
First, the UIImageView animating as a progress indicator (imagine it spinning, alignment is correct)
Second, the download complete, the progress indicator replaced by a UIButton with a backgroundImage:
Third, the UIImageView animating on 4" iPhone (note misalignment on x-axis):
Fourth, the download complete, UIButton replaces it, aligned correctly:
Here's how the UIImageView *progressIndicator is configured.
Note that conditionButton is the UIButton with backgroundImage of the weather condition:
self.progressIndicator = [[UIImageView alloc] initWithFrame:self.conditionButton.frame];
self.progressIndicator.contentMode = UIViewContentModeCenter;
self.progressIndicator.animationImages = #[...long series of images...];
self.progressIndicator.animationDuration = 0.5f;
[self.conditionButton setBackgroundImage:[UIImage imageNamed:#"empty.png"] forState:UIControlStateNormal];
[self.progressIndicator startAnimating];
[self.view addSubview:self.progressIndicator];
I'm pretty sure the issue is with
self.progressIndicator = [[UIImageView alloc] initWithFrame:self.conditionButton.frame];
But I'm not sure how to resolve this.
The same problem occurs when I switch to 5.5" iPhone. I have no Auto Layout warnings, and the constraints that apply to the conditionButton are:
Align Center X to superview
Width = 94
Height = 94
Bottom and Top space to nearest neighbor = default
Any help would be greatly appreciated!

Related

Scaling down a UIButton's background image when using initWithFrame:

This is the first time I have ever designed an iOS app so I want to make sure I understand this behavior correctly.
I designed a custom bar button icon for a navigation bar in Photoshop. The final image that I saved in Photoshop was 102 x 45, and yes I realize that these dimensions are bigger than the recommended 44x44 in the iOS 7 design guidelines.
Anyways, I placed my image into the asset folder, and then programmatically set the bar button item with the following code:
UIImage* firstButtonImage = [UIImage imageNamed:#"loginbutton1"];
CGRect frame = CGRectMake(0, 0, 102, 45);
UIButton * someButton = [[UIButton alloc] initWithFrame:frame];
[someButton setBackgroundImage:firstButtonImage forState:UIControlStateNormal];
[someButton addTarget:self action:#selector(didTapLoginButton:)
forControlEvents:UIControlEventTouchUpInside];
self.rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:someButton];
self.navItem.rightBarButtonItem = self.rightBarButton;
As you can see I set the frame's width and height to the exact size of the image. When I first ran the app, I didn't like the image and thought it was too big. So I changed the width and height parameters in this statement:
CGRect frame = CGRectMake(0, 0, 70, 30);
And now the image looks perfect on the iPhone screen. This is on an iPhone 4s.
So my main question is, what is actually happening when I change the frame size? Since the frame is now smaller than the actual image size, does the image just get scaled down automatically to fit inside the frame?
Yes the image get scaled because you are using backgroundImage (not Image). Both images have different behaviors.
Check the Xcode Interface Builder, you can see there, that you can set two images: Image and Background. Background is the UIImage that get scaled for the whole frame of the UIButton.
The UIButton Class Reference allows you to access the imageView of the image (not theimageView of the backgroundImage)
Because you have access to the imageView, you can change the mode of the image with:
[[someButton imageView] setContentMode:UIViewContentModeBottomLeft];
In UIView Class Reference you can check all the UIViewContentModes provided by Apple.
You can check that changing a little bit your code:
[someButton setImage:firstButtonImage forState:UIControlStateNormal];
[[someButton imageView] setContentMode:UIViewContentModeBottomRight];

iOS custom scrollbar for UIScrollView

iOS scrollbars for a UIScrollView usually hide after a brief delay, but I want to the scrollbars in my app to show all the time like in this picture:
Do you have any Idea how to implement this feature? Can I use a custom UISlider for this? If you can provide answers, please do so in simple English because it's not my native language. Thank you!
There is no direct way to show scrollbar permanent.
You can do this by UISlider and UIImageView.
1) Add UImage View for Vertical line.
UIImageView *scrollLineImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"scroll_1-1.png"]];
scrollLineImageView.frame = CGRectMake(970,160,2,254);
[self.view addSubview:scrollLineImageView];
2) Add UISlider and transform to UISlider vertical .UISlider height should be your scroll view height.
CGAffineTransform trans = CGAffineTransformMakeRotation(M_PI * 0.5);
self.scrollViewSlider.transform = trans;
self.scrollViewSlider.frame = CGRectMake(972.5,189,0, self.textScrollView.frame.size.height);
Set Slider minimum value to 0 and maximum value to scrollView content height.
self.scrollViewSlider.minimumValue = 0.0;
self.scrollViewSlider.maximumValue = self.textScrollView.contentSize.height;
3) Set UISlider Thumb Image
[self.scrollViewSlider setThumbImage:[UIImage imageNamed:#"scroll_circle.png"] forState:UIControlStateNormal];
4) Clear Minimum and Maximum track Image.
UIImage *clearImage = [[UIImage alloc] init];
[self.scrollViewSlider setMinimumTrackImage:clearImage forState:UIControlStateNormal];
[self.scrollViewSlider setMaximumTrackImage:clearImage forState:UIControlStateNormal];
5) ScrollView Delegate Function to scroll slider
self.scrollViewSlider.value=scrollView.contentOffset.y;
I hope this helps you to show Scroll Bar Permanent.

Make an UIImageView and its UIImage scale proportionally without extra padding

I have an UIView that contains a UIImageView. The UIImageViews works like the branding logo of the app. When I rotate the device, the containing UIView resizes itself to correspond to the landscape or portrait proportions of the screen.
What I'm trying to achieve is to have the UIImageView scaled accordingly, keeping proportions also on the left margin.
This is the actual code for the top white "banner":
UIView *topBanner = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, height_topBanner)];
[topBanner setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin)];
[topBanner setBackgroundColor:[UIColor whiteColor]];
topBanner.autoresizesSubviews = YES;
// the logo
UIImage *topBanner_logo = [UIImage imageNamed:#"logo.png"];
float logoAspectRatio = topBanner_logo.size.width/topBanner_logo.size.height;
topBanner_logoView = [[UIImageView alloc] initWithFrame:CGRectMake(topBanner.frame.size.width/100*3, topBanner.frame.size.height/100*7, (topBanner.frame.size.height/100*86)*logoAspectRatio, topBanner.frame.size.height/100*86)];
[topBanner_logoView setImage:topBanner_logo];
topBanner_logoView.backgroundColor = [UIColor blueColor];
topBanner_logoView.contentMode = UIViewContentModeScaleAspectFit;
[topBanner_logoView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleRightMargin)];
[topBanner addSubview:topBanner_logoView];
[self.view addSubview:topBanner];
This is my starting point: portrait iPad on startup:
This is what happens when I rotate it in landscape:
As you can see, the proportions of the UIImage are ok, but I'm getting extra borders (I set the background color of the UIImageView to highlight it) because the UIImageView stretches itself to follow the change of the size of its container, and the UIImage is fit into the UIImageView and put on its center.
The same - reversed - happens when I start the app directly in landscape mode:
Then I rotate it:
... and I get the logo with extra borders on top and bottom.
I do see that I can write a function to recalculate every size on each rotation change, but I'm asking to myself if is there a way to set the UIImageView and the UIImage to make it works without hacking the autorotate/resize procedures of iOS. It sounds so simple!
You can solve this by not using UIViewContentModeScaleAspectFit, and instead calculating the aspect ratio of the image and using that to explicitly the width or height based on the other (width or height).
e.g. I rotate to landscape, and so I want the height to be 80% of the view.
CGFloat w = logo.image.size.width;
CGFloat h = logo.image.size.height;
CGFloat a = w / h;
CGFloat h_use = self.view.height *0.8;
CGFloat w_use = h_use*a;
Furthermore, set the content mode to UIViewContentModeScaleAspectFill instead now that you've explicitly set the aspect ratio.
You have set the auto resizing mask to flexible height and width:
[topBanner_logoView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleRightMargin)];
If you do not do that, the default is that the view will not chance size, and therefore, the image will not either.
I think it is because of topBanner_logoView.contentMode = UIViewContentModeScaleAspectFit;
Try topBanner_logoView.contentMode = UIViewContentModeCenter or topBanner_logoView.contentMode = UIViewContentModeLeft to prevent the UIImageView's image from resizing (and getting padding).
If the UIImageView is resizing, remove the autoresizing mask.

Custom MPVolumeView Thumb Image not vertically centered since iOS 5.1

I'm building an application that needs an MPVolumeView to control the volume. It worked perfectly before iOS 5.1 but since the 5.1 update the thumb image is no longer vertically centered. I tried a few things like changing imagine dimensions, resizing my views (and slider) but nothing seems to work, the thumb is just not vertically centered anymore. The only way i get a centered thumb is if i use the default iOS one.
I tried adding a UISlider to another view with the exact min, max and thumb image and that one is centered fine.
Here is the code for the MPVolumeView:
MPVolumeView *volumeView;
volumeView = [[[MPVolumeView alloc] initWithFrame:volumeViewHolder.bounds] autorelease];
[volumeViewHolder addSubview:volumeView];
UIView *volumeViewSlider;
for (UIView *view in [volumeView subviews])
{
if ([[[view class] description] isEqualToString:#"MPVolumeSlider"])
{
volumeViewSlider = view;
}
}
[(UISlider *)volumeViewSlider setThumbImage:sliderHandleIcon forState:UIControlStateNormal];
[(UISlider *)volumeViewSlider setMinimumTrackImage:leftTrackImage forState:UIControlStateNormal];
[(UISlider *)volumeViewSlider setMaximumTrackImage:rightTrackImage forState:UIControlStateNormal];
volumeViewHolder is just a UIView thats 153x33. I put the thumb in green in the screenshot.
Maybe a better solution:
User a bigger image with a transparent border on the bottom. Should be around 10px for Retina Displays.
the same problem i resolved in one project. Must be set color of left part and right part with alpha = 0 -it means transparent all slider without thumb (without moovable part of it). After we must create custom view for line of slider, without thumb. In this view any colored part may be shifted as you want, upper or below, left or right. It obtained using the defined y for your ocassion:
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(x,y,width, height)];
And add the slider to this line as subview. Resulted view will be slider. For example:
UISlider *ourSlider = ...;
//initialise UISlider
ourSlider.minimumTrackTintColor = [UIColor colorWithRed:0 green:122.0f/255.0f blue:1 alpha:0];
ourSlider.minimumTrackTintColor = [UIColor colorWithRed:0 green:122.0f/255.0f blue:1 alpha:0];
UIView *lineOfSliderWithoutThumb = ... ;
// creation it
[lineOfSliderWithoutThumb addSubview:ourSlider];
//after this lineOfSliderWithoutThumb is the our custom uislider.
Note: colors there are used as default slider colors of left and right sides of UISlider.

UIView subview placement

I have a UIView that I am placing UIImageView's into, with each UIImageView being 16 pixels wide.
The query is if I add say 5 of the UIImageViews using addSubView, and the UIView is spec'd at 16 tall by 300 wide, is there any way to have the images in the view 'stack up' so to speak, so that the images are not on top of each other? Like adding image tags to a web page.
The easiest way I see of doing this is to keep a running tally of where you last placed an image, then increment by width, something like this:
-(void) addImage:(UIImage*)img toView:(UIView*)view
{
static CGRect curFrame = CGRectMake (0,0,16,16);
UIImageView* imgView = [[UIImageView alloc] initWithFrame:curFrame];
imgView.image = img;
[view addSubview:imgView];
curFrame.origin.x += 16;
}
This will have the images appear within your view from left to right
I think I understand your question correctly. You want all the images to line up in a row correct? You would need to set the frame of the UIImageView's view. The orgin will be where the top left of your image is(x,y coordinates inside the UIView that contains it) - so you would move that over 16 each time you add another image.

Resources