Cannot select/edit text in UITextView within UIScrollView - ios

I have setup my UIScrollView with subviews like so using Masonry:
- (void)setupViews {
self.view.backgroundColor = [UIColor Background];
self.scrollView = [UIScrollView new];
self.scrollView.alwaysBounceVertical = YES;
[self.view addSubview:self.scrollView];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
self.contentView = [UIView new];
[self.scrollView addSubview:self.contentView];
self.scrollView.backgroundColor = [UIColor clearColor];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.scrollView);
make.left.and.right.equalTo(self.view);
}];
self.imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.imageButton sd_setImageWithURL:[NSURL URLWithString:self.card.cardImageURL] forState:UIControlStateNormal];
[self.imageButton.imageView setContentMode:UIViewContentModeScaleAspectFill];
[self.contentView addSubview:self.imageButton];
[self.imageButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.and.right.equalTo(self.contentView);
make.height.equalTo(self.imageButton.mas_width).multipliedBy(3/4.0);
}];
self.textField = [UITextField new];
self.textField.backgroundColor = [UIColor whiteColor];
self.textField.font = kFontRegular(14);
self.textField.text = self.card.cardTitle;
[self.contentView addSubview:self.textField];
[self.textField mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).with.offset(8);
make.top.equalTo(self.imageButton.mas_bottom).with.offset(8);
make.right.equalTo(self.contentView).with.offset(-8);
make.height.equalTo(#(45));
}];
}
but it will not let me interact with the UITextField. what element here is preventing user interaction?

Your contentView's height will be zero. So it will never get some touch events. You should not use this constraint:
make.edges.equalTo(self.scrollView);
It will not get a correct value. Try to set top and height constraints for your contentView.
make.top.equalTo(#0);
make.height.equalTo(#700);

Related

Masonry.unrecognized selector sent to instance

UIView *v2 = ({
UIView *view = [UIView new];
[self.view addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(50, 50));
make.left.equalTo(v1.mas_right);
make.top.equalTo(v1.mas_bottom);
}];
view.backgroundColor = [UIColor blueColor];
view.layoutMargins = UIEdgeInsetsMake(-20, -20, -20, -20);
view;
});
UIView *v3 = ({
UIView *view = [UIView new];
[self.view addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(50, 50));
make.centerY.equalTo(v2);
make.left.equalTo(v2.mas_rightMargin);
// make.left.equalTo(v2.mas_right);
}];
view.backgroundColor = [UIColor redColor];
view;
});
As you see, I am using the Masonry to create the UI.
This code has the bug.
-[UIView mas_rightMargin]: unrecognized selector sent to instance 0x7fdfa640cf80'
If I change the make.left.equalTo(v2.mas_rightMargin); to make.left.equalTo(v2.mas_right);;, it doesn't crash.
Just set the Pods -> Masonry -> iOS Deployment Target to the target what your project is.
Here is the screenshot, wish to be helpful to you...

UIScrollView paging disabled after rotation

Following is my code for App Tour using UIScrollView with paging enabled using AutoLayout (Masonry) It works fine in Portrait but when I rotate paging gets disabled so it doesn't work in Landscape. Then it doesn't work in Portrait mode either. Can someone help what's wrong here?
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
self.scrollView = [UIScrollView new];
self.scrollView.backgroundColor = [UIColor clearColor];
self.scrollView.scrollEnabled = YES;
self.scrollView.pagingEnabled = YES;
self.scrollView.delegate = self;
self.scrollView.showsHorizontalScrollIndicator = NO;
[self.view addSubview:self.scrollView];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
UIImageView *esImageview1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"CommonResources.bundle/page1"]];
esImageview1.contentMode = UIViewContentModeScaleAspectFit;
esImageview1.backgroundColor = [UIColor clearColor];
esImageview1.userInteractionEnabled = YES;
[self.scrollView addSubview:esImageview1];
[esImageview1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.equalTo(self.scrollView);
make.width.height.equalTo(self.view);
}];
UIImageView *esImageview2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"CommonResources.bundle/page2"]];
esImageview2.contentMode = UIViewContentModeScaleAspectFit;
esImageview2.backgroundColor = [UIColor clearColor];
esImageview2.userInteractionEnabled = YES;
[self.scrollView addSubview:esImageview2];
[esImageview2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(esImageview1.mas_right);
make.top.bottom.equalTo(self.scrollView);
make.width.height.equalTo(self.view);
}];
UIImageView *esImageview3 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"CommonResources.bundle/page3"]];
esImageview3.contentMode = UIViewContentModeScaleAspectFit;
esImageview3.backgroundColor = [UIColor clearColor];
esImageview3.userInteractionEnabled = YES;
[self.scrollView addSubview:esImageview3];
[esImageview3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(esImageview2.mas_right);
make.top.bottom.equalTo(self.scrollView);
make.width.height.equalTo(self.view);
}];
self.pageControl = [UIPageControl new];
self.pageControl.numberOfPages = 3;
self.pageControl.currentPage = 0;
self.pageControl.backgroundColor = [UIColor clearColor];
[self.view addSubview:self.pageControl];
[self.pageControl mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.height.equalTo(#40);
make.top.equalTo(self.view).with.offset(40);
}];
UILabel *titleLabel = [UILabel new];
titleLabel.text = #"App Tour";
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.font = [UIFont fontWithName:#"Helvetica-Light" size:16];
titleLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:titleLabel];
[titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.height.equalTo(#40);
make.top.equalTo(self.view).with.offset(20);
}];
UIButton *doneButton = [UIButton new];
[doneButton.titleLabel setFont:[UIFont fontWithName:#"Helvetica-Light" size:16]];
[doneButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[doneButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
[doneButton setTitle:#"Done" forState:UIControlStateNormal];
[doneButton addTarget:self action:#selector(doneButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
doneButton.backgroundColor = [UIColor clearColor];
[self.view addSubview:doneButton];
[doneButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.view);
make.height.equalTo(#40);
make.width.equalTo(#70);
make.top.equalTo(self.view).with.offset(20);
}];
}
- (void)doneButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width*self.pageControl.numberOfPages, self.view.frame.size.height);
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
I'm guessing its getting covered up by another view or something similar to that. Try subclassing the UIScrollView and implementing the following method to check if its responding to your touches at all.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"OMG TOUCHES WORK, NOW WHAT?");
}
You can easily check if it was getting covered up by forcing it to be in front. Call this line of code in the callback for rotation in the UIViewController containing the UIScrollView. It should fix the problem. You may have to subclass the UIView for the controller and put this method in the didLayoutSubviews method instead, not quite sure, depends on your implementation.
[self.view bringSubViewToFront:self.scrollView];
Also check the frame and bounds before and after rotation and see if anything is out of place looking
I just wanted to reset Scrollview's contentsize in didRotateFromInterfaceOrientation delegate. Not sure why though because when I rotate, videDidLayoutSubview already gets called where I am already reseting content size.
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width*self.pageControl.numberOfPages, self.view.frame.size.height);
}

Button action is not fired for UIButton Inside UIView which is inside UIScrollview in IOS

I want to load set of objects coming from array in vertical scrollview. I have UIScrollview at xib. Programmatically I added photo image, item name, item tags, comment button and likes label to UIView and added UIView to UIScrollview.
I added likes button to UIScrollview but the button action is not firing. Below is my code.
I think some Frames of subviews are over riding that makes button action (likes_ButtonPressed) not fired.
-(void)createScrollview
{
NSArray *viewsToRemove = [scrollview subviews];
for (UIView *v in viewsToRemove) [v removeFromSuperview];
int x=7;
int y=0;
CGRect screenbounds=[[UIScreen mainScreen] bounds];
for(int i=0;i<[array count];i++)
{
ProfileObjCls *profileObjRef = [self.array objectAtIndex:i];
//NSLog(#"Button Tag is %#",profileObjRef.image_UserLoaded_objInArray);
UIView *mainView=[[UIView alloc]initWithFrame:CGRectMake(x,y,310,400)];
self.photoTagImgView=[[UIImageView alloc]initWithFrame:CGRectMake(x,y+20,294,320)];
self.likesLabel.font=[UIFont fontWithName:#"BodoniStd-BoldItalic" size:13];
self.itemNameLbl=[[UILabel alloc]initWithFrame:CGRectMake(x,y+340,100,30)];
commentsButton=[[UIButton alloc]initWithFrame:CGRectMake(x+155+32, y+340, 40, 40)];
[commentsButton setImage:[UIImage imageNamed:#"comment_icon.png"] forState:UIControlStateNormal];
UIButton *photoLikeButton=[[UIButton alloc]initWithFrame:CGRectMake(x+100, y+340, 40, 40)];
photoLikeButton.tag=i;
[photoLikeButton setImage:[UIImage imageNamed:#"like_img_new.png"] forState:UIControlStateNormal];
[photoLikeButton addTarget:self action:#selector(likes_ButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
self.likesLabel=[[UILabel alloc]initWithFrame:CGRectMake(x+223+32,y+346,310,30)];
if (profileObjRef.photoLikes==0)
{
self.likesLabel.text=#"0 likes";
}
else
{
self.likesLabel.text=[NSString stringWithFormat:#"%# likes",profileObjRef.photoLikes];
}
[self.photoTagImgView setImageWithURL:[NSURL URLWithString:profileObjRef.image_UserLoaded_objInArray]
placeholderImage:[UIImage imageNamed:#"satisfashionplaceholder#568.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)
{
if (!error && image)
{
}
}];
self.imagetotweet=profileObjRef.image_UserLoaded_objInArray;
//int y=335;
//first label - PHOTO NAME
self.itemNameLbl.text=profileObjRef.photoname;
self.itemNameLbl.font = [UIFont fontWithName:#"BodoniStd-Poster" size:14.0];//BodoniStd-Bold
self.itemNameLbl.textColor = [UIColor blackColor];
//second Label - PHOTO DESCRIPTION
UIFont *cellFont=[UIFont fontWithName:#"BodoniStd-BoldItalic" size:13.0];
[mainView addSubview:commentsButton];
[mainView addSubview:likesLabel];
[self.scrollview addSubview:photoLikeButton];
[self.scrollview bringSubviewToFront:photoLikeButton];
[mainView addSubview:self.photoTagImgView];
[mainView addSubview:self.itemNameLbl];
[mainView addSubview:self.detailsBgImgView];
[self.scrollview addSubview:likesButton];
[self.scrollview bringSubviewToFront:likesButton];
mainView.userInteractionEnabled=YES;
self.scrollview.backgroundColor=[UIColor clearColor];
self.scrollview.userInteractionEnabled = YES;
/*
self.scrollview.exclusiveTouch = YES;
self.scrollview.canCancelContentTouches = YES;
self.scrollview.delaysContentTouches = YES;
self.view.userInteractionEnabled=YES;*/
//self.scrollview.backgroundColor=[UIColor colorWithRed:212.0f/255.0f green:213.0f/255.0f blue:214.0f/255.0f alpha:1.0f];
[self.scrollview addSubview:mainView];
[self.view addSubview:self.scrollview];
y=y+200;
//x=x+320;
}
self.scrollview.contentSize=CGSizeMake(320, 400*array.count);
//self.scrollview.contentSize=(CGSizeMake(x, 320));
self.scrollview.pagingEnabled=YES;
//[self.scrollview setContentOffset:CGPointMake(320*tagValue, 0)];
[self.scrollview setContentOffset:CGPointMake(0, 400*tagValue)];
[self.view bringSubviewToFront:spinner];
//[self.scrollview setContentOffset:CGPointMake(320*(tagValue-1), 0)];
}
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
return ![view isKindOfClass:[UIButton class]];
}
Please suggest any ideas where I went wrong..
Thanks in Advance..

Fit UIView height to its content with AutoLayout

I'm using iOS 6 AutoLayout feature with Masonry DSL to arrange views within UITableViewCell. This is the layout arrangements that I want to achieve:
The containerView is a virtual container that should dynamically adapt its size to fit its content. With my current implementation, this is what I got instead:
It seems that containerView did get vertically centered correctly, but it has zero width and height, hence not showing up properly. How can I instruct containerView to fit its size to its content? Code snippets are attached below.
Thanks!
UITableViewCell initializer
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]) {
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.font = [UIFont boldSystemFontOfSize:[UIFont smallSystemFontSize]];
self.titleLabel.text = #"ノートタイトル";
self.coverImage = [[UIView alloc] init];
self.coverImage.backgroundColor = [UIColor carrotColor];
self.avatarImage = [[UIView alloc] init];
self.avatarImage.backgroundColor = [UIColor emerlandColor];
self.authorLabel = [[UILabel alloc] init];
self.authorLabel.font = [UIFont systemFontOfSize:[UIFont smallSystemFontSize]];
self.authorLabel.text = #"著者の名前";
self.containerView = [[UIView alloc] init];
self.containerView.backgroundColor = [UIColor lightGrayColor];
[self.containerView addSubview:self.titleLabel];
[self.containerView addSubview:self.avatarImage];
[self.containerView addSubview:self.authorLabel];
[self.contentView addSubview:self.containerView];
[self.contentView addSubview:self.coverImage];
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self updateConstraintsIfNeeded];
}
return self;
}
UITableViewCell updateConstraints
- (void)updateConstraints
{
[super updateConstraints];
[self.coverImage mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).with.offset(20);
make.top.equalTo(self.contentView).with.offset(5);
make.bottom.equalTo(self.contentView).with.offset(-5);
make.width.equalTo(self.coverImage.mas_height).multipliedBy(0.75);
}];
[self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.coverImage.mas_right).with.offset(10);
make.centerY.equalTo(self.contentView);
}];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.containerView);
make.top.equalTo(self.containerView);
}];
[self.avatarImage mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.titleLabel.mas_bottom).with.offset(5);
make.left.equalTo(self.titleLabel);
make.width.equalTo(#20);
make.height.equalTo(#20);
}];
[self.authorLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.avatarImage.mas_right).with.offset(5);
make.centerY.equalTo(self.avatarImage);
}];
}
I found out the solution to my own question. Apparently, in order for containerView to resize itself dynamically, we have to make sure that each elements within are connected rigidly to each other and the edges of the superview (i.e. containerView). For example, in VFL it should be something like this: "V:|-10-[child1]-5-[child2]-5-|"
So in my case, I add a new constraint make.bottom.equalTo(self.containerView) to avatarImage and now the superview knows how to height itself!

UILabel height animation with autolayout

I have an UILabel on my view and UIButton. When button touched UILabel should change height animated, depends on label content . I was trying this:
- (void)viewDidLoad {
self.textLabel= [[UILabel alloc] initWithFrame:CGRectZero];
self.textLabel.numberOfLines=0;
self.textLabel.font= [UIFont systemFontOfSize:14];
self.textLabel.backgroundColor= [UIColor lightGrayColor];
self.textLabel.text= #"short text";
[self.view addSubview:self.textLabel];
[self.textLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-10-[_textLabel]-10-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_textLabel)]];
self.button= [UIButton buttonWithType:UIButtonTypeSystem];
[self.button addTarget:self action:#selector(buttonTouched:) forControlEvents:UIControlEventTouchUpInside];
[self.button setTitle:#"Tap" forState:UIControlStateNormal];
self.button.backgroundColor= [UIColor greenColor];
[self.button setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:self.button];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-10-[_button]-10-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_button)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-50-[_textLabel(>=0)]-10-[_button(==20)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_textLabel,_button)]];
}
- (void)buttonTouched:(id)buttonTouched {
self.shortText =!self.shortText;
self.textLabel.text= self.shortText ?#"short text":#"long long long text\nlong long long text\nlong long long text\n";
[UIView animateWithDuration:1.0
animations:^{
[self.view layoutIfNeeded];
}];
}
Right before the animation block, you need to call [self.view setNeedsUpdateConstraints] in order to trigger tell the view that the constraints need to be updated when you call layoutIfNeeded
So the new method:
- (void)buttonTouched:(id)buttonTouched {
self.shortText =!self.shortText;
self.textLabel.text= self.shortText ?#"short text":#"long long long text\nlong long long text\nlong long long text\n";
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:1.0
animations:^{
[self.view layoutIfNeeded];
}];
}
I have this example working no problem.
#interface ViewController ()
#end
#implementation ViewController
{
__weak UIView *_bgView;
__weak UILabel *_label;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView *bgView = [[UIView alloc] initWithFrame:CGRectZero];
bgView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.5];
bgView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:bgView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[bgView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(bgView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[bgView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(bgView)]];
_bgView = bgView;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.5];
label.text = #"ahoj";
label.numberOfLines = 99;
label.textAlignment = NSTextAlignmentCenter;
label.translatesAutoresizingMaskIntoConstraints = NO;
[bgView addSubview:label];
[bgView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-8-[label]-8-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(label)]];
[bgView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-8-[label]-8-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(label)]];
_label = label;
[self performSelector:#selector(animate) withObject:nil afterDelay:1];
}
- (void)animate
{
_label.text = #"ahoj, ahoj\ntotalka ahoj";
[UIView animateWithDuration:1 animations:^{
[_bgView.superview layoutIfNeeded];
} completion:^(BOOL finished) {
;
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Define the height constraint in your storyboard, add it as an IBOutlet, and then change its value inside your animation block.
Maybe if you use
[self.textLabel sizeToFit];
it works.

Resources