My UIPickerView Working perfect. Apparently I got confused with its behaviour - if I keep below code my picker remain visible (which is exactly what I want)
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSLog(#"=====");
}
Now If I just one line Picker automatically get hidden and my button title label also get set with appropriate value.
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
[MyButtonObj setTitle:myarray[row] forState:UIControlStateNormal];
}
I am not getting why setting button title makes uipickerview hidden automatically.
On button click I am displaying pickerview using View animation.
if (!isPickerDisplay)
{
[UIView animateWithDuration:0.25 animations:^{
CGRect temp = _ownPickerView.frame;
temp.origin.y = self.view.frame.size.height - _ownPickerView.frame.size.height;
_ownPickerView.frame = temp;
}
completion:^(BOOL finished)
{
NSLog(#"picker displayed");
isPickerDisplay = YES;
}];
}
Related
I found on this forum a method that can create a border from ether side of a view, with I applying on my labels in my cell when it created in cellForRowAtIndexPath
the problem is when i select the cell the lines I created are gone, when I deselect the cell I can see the line again.
I had an issue when the cell is selected the labels text color in the cell get change to white but u fixed this with the method setSelected , with help me save cell labels colors before it selected. the problem is it dosent work the same way
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
[self saveTextColors];
[self saveLeftBoarders];
}
- (void)saveLeftBoarders {
[self addLeftBorderWithColor:[UIColor grayColor] Width:1.0 andView:amountV];
[self addLeftBorderWithColor:[UIColor grayColor] Width:1.0 andView:amountPay];
[self addLeftBorderWithColor:[UIColor grayColor] Width:1.0 andView:date];
[self addLeftBorderWithColor:[UIColor grayColor] Width:1.0 andView:month];
}
- (void)saveTextColors {
UIColor *leftPayColor = self.leftPay.textColor;
UIColor *amountVColor = self.amountV.textColor;
UIColor *monthColor = self.month.textColor;
UIColor *amountPayColor = self.amountPay.textColor;
UIColor *dateColor = self.date.textColor;
self.leftPay.highlightedTextColor = leftPayColor;
self.amountV.highlightedTextColor = amountVColor;
self.month.highlightedTextColor = monthColor;
self.amountPay.highlightedTextColor = amountPayColor;
self.date.highlightedTextColor = dateColor;
}
- (void)addLeftBorderWithColor:(UIColor *)color Width:(CGFloat) borderWidth andView:(UIView *)view {
UIView *border = [UIView new];
border.backgroundColor = color;
border.frame = CGRectMake(0, 0, borderWidth, view.frame.size.height);
[border setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin];
[view addSubview:border];
}
this code is from the cell.m
in the method cellForRowAtIndexPath I run the same method to create the border line.
as I type this question I saw in the debugView that this creates a problem of creating that border over and over again but is still not visible,
after deleting the border creation in the cell.m I saw in the debug view hierarchy that the border is there ( from it creation in cellForRowAtIndexPath) but it not visible.
what is the problem ?
I have implemented refreshControl as shown below in viewDidLoad():
refreshControl = [[UIRefreshControl alloc] init];
if (#available(iOS 10.0, *)) {
self.tableView.refreshControl = refreshControl;
} else {
[self.tableView addSubview:refreshControl];
}
Now I am presenting another viewController which has options to select filters. And after selecting those filters you come back again to current viewController having refreshControl.
I have added below code in viewDidAppear() for manually calling beginRefreshing:
if (self.filterChanged) {
self.filterChanged = NO;
[self.activityTableView setContentOffset:CGPointMake(0, - refreshControl.frame.size.height) animated:YES];
[refreshControl setHidden:NO];
[refreshControl beginRefreshing];
}
I have used setContentOffset for scrolling back to top and showing refreshControl.
The only problem is suppose my tableView is half scrolled in between then there is a big gap between refreshControl.
If my tableView is not scrolled then it works fine like I have pulled down to refresh, but if it is half scrolled then inspite of giving setContentOffset there is a big gap between refreshControl and tableview.
You need to wait for the scroll to finish before you can start the refresh. Unfortunately there is no completion block on setContentOffset, so try this.
After creating your refresh control set the target and create a corresponding method.
[_refreshControl addTarget:self action:#selector(refreshRequested) forControlEvents:UIControlEventValueChanged];
- (void)refreshRequested {
[_activityTableView reloadData];
}
In your viewDidAppear you scroll to top and refresh when done.
[UIView animateWithDuration:0.25 delay:0 options:0 animations:^(void){
self.activityTableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
} completion:^(BOOL finished){
[self.refreshControl beginRefreshing];
[self refreshRequested];
}];
When finished loading you need to end refresh and make sure to scroll back to zero position.
- (void)finishedLoading {
[_refreshControl endRefreshing];
[self.activityTableView setContentOffset:CGPointMake(0, 0) animated:YES];
}
On any 2014+ iPhone or iPad, double-click the home button to see the "app manager"
This is a left-right UICollectionView BUT it has a "swipe-away" gesture .. swipe up. How is it done? It's not so easy to "remove" a cell from a UICollectionView.
Footnote for googlers .. for the general problem of "peeling off", "tearing away", one cell from a collection view, here's a full tidy explanation: https://stackoverflow.com/a/24339705/294884 Hope it helps someone.
It can be much simpler than the comments on your question are suggesting.
Your cell should contain a view (the thing that you're going to drag off) and you add a UIPanGestureRecognizer to that view.
In the gesture's action method, you move the view up or down, and when it gets far enough off that you want to delete it, you just animate it off. There are plenty of questions here dealing with this part.
This leaves a gap in your collection and now you need to move things around. It turns out this is quite simple:
[_collectionView performBatchUpdates:^{
[_collectionView deleteItemsAtIndexPaths:#[indexPath]];
} completion:^(BOOL finished) {
// you might want to remove the data from the data source here so the view doesn't come back to life when the collection view is reloaded.
}];
The stuff to the right of the removed cell slides over and we're all good.
Another problem to get over: making sure your gesture recognizer and the collection view's one play nice together. Thankfully, that's not too tricky either.
[_collectionView.panGestureRecognizer requireGestureRecognizerToFail:pgr]; //where pgr is the recognizer you made for dragging the view off
This means in order for the collection view's pan gesture to do its thing, your one has to fail. So you'll want to set yours up so that it only works when panning up and down, and let the collection view still do its thing for left to right pans. In your gesture recognizers's delegate, implement the following method which simply checks if you're moving more on the x-axis or y-axis.
-(BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
CGPoint translation =[gestureRecognizer translationInView:self.view];
return(translation.x * translation.x > translation.y * translation.y);
}
I was looking for this functionality and using #mbehan suggestion i faked this functionality using UICollectionView.
What i did is i added a view of smaller size on a collection cell(Transparent background) and added a single pan gesture on CollectionView(not on each cell) then on pan gesture i move the view and it looks like the cell is moving. After view reaches some point i first hide it and then deletes the collection view cell.
Cell Hierarchy : collectionViewCell -> View(tag value==2) -> UILabel(tag Value == 1)
Label is just used for placeholder purpose.
i am posting my code below:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = (UICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"Cards" forIndexPath:indexPath];
UILabel *lblNumber = (UILabel*)[cell.contentView viewWithTag:1];
UIView *viewTouch = (UIView*)[cell.contentView viewWithTag:2];
[viewTouch setHidden:NO];
[lblNumber setText:arrCards[indexPath.row]];
return cell;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 50, 0, 30);
}
-(BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
if([gestureRecognizer isEqual:panGesture]) {
CGPoint point = [(UIPanGestureRecognizer*)gestureRecognizer translationInView:collectionView_];
if(point.x != 0) { //adjust this condition if you want some leniency on the X axis
//The translation was on the X axis, i.e. right/left,
//so this gesture recognizer shouldn't do anything about it
return NO;
}
}
return YES;
}
- (IBAction)panGestureCalled:(UIPanGestureRecognizer *)sender {
yFromCenter = [sender translationInView:collectionView_].y; //%%% positive for up, negative for down
UIView *view = sender.view;
CGPoint location = [view.superview convertPoint:view.center toView:collectionView_];
NSIndexPath *indexPath = [collectionView_ indexPathForItemAtPoint:location];
UICollectionViewCell *cell = [collectionView_ cellForItemAtIndexPath:indexPath];
UIView *touchView = (UIView*)[cell.contentView viewWithTag:2];
switch (sender.state) {
case UIGestureRecognizerStateBegan:{
originalPoint = touchView.center;
break;
};
case UIGestureRecognizerStateChanged:{
touchView.center = CGPointMake(originalPoint.x , originalPoint.y + yFromCenter);
break;
};
//%%% let go of the card
case UIGestureRecognizerStateEnded: {
CGFloat velocityY = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:collectionView_].y);
if (velocityY < -30 && yFromCenter<0) {
[self hideView:touchView withDuration:0.2 andIndexPath:indexPath];
}else if ((yFromCenter< 0 && yFromCenter > -200) || yFromCenter > 0){
CGFloat animationDuration = (ABS(velocityY)*.0002)+.2;
[self resettleViewToOriginalPosition:touchView andDuration:animationDuration];
}else
[self hideView:touchView withDuration:0.2 andIndexPath:indexPath];
};
break;
case UIGestureRecognizerStatePossible:break;
case UIGestureRecognizerStateCancelled:break;
case UIGestureRecognizerStateFailed:break;
}
}
-(void)resettleViewToOriginalPosition:(UIView*)view andDuration:(float)duration{
[UIView animateWithDuration:duration
delay:0.0f
options: UIViewAnimationOptionCurveEaseOut
animations:^
{
[view setCenter:originalPoint];
}
completion:^(BOOL finished)
{
}];
}
- (void)hideView:(UIView*)view withDuration:(float)duration andIndexPath:(NSIndexPath*)indexPath
{
[UIView animateWithDuration:duration
delay:0.0f
options: UIViewAnimationOptionCurveEaseOut
animations:^
{
CGRect frame = view.frame;
frame.origin.y = -300;
view.frame = frame;
}
completion:^(BOOL finished)
{
[view setHidden:YES];
CGRect frame = view.frame;
frame.origin.y = 39;
view.frame = frame;
NSLog(#"View is hidden.");
[arrCards removeObjectAtIndex:indexPath.row];
[collectionView_ performBatchUpdates:^{
[collectionView_ deleteItemsAtIndexPaths:#[indexPath]];
} completion:^(BOOL finished) {
// you might want to remove the data from the data source here so the view doesn't come back to life when the collection view is reloaded.
}];
}];
}
and keep pagingEnabled of CollectionView to NO and then it should be good to go.
My UIButton is set to disappear every time my UITextField is done editing, I invoke the textFieldDidEndEditing: method, and just have the button fade away. This works fine, unless I switch to another textfield without clicking out of the first one. So for instance, I'm on textfield A, and just tap textfield B, the keyboard still stays up, and so does the button. I don't believe that there is a method that covers textfields switching like this, only when ALL the textfields are done editing. Am I wrong? Here is my code:
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField
{
negButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
negButton.frame = CGRectMake(textField.frame.origin.x, textField.frame.origin.y, 37, textField.frame.size.height);
[negButton setAlpha:0];
return YES;
}
-(void) textFieldDidBeginEditing:(UITextField *)textField
{
if ([textField isEditing])
{
[UIView animateWithDuration:0.3 animations:^
{
field = textField;
CGRect frame = textField.frame;
frame.size.width -= 40;
frame.origin.x += 40;
[negButton setAlpha:1];
[textField setFrame:frame];
[self.view addSubview:negButton];
}];
}
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
[UIView animateWithDuration:0.3 animations:^
{
CGRect frame = textField.frame;
frame.size.width += 40;
frame.origin.x -= 40;
[negButton setAlpha:0];
[textField setFrame:frame];
}
];
}
It sounds to me like you are invoking the button to appear on the
textFieldShouldBeginEditing
method, which is fine, and you are removing it on the
textFieldDidEndEditing
method, also fine. Why you are not seeing the button disappear when you switch to another text box is because when you tap that text box, the shouldBeginEditing method is called immediately after the endEditing method, resulting in the button reappearing immediately after it is deleted.
This is the way it is supposed to work, and if you want it to work a different way, you will have to make the code specific to each text field
EX:
- (BOOL)textFieldShouldBeginEditing:(UITextField*)textField
{
if(textField == myField1)
{
//make button appear
}
else if(textField == myField2)
{
//Something else
}
}
Voila!
The problem here is the order that your delegate methods are being called.
Let's say that you are going from textField1 to textField2.
Once textField1 is already active and you click on textField2, they get called like this:
textFieldShouldBeginEditing (textField2)
textFieldShouldEndEditing (textField1)
textFieldDidEndEditing (textField1)
textFieldDidBeginEditing (textField2)
You are creating your new negButton in textFieldShouldBeginEditing which over-writes the reference to the "old" button (beside textField1) by creating one beside textField2 and storing it's reference instead. Next, you call textFieldDidEndEditing and textFieldDidBeginEditing on the new button.
What you want to do is move your code that is currently in textFieldShouldBeginEditing to the beginning of textFieldDidBeginEditing so that the previous two methods act upon the appropriate button before the new one is created.
I'm new to the iphone dev. The app I'm making uses the picker to input value from the user. I have managed to make the picker hidden until the user hits the button. I used the mypicker.alpha = 0; in viewdidload so the the picker is invisible when the program starts. When the user hits the start button it executes the code mypicker.alpha=1;. I want the picker to close after the user chooses a value. How do I do that? anyone have any hints or tutorials ? I looked at few but they were confusing! Also how do I make the picker appear from the bottom up ? (like the keyboard !)
One method I recently started using is to put a shade button behind the picker, a large transparent black button the size of the screen, color black with alpha=0.3 ([UIColor colorWithWhite:0 alpha:0.3f] I think it was). This just puts a transparent "shade" over the rest of the screen except for the picker, similar to how it looks when you use UIAlertView. Then hook up the button so that it sends resignFirstResponder to the picker. Now when the user is done picking, they just tap anywhere outside the picker in the shaded area, and the button resigns the picker, and the picker can be slid down and the button faded out with an animation.
The picker slide up/down animation can be done and I have the code for it at home but don't have access to it right now. You can make it appear just like the keyboard and send the same notifications that the keyboard sends.
Don't use:
mypicker.alpha = 1;
mypicker.alpha = 0;
You should use:
mypicker.hidden = YES;
mypicker.hidden = NO;
in order to show or hide the picker.
In order to make it appear from the bottom, you can use block animations. I would use:
The .h file:
#interface viewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {
BOOL shouldMoveDown;
IBOutlet UIPickerView * picker;
}
- (IBAction)movePicker;
The .m file:
#pragma mark - View lifecycle
- (void)viewDidLoad; {
[super viewDidLoad];
picker.hidden = YES;
shouldMoveDown = NO;
picker.userInteractionEnabled = NO;
}
- (IBAction)movePicker; {
if(shouldMoveDown){
[UIView animateWithDuration:1.0
animations:^{
CGRect newRect = picker.frame;
newRect.origin.y += 236; // 480 - 244 (Height of Picker) = 236
picker.frame = newRect;
}
completion:^(BOOL finished){
[UIView animateWithDuration:1.0
animations:^{
picker.hidden = YES;
shouldMoveDown = NO;
picker.userInteractionEnabled = NO;
}
completion:^(BOOL finished){
;
}];
}];
}
else{
picker.hidden = NO;
//picker.frame = CGRectMake(picker.frame.origin.x, 480, picker.frame.size.width, picker.frame.size.height);
[UIView animateWithDuration:1.0
animations:^{
CGRect newRect = picker.frame;
newRect.origin.y -= 236; // 480 - 244 (Height of Picker) = 236
picker.frame = newRect;
}
completion:^(BOOL finished){
[UIView animateWithDuration:1.0
animations:^{
shouldMoveDown = YES;
picker.userInteractionEnabled = YES;
}
completion:^(BOOL finished){
;
}];
}];
}
}
#pragma mark -
#pragma mark Picker Delegate Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView; {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component; {
return 1;
}
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component; {
return #"1";
}
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component; {
}
Obviously you can set the picker up any way you would like to. You can also alter the speed at which this happens too! Hope this helps!