I am trying to navigate from a UIScrollView's content view to another view by using a UIButton. I do not want to display this other view modally, and pushing the view on the stack is not working for me.
Example:
My Viewcontroller contains a Scrollview that has 2 content views. Within these content views I would like to push another view onto the stack.
Is what I am trying to do possible?
Ok let's see if I understood well enough your problem.
#interface MyViewController ()
#property (nonatomic, strong) UIScrollView *scrollView;
#property (nonatomic, strong) UIView *firstPlayerView;
#property (nonatomic, strong) UIView *secondPlayerView;
#end
#implementation MyViewController
-(UIView *)firstPlayerView
{
if (!_firstPlayerView) {
_firstPlayerView = [[UIView alloc] initWithFrame:self.view.bounds];
// set up your view as you like and place the button to go to the second player
// view when you need to.
// let's suppose that you called that button "goToSecondPlayerViewButton"
[goToSecondPlayerViewButton addTarget:self
action:#selector(switchPlayer)
forControlEvents:UIControlEventTouchUpInside];
}
return _firstPlayerView;
}
-(UIView *)secondPlayerView
{
if (!_secondPlayerView) {
_secondPlayerView = [[UIView alloc] initWithFrame:CGRectOffset(self.view.bounds, self.view.bounds.size.width, 0)];
// set up your view as you like and place the button to go to the first player
// view when you need to.
// let's suppose that you called that button "goToFirstPlayerViewButton"
[goToFirstPlayerViewButton addTarget:self
action:#selector(switchPlayer)
forControlEvents:UIControlEventTouchUpInside];
}
return _secondPlayerView;
}
-(UIScrollView *)scrollView
{
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
_scrollView.autoresizingMask = UIViewAutoresizingNone;
[_scrollView addSubview:self.firstPlayerView];
[_scrollView addSubview:self.secondPlayerView];
_scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height);
_scrollView.pagingEnabled = YES;
_scrollView.scrollEnabled = NO;
_scrollView.bounces = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
}
return _scrollView;
}
-(void)switchPlayer
{
if(self.scrollView.contentOffset.x == 0) {
[self.scrollView scrollRectToVisible:CGRectMake(self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height) animated:YES];
self.title = #"Second Player";
} else {
[self.scrollView scrollRectToVisible:self.scrollView.bounds animated:YES];
self.title = #"First Player";
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view addSubview:self.scrollView];
self.title = #"First Player";
}
#end
I hope that solves your problem! I haven't tested the code so if you encounter problems just comment and I'll try to help.
Edited : To add a view you just enlarge the scroll view contentSize and add that view as its subview
-(UIView *)thirdView
{
if (!_thirdView) {
_thirdView = [[UIView alloc] initWithFrame:CGRectOffset(self.view.bounds * 2, self.view.bounds.size.width, 0)];
// set up your view as you like
}
return _thirdView;
}
-(void)addThirdView
{
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width * 3, self.scrollView.bounds.size.height);
[self.scrollView addSubview:self.thirdView];
[self.scrollView scrollRectToVisible:CGRectMake(self.scrollView.bounds.size.width * 2, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height) animated:YES];
}
You can generalize this and set your content size first then have a single method that takes an index as an argument.
-(void)scrollToViewAtIndex:(NSInteger)index
{
[self.scrollView scrollRectToVisible:CGRectMake(self.scrollView.bounds.size.width * index, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height)
animated:YES];
}
Related
I have made a simple subclass of UIView which has a few subviews but its breaking for a reason I can't see.
In my storyboard view controller I have added a UIView and made it the shape I want it, and added my custom class to it. The contents of my subclass is below:
#implementation PersonDetailCell
#synthesize button, requiredMarker, textField;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)layoutSubviews
{
[self setBackgroundColor:[UIColor colorWithRed:87.0f/255.0f green:153.0f/255.0f blue:191.0f/255.0f alpha:1.0f]];
textField = [[DetailTextField alloc] initWithFrame:CGRectMake(10, 0, self.frame.size.width -20, self.frame.size.height)];
[textField setFont:[UIFont fontWithName:#"Helvetica" size:14.0f]];
[textField setTextColor:[UIColor whiteColor]];
[textField setHidden:YES];
[self addSubview:textField];
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button setHidden:YES];
[self addSubview:button];
requiredMarker = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 4, 22)];
[requiredMarker setBackgroundColor:[UIColor redColor]];
[requiredMarker setHidden:YES];
[self addSubview:requiredMarker];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
Then in my view controller code I have imported my subclass and hooked up an IBOutlet of it to my view in my storyboard. In my viewDidLoad of my view controller I also try setting background colour of this view but nothing happens.
All of my code runs without crashing, but my issues:
I can't set the background colour from my view controller, (or any other properties for that matter).
When I run the app, the height is more than that I set in my storyboard (width is fine), but I change the height of the view nowhere.
Any ideas? Am i using the wrong approach somehow?
Thanks.
If it is a table cell, then the class should be extending UITableViewCell. Buttons and textfields can be added on the storyboard - then you can use struts and springs (Size Inspector pane) to ensure the view resizes properly. I don't think layoutSubviews should be used for adding new UI elements (maybe for resizing if you need to do it manually).
Here is some working code:
#interface ChildView()
#property (strong, nonatomic) UITextField *textField;
#property (strong, nonatomic) UIButton *button;
#property (strong, nonatomic) UIImageView *requiredMarker;
#end
#implementation ChildView
#synthesize textField= _textField;
#synthesize button = _button;
#synthesize requiredMarker = _requiredMarker;
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self setBackgroundColor:[UIColor colorWithRed:87.0f/255.0f green:153.0f/255.0f blue:191.0f/255.0f alpha:1.0f]];
self.textField = [[UITextField alloc] init];
[self.textField setFont:[UIFont fontWithName:#"Helvetica" size:14.0f]];
[self.textField setTextColor:[UIColor whiteColor]];
self.textField.text = #"Test text";
[self addSubview:self.textField];
self.button = [[UIButton alloc] init];
self.button.backgroundColor = [UIColor greenColor];
[self addSubview:self.button];
self.requiredMarker = [[UIImageView alloc] init];
[self.requiredMarker setBackgroundColor:[UIColor redColor]];
[self addSubview:self.requiredMarker];
}
return self;
}
-(void)layoutSubviews
{
CGSize hostSize = self.frame.size;
float length = 22;
self.textField.frame = CGRectMake(10, length, hostSize.width, hostSize.height-length);
self.button.frame = CGRectMake(0, 0, hostSize.width, length);
self.requiredMarker.frame = CGRectMake(0, 0, 4, length);
}
#end
I have a UIScrollView in which I am adding a subview which is a TimeLineView(a UIView).For the purpose of displaying; initially I just did the same and the TimeLineView got displayed without any problem. But now I want to have a UIView just above the UIScrollView where I can display some information about the the timeline.
Do I need to decrease the height of the UIScrollView so that the UIView gets fit on the space above it? If yes, How would I do that?
If there's another way...then please let me know.
All my initial implementations are as follows :
in .h
#property (nonatomic, readonly) UIScrollView *scrollView;
#property (nonatomic, readonly) TimeLineView *timelineView;
in .m
#synthesize scrollView = scrollView;
#synthesize timelineView = timelineView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self prepareCustomView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder
{
self = [super initWithCoder:decoder];
if (self) {
[self prepareCustomView];
}
return self;
}
- (void)prepareCustomView {
// Initialization code
// Add main scroll view
[self addSubview:self.scrollView];
// Add timeline view inside scrollview
[self.scrollView addSubview:self.timelineView];
}
- (UIScrollView *)scrollView
{
if (!scrollView) {
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0f, TOP_BAR_HEIGHT, self.bounds.size.width, self.bounds.size.height-TOP_BAR_HEIGHT-FOOTER_HEIGHT)];
scrollView.contentSize = CGSizeMake(self.bounds.size.width,TIMELINE_HEIGHT);
scrollView.scrollEnabled = TRUE;
scrollView.backgroundColor =[UIColor whiteColor];
scrollView.alwaysBounceVertical = TRUE;
}
return scrollView;
}
Thanks in advance for the help.
Yes you have to change y-axis and decrease the height of scrollview by the height of your UIView.You have to change the frame of your scrollview as follows if the scrollview is just below UIView:
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0f, UIViewFrame.size.height+UIViewFrame.origin.y, self.bounds.size.width, self.bounds.size.height-TOP_BAR_HEIGHT-FOOTER_HEIGHT-UIViewFrame.size.height)];
where UIViewFrame is the frame of your UIView.
I have a UITableViewController. When a certain BOOL is set, I want to show another view instead of the UITableView. How can I do this? I need to be able to bring the UITableView back also.
I implemented the following method in my Table view controller subclass to reload its background.
- (void)reloadBackground
{
if(myBool)
{
//load the view to be displayed from a nib
NSArray* nibs = [[NSBundle mainBundle] loadNibNamed:#"EmptyView" owner:self options:nil];
UIView* emptyView = [nibs objectAtIndex:0];
self.tableView.backgroundView = emptyView;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
else
{
self.tableView.backgroundView = nil;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
}
}
HTH,
Akshay
Instead of a UITableViewController, you can put two views inside a UIViewController:
#interface MyViewController : UIViewController <UITableViewDelegate> {
UITableView *tableView;
UIWebView *anotherView;
}
...
if (someBool) {
tableView.hidden = YES;
anotherView.hidden = NO;
} else {
tableView.hidden = NO;
anotherView.hidden = YES;
}
How about..
if(myBOOL == YES) {
ADifferentViewController * vc = (ADifferentViewController *)[[ADifferentViewController alloc]init];
[self.navigationController pushViewController:vc animated:NO];
[vc release];
}
Possibly something like:
if (myBool == YES) {
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[self.view addSubview:myView];
}
Now to get rid of it:
[myView removeFromSuperview];
Of course there are plenty of other methods...
Even: self.view = myView;
Use a UIView instead if UITableViewController.... from .h file change
UITableViewController to UIViewController Connect view to Files owner
from xib
take UITableView in a UIView... take another UIView for a blank view
and set its background color as Tableview color
If your bool if true
then show tableview
and hide blank View else
hide tableview
show blank view
Here is the idea:
The scroll view has several sub views, in this example, A, B, C:
[A][B][C]
Once the user scrolls to C, the view can't scroll anymore, but I want to loop back to A, like this:
[C][A][B]
When the user keeps scrolling to the right, the view keeps filling previous views in at the end. When the user
scrolls to left the view should also have similar behavior,
in order to make the user think that this view is infinitely long:
[A][B][C][A][B][C][A][B][C][A][B][C][A][B][C][A][B][C].....
How can I implement this in actual code? Thank you.
you need to set a delegate method that gets called when the view is scrolled, and then check any view that is more than one screens worth of pixels away from being visible, if it is then reposition the view 3*screen width to the other side.
This is what you want( on iphone 7 plus). This is pure code UI, no storyboard.First you need add sub code in your AppDelegate.m.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
ViewController *vc = [ViewController alloc];
self.window.rootViewController = vc;
self.window.backgroundColor = [UIColor redColor];
return YES;
}
Second add sub code in ViewController.m
#interface ViewController ()<UIScrollViewDelegate>
#property (nonatomic, strong) UIScrollView *readCannelScrollView;
#property (nonatomic, strong) UIImageView *pageOneView;
#property (nonatomic, strong) UIImageView *pageTwoView;
#property (nonatomic, strong) UIImageView *pageThreeView;
#end
#implementation ViewController
- (void)dealloc
{
_readCannelScrollView = nil;
_pageOneView = nil;
_pageTwoView = nil;
_pageThreeView = nil;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//容器的属性设置
self.readCannelScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.readCannelScrollView];
CGSize size = self.readCannelScrollView.contentSize;
size.width = 414*3;
self.readCannelScrollView.contentSize = size;
self.readCannelScrollView.pagingEnabled = YES;
self.readCannelScrollView.showsHorizontalScrollIndicator = NO;
self.readCannelScrollView.delegate = self;
self.readCannelScrollView.contentOffset = CGPointMake(0, 0);
//end
//添加页面1
self.pageOneView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 414, self.view.bounds.size.height)];
self.pageOneView.backgroundColor = [UIColor lightGrayColor];
self.pageOneView.image = [UIImage imageNamed:#"1"];
// self.pageOneView.font = [UIFont systemFontOfSize:80];
// self.pageOneView.textAlignment = NSTextAlignmentCenter;
[self.readCannelScrollView addSubview:self.pageOneView];
//添加页面2
self.pageTwoView = [[UIImageView alloc] initWithFrame:CGRectMake(828, 0, 414, self.view.bounds.size.height)];
self.pageTwoView.backgroundColor = [UIColor greenColor];
self.pageTwoView.image = [UIImage imageNamed:#"2"];
// self.pageTwoView.font = [UIFont systemFontOfSize:80];
// self.pageTwoView.textAlignment = NSTextAlignmentCenter;
[self.readCannelScrollView addSubview:self.pageTwoView];
//添加页面3
self.pageThreeView = [[UIImageView alloc] initWithFrame:CGRectMake(828, 0, 414, self.view.bounds.size.height)];
self.pageThreeView.backgroundColor = [UIColor grayColor];
self.pageThreeView.image = [UIImage imageNamed:#"3"];
// self.pageThreeView.font = [UIFont systemFontOfSize:80];
// self.pageThreeView.textAlignment = NSTextAlignmentCenter;
[self.readCannelScrollView addSubview:self.pageThreeView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark -
#pragma mark - scroll delegate
- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(#"scrollView.contentOffset.x=%f",scrollView.contentOffset.x);
CGFloat pageWidth = scrollView.frame.size.width;
int currentPage = floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth)+1;
if (currentPage == 0)
{
UIImageView *tmpTxtView = self.pageThreeView;
self.pageThreeView = self.pageTwoView;
self.pageTwoView = self.pageOneView;
self.pageOneView = tmpTxtView;
}
if (currentPage == 2)
{
//换指针
UIImageView *tmpTxtView = self.pageOneView;
self.pageOneView = self.pageTwoView;
self.pageTwoView = self.pageThreeView;
self.pageThreeView = tmpTxtView;
}
//恢复原位
self.pageOneView.frame = (CGRect){0,0,self.pageOneView.frame.size};
self.pageTwoView.frame = (CGRect){414,0,self.pageTwoView.frame.size};
self.pageThreeView.frame = (CGRect){828,0,self.pageThreeView.frame.size};
self.readCannelScrollView.contentOffset = CGPointMake(414, 0);
}
#end
If you are satisfied with my answer give me a star.I need reputation.
I am bit stack with creating two UIViews which are switchable (each UIView has some of subviews). Since I do not IB, I wanna do that programmatically.
I have tried adding my subviews to my first UIView, then the same with second one and then switching to view like this.
if ([self.setView superview]) {
[self.setView removeFromSuperview];
[self.view addSubview:contentView];
self.navigationItem.title = #"BaseLine";
} else {
[self.contentView removeFromSuperview];
self.view = setView;
self.navigationItem.title = #"Settings";
}
but only thing which works correctly was "title" and nothing appeared on the UIViews. The UIView seems to be OK because when I use
self.view = contentView;
or
self.view = setView;
both showing subviews correctly.
Pls someone kick me to the right direction about this.
tnx
EDIT:
Also pointing the solution, perhaps something wrong with my initialization in the loadView
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
contentView = [[UIView alloc] initWithFrame:screenRect];
setView = [[UIView alloc] initWithFrame:screenRect];
self.view = contentView;
I tried to add it first [self. view add..] but the app crashed, so I used this
EDIT2
the root controller is UITableViewController..it is in navigation view and after choosing a cell this UIVieController (percView) with two UIVies is allocated
ShakeControl *percView = [[ShakeControl alloc] init];
[self.navigationController pushViewController:percView animated:YES];
[percView release];
EDIT3
switch is done by button, but it is fine done because I used that many times and it worked
Here is an example of a view controller that does what you want (I think). It is very basic, just switching between two views with different color backgrounds. But, you could further customize those subviews in the loadView method to display whatever you need.
The interface file:
#interface SwapViewController : UIViewController {
UIView *firstView;
UIView *secondView;
BOOL displayingFirstView;
UIButton *swapButton;
}
#property (nonatomic, retain) UIView *firstView;
#property (nonatomic, retain) UIView *secondView;
#property (nonatomic, retain) UIButton *swapButton;
- (void)swap;
#end
The implementation file:
#import "SwapViewController.h"
#implementation SwapViewController
#synthesize firstView;
#synthesize secondView;
#synthesize swapButton;
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] applicationFrame];
UIView *containerView = [[UIView alloc] initWithFrame:frame];
containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.view = containerView;
[containerView release];
frame = self.view.bounds;
firstView = [[UIView alloc] initWithFrame:frame];
firstView.backgroundColor = [UIColor redColor];
secondView = [[UIView alloc] initWithFrame:frame];
secondView.backgroundColor = [UIColor blueColor];
self.swapButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.swapButton.frame = CGRectMake(10, 10, 100, 50);
[swapButton addTarget:self action:#selector(swap) forControlEvents:UIControlEventTouchUpInside];
displayingFirstView = YES;
[self.view addSubview:firstView];
[self.view addSubview:swapButton];
}
- (void)swap
{
if(displayingFirstView) {
[self.firstView removeFromSuperview];
[self.view addSubview:secondView];
displayingFirstView = NO;
} else {
[self.secondView removeFromSuperview];
[self.view addSubview:firstView];
displayingFirstView = YES;
}
[self.view bringSubviewToFront:self.swapButton];
}
#end
sample code;
BOOL firstview = YES; // First, I have added view1 as a subview;
if (firstview) {
[view1 removeFromSuperview];
[self.view addSubview:view2];
} else {
[view2 removeFromSuperview];
self.view addSubview:view1];
}