How to assign didSelectRowAtIndexPath in Tableview cells subview item - iphone

I have 2 problem and i am totally confuse. please help me
1) I face one problem that i want to assign click listener to image view which is inside of my subview and that subview is with in cell of UITableView.
In my tableview cell there are two image-view i want to give them click listener and also identify them like which image-view is clicked on which row etc etc.
if i write scrollview.userinteractionEnable=YES; than my didSelectRowAtIndexPath Not responds.
i know its because of subview.
But if i change scrollview.userinteractionEnable=NO; than my didselectrowatIndexpath code executes. but scrollview does not scroll to horizontal..
What do i do ? I want horizontal scroll plus Image-view click Listener on both ImageView.
** Solve click problem by crating scrollview sub class**
This is my Customcell class
cellScrollViewClass *scrollView = [[cellScrollViewClass alloc] initWithFrame:CGRectMake(0.0,0.0,430,187)];
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 3,scrollView.frame.size.height);
scrollView.scrollEnabled=YES;
scrollView.userInteractionEnabled=YES;
for (int i = 0; i < 3; i++) {
CGRect frame;
frame.origin.x = scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = scrollView.frame.size;
if(i==2) // to check Last item must be train Engine
{
UIView *EngineView = [[UIView alloc]initWithFrame:frame];
UIImageView *engineImageView = [[UIImageView alloc]initWithFrame:CGRectMake(-112.5, 6, 430, 180)];
UIImage *Image = [UIImage imageNamed:#"backengine.png"];
engineImageView.contentMode = UIViewContentModeScaleAspectFit;
engineImageView.image = Image;
[EngineView addSubview:engineImageView];
[scrollView addSubview:EngineView]; // add 3rd imageview that is Train Engine to end of scrollview
}
else{ // Not equal to 2 than it must be wagon of train.
UIView *wagon = [[UIView alloc]initWithFrame:frame];
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"wagon.png"]];
wagon.backgroundColor = background;
UIView *videoviewContainer = [[UIView alloc]initWithFrame:CGRectMake(20, 40, 220 , 200)];
UIImageView *videoImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0,0, 220, 100)];
UIImage *bgImage = [UIImage imageNamed:#"video.png"];
videoImageView.image = bgImage;
videoviewContainer.contentMode = UIViewContentModeLeft; // set Video Image view to left hand side of wagon UIView
videoImageView.tag=2;
[videoviewContainer addSubview:videoImageView];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGestureCaptured:)];
[videoImageView addGestureRecognizer:singleTap];
[videoImageView setMultipleTouchEnabled:YES];
[videoImageView setUserInteractionEnabled:YES];
UIView *textUiView = [[UIView alloc]initWithFrame:CGRectMake(238,28, 150 , 187)];
textUiView.contentMode = UIViewContentModeRight;
UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(28,10, 150 , 87)];
label.text=#"This is testing text for IOS app to check line are aligned or not and to check video image and nested views for UIviews";
label.backgroundColor = [UIColor clearColor];
label.textColor=[UIColor redColor];
label.numberOfLines = 4;
[textUiView addSubview:label];
[wagon addSubview:textUiView];
[wagon addSubview:videoviewContainer];
[scrollView addSubview:wagon];
[self.contentView addSubview:scrollView];
}
}
}
return self;
}
- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
NSLog(#"Touch event on view %d",gesture.view.tag);
}
And I created Scrollview subclass like this..
#implementation cellScrollViewClass
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSLog(#"You are in scrollview");
}
return self;
}
IS this one is right method of Implementation?
Any Help is Appreciated . Thank you in advance.

Use UITapGestureRecognizer. Create and attach a tap gesture recogniser to each image view when you create it. Also set the tag of the image view when you create it so you can identify which one it is on the cell.
When you get the callback from the recogniser you can get the tag by:
recogniser.view.tag
And you can get the table view cell by looping on the superview until you find a table view cell class:
UIView *superView = recogniser.view.superview;
while (superView != nil && ![superView isKindOfClass:[UITableViewCell class]]) {
superView = superView.superview;
}
Then you can get the index path from the table view using
[tableView indexPathForCell:superView];

To get the on click listener for UIImageView have a category of it & use touches begin method and delegate callback to 'tableViewController'.
Use tags to identify which image is clicked & which row.
To avoid overlap, if the cell us already allocated just remove the previous images to do this have a else condition.

you need to implement the UIScrollView delegate callbacks and check what kind of scroll the user is doing (horizontal scroll or vertical scroll) and then changing the tableview or the scrollview offset manually, thats pretty much the only way i see this...
as for your image you need to set a UIButton for everyImage and link them to a selector, then you can use the tag of the button to know what image it was.

you can add a custom button over the imageview with same frame of image view and the you can add the selector on the button.

For handling gestures on UIImageView make sure that the UIImageView that you are using has the userInteractionEnable = YES by default is set to NO

Related

Want to implement UIPageController and UIScrollView in UIView programmatically in ios

I have one view Controller and one UIView now in my ViewController when i click barButton than second view will apear like popup,now i want to add page controller and scrollview in that second view, my second view is not UIViewController but it is UIView.so how can i do that...
my first view is "ImageViewController" and second view is "PopupView"
in ImageViewController.m
#import "PopupView.h"
#implementation ImageViewController
- (void)viewDidLoad
{
UIBarButtonItem *clipArt = [[UIBarButtonItem alloc] initWithTitle:#"Clip Art"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(popUpView:)];
}
- (void)popUpView:(id)sender {
CGRect * imageFrame = CGRectMake(10, 90, 300, 300);
PopupView *popUpView = [[PopupView alloc] initWithFrame:imageFrame];
[self.view addSubview:popUpView];
}
And in PopupView.m
- (id)initWithFrame:(CGRect)frame
{
if (self) {
CGRect * imageFrame = CGRectMake(0, 0, 300, 300);
self = [super initWithFrame:frame];
UIImageView *starImgView = [[UIImageView alloc] initWithFrame:imageFrame]; //create ImageView
starImgView.alpha =0.8;
starImgView.layer.cornerRadius = 15;
starImgView.layer.masksToBounds = YES;
starImgView.image = [UIImage imageNamed:#"black"];
[self addSubview:starImgView];
self.backgroundColor = [UIColor clearColor];
}
return self;
}
Implement like this in the second view, for scroll view with page control (this example illustrates the scenario for two views):
CGRect scrollViewFrame = CGRectMake(ur dimensions for scroll view);
UIScrollView *myScrollView = [[UIScrollView alloc] initWithFrame:scrollViewFrame];
myScrollView.pagingEnabled = YES;
myScrollView.contentSize = CGSizeMake(scrollViewFrame.size.width * 2, scrollViewFrame.size.height);
//content size is the actual size of the content to be displayed in the scroll view.
//Since, here we want to add two views so multiplied the width by two.
CGRect viewFrame = [myScrollView bounds];
UIView *view1 = [[UIView alloc] initWithFrame:viewFrame];
viewFrame.origin.x = viewFrame.size.width; //setting the offset so that view2 is next to view 1
UIView *view2 = [[UIView alloc] initWithFrame:viewFrame];
//add both the view to scroll view
[myScrollView addSubview:view1];
[myScrollView addSubview:view2];
//add scroll view to parent view
[self addSubview:myScrollView];
You can replace the view1/2 with any visual element. To have scrolling with page control make sure all the view that you want to add to scrollview are so same width/height. That way it work out of the box and you wont have to do anything. Also, its always a good idea to add UIPageControl to the view for giving user some kind of feedback. Its optional though.
One more thing, if you want horizontal scrolling with page control, increase the width as done above. If you want vertical scrolling, increase the height and keep the width same.

facing issue for touch down event for UIImageView again

If My Story Board contains
View
|_my UIIMageView 1
|
|_my UIImageView 2
I can handle the touch down event by following the solution at this post
However, if my Story Board is changed to
Scroll View
|_my UIIMageView 1
|
|_my UIImageView 2
Now I can not detect the touch down event on one of these UIImageView...
Please help me on this issue..
I have used :
UITapGestureRecognizer *touch;
UIImageView *anImageView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
anImageView.image = [UIImage imageNamed:#"iad.png"];
[anImageView setUserInteractionEnabled:TRUE];
anImageView.tag = 1001 ;
touch = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(test)] autorelease];
touch.numberOfTapsRequired = 1;
[anImageView addGestureRecognizer:touch];
[scrollView addSubview:anImageView];
[anImageView release];
- (void) test:(UIGestureRecognizer *)sender
{
UIImageView *imageView = (UIImageView *)sender.view;
switch (imageView.tag)
{
case 1001:
// your code
break;
case 1002:
// your code
break;
}
}
Probably not the answer you're looking for, but you should think about using UIButtons instead of UIImageViews.
Each UIButton have an UIImageView inside plus all the touch events with it.

how to pushViewController to another view with images in a scrollview

I have a scrollview of images, I will like to tab them and will pushed to another view.
once i tab on the image, the whole view should push to another view.
From this View to another view
Detail view
Sorry for not asking the question clearly.
my scrollview
-(void)pictureScrolling
{
//init scrollview in location on screen
scrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 100, 320, 290)];
scrollview.backgroundColor = [UIColor redColor];
//pass image filenames
NSMutableArray *fileNames = nearbyFrog.imageFiles; //[[[NSMutableArray alloc] init] autorelease];
//setup the array of uiimageviews
NSMutableArray *imgArray = [[NSMutableArray alloc] init];
UIImageView *imageView;
//loop through the array imgNames to add file names to imgArray
for (NSString *imageName in fileNames) {
imageView = [[UIImageView alloc] init];
imageView.image = [UIImage imageNamed:imageName];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[imgArray addObject:imageView];
[imageView release];
}
CGSize pageSize = scrollview.frame.size;
NSUInteger page = 0;
for (UIView *viewForScrollView in imgArray) {
[scrollview addSubview:viewForScrollView];
viewForScrollView.frame = CGRectMake(pageSize.width * page++ +10, 0, pageSize.width -20 , pageSize.height);
// making use of the scrollView's frame size (pageSize) so we need to;
// +10 to left offset of image pos (1/2 the gap)
// -20 for UIImageView's width (to leave 10 gap at left and right)
}
//add scroll view to view
[self.view addSubview:scrollview];
scrollview.contentSize = CGSizeMake(pageSize.width * [imgArray count], pageSize.height);
//scrollview.contentSize = CGSizeMake(320 *viewcount + 20, 290 );
scrollview.showsHorizontalScrollIndicator =NO;
[scrollview setPagingEnabled:YES];
scrollview.delegate =self;
//paging function for scrollview
CGRect frame = [[UIScreen mainScreen] applicationFrame];
self.pageControl = [[[UIPageControl alloc] initWithFrame:CGRectMake(0, 100, 100, 50)] autorelease];
self.pageControl.center = CGPointMake(frame.size.width/2, frame.size.height-60);
self.pageControl.numberOfPages = [fileNames count];
[self.view addSubview:self.pageControl];
//handle Touch Even
[pageControl addTarget:self action:#selector(changePage:) forControlEvents:UIControlEventValueChanged];
[imgArray release];
}
anybody knows how to do it or can show me a tutorial?
Thanks
I think this is the best way to implement it
Create your own Custom UIImageView class. This is required to store an additional property which will help you identify which image for clicked.
Create a delegate for that class which is called with the single tap event is raised in the UIImageView
Add the Images inside the scrollview using this custom class. The delegate of this class will tell you which image was tapped. You can use this to push a new view controller passing the image details (if necessary).
You can find some sample code in the ThumbImageView class in the scrollviewSuite sample
http://developer.apple.com/library/ios/#samplecode/ScrollViewSuite/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008904-Intro-DontLinkElementID_2

Expedia app sectionIndex: how they do that?

I noticed that Expedia app ( http://a5.mzstatic.com/us/r1000/027/Purple/4c/f4/6c/mzl.wcipbyyg.320x480-75.jpg) has a customized sectionIndex for UITableView on hotels list. (image attached)
I'm figuring that it could be a custom view, maybe with a vertical UISlider but, as I know, UISlider cannot recognize touch events on slides but just dragging ones.
So, how they do that ? A vertical sequence of buttons ? But, in this case, how to recognize dragging events ?
I would like to replicate that control but I need some hints ;)
thanks
There are more ways how to achieve the effect. Assuming you have a self.view initialized from a nib file and it's ordinary UIView, you can put this code into viewDidLoad:
- (void)viewDidLoad
{
CGRect tvFrame = self.view.frame;
tvFrame.origin = CGPointZero;
UITableView* tv = [[UITableView alloc] initWithFrame:self.view.frame];
tv.delegate = self;
tv.dataSource = self;
tv.showsVerticalScrollIndicator = NO;
[self.view addSubview:tv];
CGRect svFrame = CGRectMake(290, 10, 30, 400);
UIScrollView* sv = [[UIScrollView alloc] initWithFrame:svFrame];
sv.contentSize = CGSizeMake(10, 780);
sv.showsVerticalScrollIndicator = NO;
sv.bounces = YES;
CGRect vFrame = CGRectMake(10, 380, 10, 20);
UIView* v = [[UIView alloc] initWithFrame:vFrame];
v.backgroundColor = [UIColor blueColor];
[sv addSubview:v];
[self.view addSubview:sv];
[super viewDidLoad];
}
This will create a table with a narrow scroll view with a blue rectangle over the table. Now you can scroll both scroll views (the table is also a scroll view) independently.
Then you will have to setup delegates and receive scroll events via UIScrollViewDelegate. When one of the scroll views starts dragging, you have to start setting offset of the other scroll view.

Changing bounds of imageView of UITableViewCell

I'm trying to place various size images inside imageView of UITableViewCell. I get the image data asynch'ly, create the image, set the content mode of imageView and finally set bounds of imageView. But the code seems insensitive to any changes I made. I want the images to be centered in a 75x75 area. I wrote the below code for this purpose
UIImage* image = [UIImage imageWithData:data];
[holder.imageView setContentMode:UIViewContentModeCenter || UIViewContentModeRedraw];
[holder.imageView setImage:image];
[holder.imageView setBounds:CGRectMake(0,0,75,75)];
[holder.imageView setFrame:CGRectMake(0,0,75,75)];
[holder setNeedsLayout];
Where holder is the UITableViewCell. The result I get is always the same. All images have 75px height and different widths. Can someone help me solve this problem?
I have realized that setting contentMode and bounds properties does not have any effect in that code. I have added an NSLog after the last line and got the results as below:
NSLog(#"imageview:%# bounds and contentMode:%# %#",[holder imageView],[holder.imageView bounds],[holder.imageView contentMode]);
imageview:<UIImageView: 0x39ab8a0;
frame = (0 0; 75 75); opaque = NO;
userInteractionEnabled = NO; layer =
<CALayer: 0x39a92b0>> bounds and
contentMode:(null) (null)
Still no solution
Done, I finally found the solution, it cost me 3 hours though =)
The solution is to change properties like bound,frame,contentMode in -(void)layoutSubviews method of the custom UITableViewCell class. The "trick" is to write layout code in this method, otherwise the code does not have any effect.
Below code did the work for me. It makes rows of the table vertically aligned.
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.bounds = CGRectMake(0,0,75,75);
self.imageView.frame = CGRectMake(0,0,75,75);
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
CGRect tmpFrame = self.textLabel.frame;
tmpFrame.origin.x = 77;
self.textLabel.frame = tmpFrame;
tmpFrame = self.detailTextLabel.frame;
tmpFrame.origin.x = 77;
self.detailTextLabel.frame = tmpFrame;
}
So the problem with UITableViewCell's is that you have no control over the size of the built-in objects (namely imageView, contentView, accessoryView, backgroundView). When the table changes, your customizations get trampled over.
You can, as Behlul pointed out, force the sizes to be correct by using layoutSubviews, but the problem with that is that layoutSubviews is called every time the table scrolls. That is a lot of unnecessary re-layout calls.
An alternate, method is to add all of your content to the contentView. Similarly if you are customizing the background, you can create a transparent backgroundView and add your custom background view (eg myBackgroundView) as a subview of backgroundView.
This way you can place and size your items how you want them.
The down side is the stock messages are no longer received from the accessory or image views. You just have to create you own.
Hope that helps!
// This code is not tested
// MyCustomTableViewCell
- (id) init{
self = [super initWithStyle: UITableViewCellStyleDefault reuseIdentifier:#"MyReuseIdentifier"];
if(self){
//image view
my_image_view = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"default_image.png"]] retain];
[my_image_view setFrame:CGRectMake(10,10,30,30)];
[self.contentView addSubview:my_image_view];
//labels
my_text_label = [[[UILabel alloc] initWithFrame:CGRectMake(50,10,100,15)] retain];
[self.contentView addSubview:my_text_label];
//set font, etc
//detail label
my_detail_label = [[[UILabel alloc] initWithFrame:CGRectMake(50,25,100,15)] retain];
[self.contentView addSubview:my_detail_label];
//set font, etc
//accessory view
//Whatever you want to do here
//attach "accessoryButtonTapped" selector to button action
//background view
UIView* background_view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 50)] autorelease];
[background_view setBackgroundColor:[UIColor greenColor]];
background_view.layer.cornerRadius = 17;
background_view.layer.borderWidth = 3;
background_view.layer.borderColor = [UIColor whiteColor].CGColor;
[self setBackgroundView:[[[UIView alloc] init] autorelease]];
[self.backgroundView addSubview:background_view];
}
return self;
}
- (void) setLabelText: (NSString*) label_text{
[my_text_label setText:label_text];
}
- (void) setDetailText: (NSString*) detail_text{
[my_detail_label setText: detail_text];
}
- (void) accessoryButtonTapped{
//call table view delegate's accessoryButtonTappedForRowWithIndexPath method
}
"UIViewContentModeCenter || UIViewContentModeRedraw" is equivalent to 1. It's also not a bitfield. You want UIViewContentModeCenter.
UITableViewCell.imageView is managed by the cell. If you want custom layout, try adding a view to contentView (I'm guessing what you mean by "centered in a 75x75 area"):
UIImageView * iv = [[[UIImageView alloc] initWithImage:image] autorelease];
iv.frame = (CGRect){{0,0},{75,75}};
iv.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin| UIViewAutoresizingFlexibleRightMargin;
iv.contentMode = UIViewContentModeScaleAspectFit;
[holder.contentView addSubview:iv];
try changing the "contentMode" property of imageView to 'UIViewContentModeScaleAspectFit' or 'UIViewContentModeScaleAspectFill'
Create subclass of UITableViewCell:
#interface UITableViewCellSubClass : UITableViewCell
#end
#implementation UITableViewCellSubClass
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame = CGRectMake(0,4,32,32);
self.textLabel.frame = CGRectMake(42,4,300,32);
}
#end