Custom UIView on iPhone, should look like UIPopover - ios

my goal is to create a simple popover view over a bar button in my tool bar. So apparently Apple doesn't want me to create this on my iPhone. But i already saw something familiar on other apps.
So instead of using the UIPopOver thing from Apple, i like to create an UIView which appears when the bar button is clicked. And disappears when it is clicked again. It would be over the top if i also could create the little arrow which points to the button (you know which arrow i mean :D). But this is not relevant at this time. I just want to create this "popover appears and disappears with the same button". My "solution" right know is not a solution:
- (IBAction)buttonPressed:(id)sender
{
UIView *myPopOverView = [[UIView alloc] initWithFrame:CGRectMake(25, 25, 500, 250)];
myPopOverView.alpha = 0.0;
myPopOverView.layer.cornerRadius = 5;
myPopOverView.layer.borderWidth = 1.5f;
myPopOverView.layer.masksToBounds = YES;
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(testNSLog)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Show myPopOverView" forState:UIControlStateNormal];
button.frame = CGRectMake(10, 10, 100, 30);
[myPopOverView addSubview:button];
[self.view addSubview:myPopOverView];
[UIView animateWithDuration:0.4 animations:^{
[myPopOverView setAlpha:1.0];
} completion:^(BOOL finished) {}];
}
So i don't have a clue on how to do that with this code fragment. It appears right away as i want. But i don't know how to create this toggle. I tried with a simple Bool-If-Toggle, but it didn't work. And i don't really know how to remove it from my view either.
Can you guys help me with this?
Thanks in advance!

Ok i solved it.
i defined a UIView in the .h-File and instantiate it in ViewDidLoad, then i did:
- (IBAction)buttonPressed:(id)sender
{
if (showedOptions == NO) {
[self.view addSubview:self.popoverView];
[UIView animateWithDuration:0.4 animations:^{
[self.popoverView setAlpha:1.0];
} completion:^(BOOL finished) {}];
showedOptions = YES;
return;
} else {
showedOptions = NO;
[self.popoverView removeFromSuperview];
}
}

Related

reading taps on titleview field iOS

I'm having a problem with reading taps on navigation bar (I need to open dropdown menu by tapping on title field, just like in telegram and etc. but not in swift)
I know that basically its unreadable, and already've tried with taprecognizer, but it didn't work for me any good.
Now my menu opens with rightbarbutton - that's ugly.
How can I deal with it?
Now string that drops menu (placed in viewDidLoad) looks like:
navbar = [[UIBarButtonItem alloc]initWithTitle:#"navbar" style:UIBarButtonItemStylePlain target:self action:#selector(navigationTitleTapGestureAction:)];
and a part that declares button:
NSArray *buttons = #[navbar <<...a few more buttons...>>];
self.navigationItem.rightBarButtonItems = buttons;
EDIT: additional code from the comments:
- (IBAction)navigationTitleTapGestureAction:(id)sender {
automaticDisappearanceCanceled_ = YES;
if (menuToolbarVisible_) {
[self hideMenuAnimated:YES];
}
else {
[self showMenuAnimated:YES];
}
}
- (void)showMenuAnimated:(BOOL)animated {
[self.view layoutIfNeeded];
self.toolbarTopLayoutConstraint.constant = 0.f;
self.menuToolbar.hidden = NO;
[UIView animateWithDuration:animated ? ToolbarMenuAnimationDuration : 0.f animations:^{
[self.view layoutIfNeeded];
} completion: ^(BOOL finished) {
}];
menuToolbarVisible_ = YES;
}
- (void)hideMenuAnimated:(BOOL)animated {
[self.view layoutIfNeeded];
self.toolbarTopLayoutConstraint.constant = -ToolbarMenuHeight;
[UIView animateWithDuration:animated ? ToolbarMenuAnimationDuration : 0.f animations: ^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
self.menuToolbar.hidden = YES;
}];
menuToolbarVisible_ = NO;
}
As far is I know you just want to get taps on the text on the center of navigation bar you can do this by adding a UIButton in the titleView like this :-
UIButton *centerButton=[[UIButton alloc]initWithFrame:CGRectMake(0, 0, 44.0, 44.0)];
[centerButton setTitle:#"Center" forState:UIControlStateNormal];
[centerButton addTarget:self action:#selector(action) forControlEvents:UIControlEventTouchDown];
self.navigationItem.titleView=centerButton;

How to pass a UIButton's frame and origin between ViewControllers

I want to do an animation that zooms in from a calendar, specifically with the origin and frame size being that of the button that represent's today's date. Here is the code for determining the todayButton inside CalendarMonthView.m:
NSDate *date = (weekdayOffset > 0) ? [_monthStartDate dateByAddingTimeInterval:-1 * weekdayOffset * D_DAY] : _monthStartDate;
BOOL bEnabled = (weekdayOffset == 0);
CGRect buttonFrame = CGRectMake (0, 0, 81, 61);
int idx = -1 * weekdayOffset;
for (int y = 0; y < 6; y++) {
buttonFrame.origin.x = 0;
for (int x = 0; x < 7; x++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = idx++;
[button setFrame:buttonFrame];
[button setBackgroundImage:[UIImage imageNamed:#"calendarFlyout_dayContainer_today.png"] forState:UIControlStateSelected];
[button setBackgroundImage:[UIImage imageNamed:#"calendarFlyout_selected.png"] forState:UIControlStateHighlighted];
button.titleLabel.font = [UIFont fontWithName:#"TitilliumWeb-Regular" size:18.0];
button.titleLabel.textAlignment = NSTextAlignmentCenter;
// TODO: optimize performance
int dayOfMonth = (int)[_calendar component:NSCalendarUnitDay fromDate:date];
if (dayOfMonth < prevDayOfMonth) {
bEnabled = !bEnabled;
}
prevDayOfMonth = dayOfMonth;
[button setTitle:[NSString stringWithFormat:#"%d", dayOfMonth] forState:UIControlStateNormal];
[button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
[button setBackgroundImage:[UIImage imageNamed:((bEnabled) ? #"calendarFlyout_dayContainer_insideMonth.png"
: #"calendarFlyout_dayContainer_outsideMonth.png")]
forState:UIControlStateNormal];
// button.enabled = bEnabled;
button.selected = [date isToday];
if (button.selected == NO) {
button.highlighted = (_currentDayDate) ? [date isEqualToDateIgnoringTime:_currentDayDate] : NO;
} else {
// Set buttonHolder to today
}
[button addTarget:self action:#selector (dayButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[_dayButtonsHolderView addSubview:button];
buttonFrame.origin.x += buttonFrame.size.width;
date = [date dateByAddingTimeInterval:D_DAY];
}
buttonFrame.origin.y += buttonFrame.size.height;
}
- (IBAction)dayButtonTapped:(id)sender
{
if (_delegate) {
UIButton *button = (UIButton *)sender;
NSDate *selectedDate = [_monthStartDate dateByAddingDays:button.tag];
[_delegate performSelector:#selector (calendarMonthView:dateSelected:) withObject:self withObject:selectedDate];
}
}
I want to get the frame of button and use it in this animation used in CalendarFlyoutView.m.
I'm new to iOS programming and I read up on some delegate information and passing information through segues, but it doesn't seem to help me here.
Any help would be greatly appreciated.
Use the transform feature.
// animate in year calendar
_yearCalendarView.hidden = NO;
self.curMonthView.monthLabel.hidden = YES;
CalendarMonthView *monthView = [CalendarMonthView new];
monthView.delegate = self;
CGRect buttonFrame = _currentDayButtonFrame;
_yearCalendarView.frame = CGRectMake(buttonFrame.origin.x, buttonFrame.origin.y + buttonFrame.size.height, buttonFrame.size.width, buttonFrame.size.height);
NSLog(#"_yearCalendarView frame: %#", NSStringFromCGRect(_yearCalendarView.frame));
_yearCalendarView.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView animateWithDuration:kAnimation_ExpandCalendarDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
_yearCalendarView.transform = CGAffineTransformIdentity;
_yearCalendarView.frame = CGRectMake(_monthSwiperScrollView.frame.origin.x, _monthBarImageView.frame.size.height + 20, _monthSwiperScrollView.frame.size.width + 2, _yearFlyoutHeight);
} completion:^(BOOL finished) {
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector (yearCalendarAnimationDidStop:finished:context:)];
}];
If you are making a segue from the CalendarMonthView to the CalendarFlyoutView then you can just add this method to the CalendarMonthView.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
CalendarFlyoutView * view = segue.destinationViewController;
view.buttonFrame = button.frame;
}
and in your CalendarFlyoutView.h
#interface CalendarFlyoutView : UIViewController
#property CGRect buttonFrame;
#end
A couple of questions that need to be answered to best help you:
1) Are CalendarMonthView and CalendarFlyoutView UIView or UIViewController? You say view controller, but the class name says otherwise.
2) What is happening in the method 'dayButtonTapped'? Are you performing a segue there? Are you somehow creating or loading an instance of CalendarFlyoutView?
3) If you are not using a segue, are you somehow creating and add a child view controller for CalendarFlyoutView to CalendarMonthView?
4) What is the desired transition (your animation)? Does the CalendarFlyoutView start at the same size as the button, then fill the whole screen?
5) Is there a specific reason that you are setting the button's frame instead of constraining it in the correct place?
Once we know a little more about these questions we should be able to provide some more concrete suggestions.
It's still not very clear where the actual animation code is being run. In your question, you state "I want to get the frame of button and use it in this animation used in CalendarFlyoutView.m." which seems to imply the animation code is in CalendarFlyoutView, which seems like an odd place for it.
There are a few things I could recommend, given my incomplete understanding of the whole of the code:
1) Move the animation code to the dayButtonTapped method, where you already have a reference to the button, and therefore it's frame. It also seems like a more logical place for it.
2) Where ever you are instantiating the CalendarFlyoutView (not shown in the code you posted), assign the button frame there.
3) If there is only a single instance of CalendarFlyoutView and you have a reference to it in CalendarMonthView, you could assign a property of the flyout view that is the frame of the button you already have a reference to in the dayButtonTapped method.
I have to add though, that these are just work arounds to what seems like a structural issue. Is this a reusable control you are trying to write? Why did you decide to not use the storyboard or view controllers? Why are you using frames and absolute sizes and positions at all instead of letting auto layout do it's job (you will bang your head against the wall for hours trying to tweak everything to run correctly in all orientations and all possible device screen sizes).

load UIView from left animation on UIButton click

I am having one UIButton on navigation bar as right bar button item.
I want to show one view when I click on the UIButton,
and that view should appear animating from right to left and stops to perform some operations for user.
when user is done from his work on the view he will click on same button and view will hide animating from right to left.
I tried to load view normally I get succeed in it,
when I apply animation
view animates from right to left and disappears.
I am new to this animation scenario.
So can anyone please guide me to animate view and show hide action on same button.
Here is the code that I tried,
-(IBAction)showView :(id)sender
{
CGRect screen = [[UIScreen mainScreen]applicationFrame];
UIView *quizInfoViewObj;
quizInfoViewObj = [[UIView alloc]init];
quizInfoViewObj.frame = CGRectMake(70, 0, 250, 480);
quizInfoViewObj.backgroundColor = [UIColor orangeColor];
[UIView beginAnimations: nil context: NULL];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: #selector(pushAnimationDidStop:finished:context:)];
quizInfoViewObj.center = self.view.center;
quizInfoViewObj.center = CGPointMake(self.view.center.x - CGRectGetWidth(self.view.frame), self.view.center.y);
[UIView commitAnimations];
[self.view addSubview:quizInfoViewObj];
}
here how I want...
This code might help you.
-(IBAction)showView :(id)sender
{
UIButton *button = (UIButton *)sender;
if ([button isSelected] == NO) {
CGRect screen = [[UIScreen mainScreen]applicationFrame];
// UIView *quizInfoViewObj; // use this line in .h file variables declaration
quizInfoViewObj = [[UIView alloc]init];
quizInfoViewObj.frame = CGRectMake(self.view.frame.width, 0, 250, 480);
quizInfoViewObj.backgroundColor = [UIColor orangeColor];
[self.view addSubview:quizInfoViewObj];
[UIView beginAnimations: nil context: NULL];
quizInfoViewObj.frame = CGRectMake(70, 0, 250, 480);
[UIView commitAnimations];
}
else {
[UIView beginAnimations: nil context: NULL];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: #selector(pushAnimationDidStop:finished:context:)];
// In pushAnimationDidStop:finished:context method remove quizInfoViewObj from superview
quizInfoViewObj.frame = CGRectMake(self.view.frame.width, 0, 250, 480);
[UIView commitAnimations];
}
[button setSelected: ![button isSelected]];
}

UIButtons Won't disspear after scene transition

Hey so I have created two buttons that when pressed transition the current scene to either the next scene or the main menu and they work but neither button disappears after it has been pressed. They both carry over onto the next scene which I don't want. I've tried hiding the buttons and removing them from the superView but neither worked. Heres what the code looks like for what happens when it is pressed.
-(IBAction)buttonPressed:(UIButton *)sender
{
if ([sender isEqual:self.continueButton]) {
SKTransition* reveal = [SKTransition doorsCloseVerticalWithDuration:0.5];
SKScene* transition2Scene = [[Transition2Scene alloc] initWithSize:self.size];
[self.view presentScene:transition2Scene transition: reveal];
[self.continueButton removeFromSuperview];
self.continueButton.hidden = YES;
self.continueButton.enabled = NO;
}
else {
SKTransition* doors = [SKTransition doorsCloseVerticalWithDuration:0.5];
SKScene* spriteMyScene = [[SpriteMyScene alloc] initWithSize:self.size];
[self.view presentScene:spriteMyScene transition: doors];
self.menuButton.hidden = YES;
self.menuButton.enabled = NO;
[self.menuButton removeFromSuperview];
}
}
And heres what the coding of the buttons themselves looks like.
self.continueButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.continueButton.frame = CGRectMake(self.frame.size.width/3, self.frame.size.height * 0.5, 120, 70);
[self.continueButton setTitle:#"Continue" forState:UIControlStateNormal];
[self.continueButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.continueButton];
self.menuButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.menuButton.frame = CGRectMake(self.frame.size.width/3, self.frame.size.height * 0.6, 120, 70);
[self.menuButton setTitle:#"Main Menu" forState:UIControlStateNormal];
[self.menuButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.menuButton];
I've looked around for answers and tried some things but they didn't work cause the issue I'm having isn't quite the same so any help would be greatly appreciated thanks!
The SKScene and its contents are remove from the view when transitioning to a new scene. Views, such as your buttons, are not removed. You will need to manually remove them. Here's an example...
- (IBAction) buttonPressed:(UIButton *)sender
{
[self.continueButton removeFromSuperview];
[self.menuButton removeFromSuperview];
// Find and remove all UIButtons in your view
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
NSLog(#"%#", view);
[view removeFromSuperview];
}
}
// Verify that the UIButtons were removed
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
NSLog(#"this shouldn't happen: %#", view);
}
}
// The rest of your code
Alternatively, you can create buttons using SKSpriteNode and add them to your scene. Here's an example...
Setting up buttons in SKScene

Why do my UIView animations work okay in iOS 5 but no iOS 4?

I have a custom UIView with nested views of type UIImageView, UILabel and UIButton. The view is created in code like this:
- (void)setupView
{
popupView = [[UIView alloc] initWithFrame:CGRectMake(-116, -61, 247, 59)];
popupView.autoresizingMask = 63;
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bubble.png"]];
bgImageView.autoresizingMask = 63;
[popupView addSubview:bgImageView];
[bgImageView release];
textLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 8, 180, 20)];
textLabel.autoresizingMask = 63;
textLabel.font = [UIFont fontWithName:#"DefaultNormal" size:16];
textLabel.text = #"DYNAMIC TEXT";
[popupView addSubview:textLabel];
popupButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
[rightAccessoryButton setImage:[UIImage imageNamed:#"btn-tick.png"] forState:UIControlStateNormal];
popupButton.frame = CGRectMake(208, 8, 32, 32);
popupButton.autoresizingMask = 63;
[popupView addSubview:rightAccessoryButton];
}
I've set all their autoresizingMasks to 63 which is basically everything in the ON position (I don't know a better way of doing that except putting all the constants on a huge line of code!). Then when they need to animate the popup, I do this:
- (void)animateIn
{
float pw = 247;
float ph = 59;
// set the view's initial position
popupView.frame = CGRectMake(-pw*0.005+8, -ph*0.01-2, pw*0.01, ph*0.01);
[self addSubview:popupView];
[UIView animateWithDuration:0.12 delay:0.0 options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-pw*0.55+8, -ph*1.1-2, pw*1.1, ph*1.1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-pw*0.475+8, -ph*0.95-2, pw*0.95, ph*0.95);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.075 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-round(pw/2-8), -ph-2, pw, ph);
} completion:nil];
}];
}];
}
Bit of a complicated looking animation, but effectively this is the same animation as the mapview callout view animation.
Only thing is, it works perfectly on iOS 5 devices, but on iOS 4 devices, everything is wrong! The label doesn't show at all, the button appears and then flies off shrinking into the top right hand corder, and the background image stretches to the wrong size and in the wrong place.
Anyone else had any problems with animations in iOS 4? Do I have to do things differently than how they are currently in order to get it to work?
(1) Are you doing manual layout in a UIView subclass's layoutSubviews implemention? If not, you should not be using UIViewAnimationOptionLayoutSubviews in your options bitmask. I don't know if that's the problem but there's no point adding extra sources of possible error.
(2) When in doubt, use Core Animation. You could describe your animation sequence very handily as a nice CAAnimationGroup.

Resources