scrolling a UIScrollView on the click of a button - uiscrollview

I would like to know if it is possible for me to scroll a UIScrollView on the click of a UIButton, and if so, would someone be able to tell me how to.
I am currently using the below code to see if in the scrollview more content is there to its left and if it is there, display an image which would tell the users that there is more content if they scroll to the left.
I would like to implement a functionality where I add a UIButton instead of the image and when more content is available on the left and when the user clicks the button, the scrollview would scroll to its left.
Code:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView1
{
if (scrollView1.contentOffset.x == scrollView1.contentSize.width - scrollView1.frame.size.width)
{
// reached the right
self.imageView.hidden = YES;
}
else
{
self.imageView.hidden = NO;
}
}
It would be great if someone could help me out on this.

You can easily make the scrollview scroll by using the scrollRectToVisible:animated: of UIScrollView. You just have to enter the rectangle where you want it to scroll and use YES for animated. For instance:
[yourScrollView scrollRectToVisible:CGRectMake(10,10,100,100) animated:YES];

You could also try setContentOffset, just like this:
[yourScrollView setContentOffset: CGPointMake(0, 0) animated: YES]
Simply call this method in the IBAction of your button. Replace the yourScrollView with the UIScrollView instance you created yourself. This will automatically scroll your scrollView to the left.
Hope this may help.

Related

Can UIPopoverPresentationController be forced to reposition popover instead of resizing it?

I am using auto layout with Storyboard. I present a popoverPresentationController from a cell rect:
NumberController * viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"NumberController"];
UIPopoverPresentationController *pc = [viewController popoverPresentationController];
pc.delegate = self;
pc.permittedArrowDirections = UIPopoverArrowDirectionAny;
pc.sourceView = tableView;
pc.sourceRect = [tableView rectForRowAtIndexPath:indexPath];
[self.navigationController presentViewController:viewController animated:animated completion:nil];
The popover presents on an iPad in portrait mode with the arrow up.
I rotate the iPad to landscape mode. The popoverPresentationController keeps the same sourceView/sourceRect and properly points to the cell. It also keeps the up arrow.
But it is now at the bottom of the view, so the popover resizes to a shorter height. This is not desired behavior.
If the popover were simply to move to a new position and change the arrow direction, it would not need to resize at all. This is the desired behavior.
I thought the following method might permit me to make changes, but it is not called since the sourceView rect does not change:
- (void)popoverController:(UIPopoverController *)popoverController
willRepositionPopoverToRect:(inout CGRect *)rect
inView:(inout UIView **)view {
}
I have tried to reset the permittedArrowDirections (in preferredContentSize, because this seemed like the most logical place). This does not work (the popover still resizes):
- (CGSize) preferredContentSize {
[super preferredContentSize];
self.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionUnknown;
return CGSizeMake(DEFAULT_POPOVER_WIDTH,DEFAULT_POPOVER_HEIGHT);
}
I simply cannot find a way to force the popoverPresentationController to change arrow direction and reposition the popover instead of resizing the popover. I am beginning to think it is not even possible - but I still hold out hope that I am just missing something.
EDIT: In the meantime, it has occurred to me that maybe a popover is not the best way to present this view if I don't want it resized in iPad. I am going to try it with UIModalPresentationFormSheet presentation. But I would still like to find an answer to this question.
I just ran into the problem where
- (void)popoverController:(UIPopoverController *)popoverController
willRepositionPopoverToRect:(inout CGRect *)rect
inView:(inout UIView **)view {
was not being called because my view controller was detached. There may be a view in your view hierarchy whose view controller has not been added as a child view controller.
I thought the following method might permit me to make changes, but it is not called since the sourceView rect does not change
The sourceView rect does not have to change, just the interface orientation. From the UIPopoverControllerDelegate documentation:
For popovers that were presented using the presentPopoverFromRect:inView:permittedArrowDirections:animated: method, the popover controller calls this method when the interface orientation changes.

Pinch Zoom into UIImageView inside a UITableViewCell

I am creating a tableview where I will have an UIImageViewinside a UITableViewCell that I would like to allow the user to zoom into. I have been able to create this effect inside a UIScrollView but have struggled to get it right for zooming into a single UITableViewCell.
At the bottom I have included the code that has worked for me for the UIScrollView. The challenge starts with what to return for the viewForZoomingInScrollView. If I try to give this method the UIImageView from the cell It throws an errors as it appears the viewForZoomingInScrollView is called before the table is loaded thus it can not find the cell I am referencing. If I pass the entire view itself self.view I can scroll but the entire tableview is zoomed (where I would like to zoom just the UIImageView inside the cell) and when I release the zoom I get an error Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer bounds contains NaN: [nan nan; 375 667] which is clearly not the correct path to take.
Any help or guidance here would be appreciated.
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.imageView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
[self centerScrollViewContents];
}
- (void)centerScrollViewContents {
CGSize boundsSize = zoomTable.bounds.size;
CGRect contentsFrame = self.imageView.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
} else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
} else {
contentsFrame.origin.y = 0.0f;
}
self.imageView.frame = contentsFrame;
}
It sounds to me as though you want something like what Facebook or Twitter have, where you tap on an image and it zooms to fit the screen.
What you need to do is to consider that as a navigational step -- i.e. conceptually similar to what happens if you select a row in a standard table view and it pushes a new view controller onto the navigation controller stack, except that you probably want to present modally using a custom transition.
In the simple case, this would mean adding a tap gesture recogniser to the cell's image view; for the full effect you would add a pinch gesture recogniser to make an interactive transition.
I'd recommend watching the following WWDC videos:
2013 Session 218 "Custom Transitions Using View Controllers"
2014 Session 214 "View Controller Advancements in iOS 8"
2014 Session 228 "A Look Inside Presentation Controllers"
From your question What I understand is that you wanted to implement the functionality of Zoom in and Zoom out for ImageView. You first implemented that in a sample where you had a ScrollView Inside a ViewController and then ImageView inside that ScrollView. Things worked for you as expected. But then when you wanted the same functionality inside the TableViewCell, things didn't work for you.
So, I am suggesting you to use a View inside ScrollView as a ZoomView, and that ZoomView should have the ImageView as subview. And return that ZoomView in the method:
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView { return self.ZoomView; }

How to change UIImageview image by clicking on that image instead of button click in Iphone?

How to change image by click on that image in Iphone.Instead of button click I want to click on image.Which method can I use UIImageView.
Use a button and make your picture the picture for the button. You can do all this in Storyboard and then right click the button and drag to the view you want to go to. It should work just like that.
After you drag the button to the storyboard go to the property inspector. Make the button a custom button in the drop down list and then use the image field to select your image. You will need to size the button correctly and set the fill property to "size to fit." the other button behaviors are all customizable if you don't want normal button behavior, i.e. visually reacting to a touch.
This can be done by using touchevents also
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if ([[touches anyObject] view] == self.m_ImageViewObjectName) {
//Here you can change the image of UIImageView
}
}
You have to set tapRecognizer for your ImageView. It'll detect tap on your ImageView and call the method -clickEventOnImage.
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(clickEventOnImage:)];
[tapRecognizer setNumberOfTouchesRequired:1];
[tapRecognizer setDelegate:self];
//Don't forget to set the userInteractionEnabled to YES, by default It's NO.
myImageView.userInteractionEnabled = YES;
[myImageView addGestureRecognizer:tapRecognizer];
Add your clickEventOnImage: will look like this :
-(void) clickEventOnImage:(id) sender
{
[myImageView setImage:[UIImage imageNamed: #"myNewImageName.png"]];
}

UIButton added to view is not responding to touches

I have a UIButton that is added to a UIImageView (it's a big chart)
The button appears nicely and I have the TouchUpInside attached to a delegate:
this.TouchUpInside += delegate { ShowPopOver (); }
This event is never fired though. The button has UserInteractionEnabled=true
I add the button to the top of the view:
UIButton b = new DataPointButton (frame);
_parentView.AddSubview (b);
_parentView.BringSubviewToFront(b);
Is there anything I need to do to enable touches on code created buttons?
In UIView the UserIntaractionEnabled property is set to YES by default when there is a button on it. Howewer, in case of UIImageView it is NO by default.
Set it to YES to make buttons work:
myUIImageView.userInteractionEnabled = YES;

How to put a disclosure triangle's title to the right of the triangle?

In the HIG's example of how to use disclosure triangles, it shows a label directly to the right of the triangle.
However, when I throw one of these onto my view in Interface Builder, the text is centered on top of the triangle. I've searched the NSButton API docs, and poked at everything I can find in IB, but nothing I try will put the text to the right of the triangle. What am I missing?
What I generally do is use 2 buttons: one disclosure button and another button for the label:
While you can use a text field for the label, I prefer using a button and setting the button to call performClick: on the disclosure triangle. This makes for a much larger target area to be able to click on than a tiny triangle. (Users with trackpads will thank you).
To set up the button, change it so it looks like this:
Then set its action:
I'm not sure if there's an actual way to get the button to show both properly (without subclassing I mean), since I've generally just used separate items to give the effect. (I just checked and there is indeed a Carbon disclosure control that has both the triangle and the label built-in).
The Carbon control has the right idea where clicking on the label will automatically trigger the control. In some places (notably the re-written Cocoa Finder), you can see that you don't get that behavior for free (unless you use a button like I've shown). I still have an open bug on that one (rdar://6828042): BugID 6828042: 10.6 (10A335) Finder: Inspector's disclsr. triangle's text label not toggleable". ;-)
Have you tried just using a triangle and using a separate label?
The disclosure triangle widget is drawn by the button's bezel, centered in the available space. To create a disclosure triangle button which also has a title, you just need to subclass NSButtonCell and make sure the bezel is restricted to the left side of the button and that the title avoids the bezel. Then add your button in IB, expand it and set your title, and set the class of the cell. Unfortunately, IB won't know how to display your subclass and will put the triangle in the middle of the button. Just make sure it's big enough.
In Objective-C:
#interface TitledDisclosureTriangleButtonCell : NSButtonCell
#end
#define TRIANGLE_PADDING 15.f
#implementation TitledDisclosureTriangleButtonCell
- (NSRect)titleRectForBounds:(NSRect)theRect
{
NSRect titleRect = [super titleRectForBounds:theRect];
titleRect.origin.x = TRIANGLE_PADDING;
titleRect.size.width = NSWidth(titleRect) - TRIANGLE_PADDING;
return titleRect;
}
- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView
{
NSRect bezelFrame = frame;
bezelFrame.size.width = TRIANGLE_PADDING;
[super drawBezelWithFrame:bezelFrame inView:controlView];
}
#end
And in Swift:
let TRIANGLE_PADDING: CGFloat = 15
class TitledDisclosureTriangleButtonCell: NSButtonCell
{
override func titleRectForBounds(theRect: NSRect) -> NSRect {
var titleRect = super.titleRectForBounds(theRect)
titleRect.origin.x = TRIANGLE_PADDING
titleRect.size.width = titleRect.size.width - TRIANGLE_PADDING
return titleRect
}
override func drawBezelWithFrame(frame: NSRect, inView controlView: NSView) {
var bezelFrame = frame
bezelFrame.size.width = TRIANGLE_PADDING
super.drawBezelWithFrame(bezelFrame, inView: controlView)
}
}

Resources