UIPageController currentPage stubbornly sets itself to nib value - ios

I have a UIPageController that I placed in my xib file, so I could get the placement proper, but the value of "currentPage" set in the xib is the value that currentPage assumes when i try to set it to something else, like below, the line of code that sets my UIScrollView to the proper initial image when starting in the middle (i.e. not page 0):
aScrollView.contentOffset = CGPointMake((currentIndex + 0.0) * screenWidth, 0.0);
which calls
-(void) scrollViewDidScroll: (UIScrollView*) aScrollView
{
// Update the page control to match the current scroll:
CGPoint offset = aScrollView.contentOffset;
float width = self.view.frame.size.width;
int pageNumber = (int)(offset.x / width);
uiPageControl.currentPage = pageNumber;
NSLog(#"%g // %g = %d", offset.x, width, (int)(offset.x/width));
}
The pageNumber integer is correct, so I am properly calculating the desired page number from the offset. However, when I try to manually (programatically) set currentPage, it doesn't set to pageNumber, it sets to the value in the xib.
Easy solution is to not use the xib and do it all programatically, but I want to know how I can continue using the UIPageController in the xib, because it was easy to place without knowledge of coordinates, etc. Normally, Attributes set in the xib are overwritable programatically, so this bug really surprised me. Any suggestions on how I can properly set currentPage?
Thanks for your help!

I found a hack that temporarily solves my problem: in the xib, I set the "Number of Pages" value to something I know will be higher than the number of pages I will ever have.
If this is too small, it turns out that setting currentPage beyond that value didn't do anything because it was clamping or setting it to some number below the number of pages I had in the xib.
If I set this xib attribute higher, then setting currentPage works.
Sorry for the quick trigger.

Related

Prevent UITextView from offsetting its text container

I am tying to modify the height of a UITextView dynamically (up to a max height) while the user enters text. I am experiencing a very strange behavior when there are an even number of lines in the text view.
I am using autolayout and the text view has a height constraint. I respond to calls to the text view's delegate (textViewDidChange(_:)), where I calculate and adjust the height constraint based on the contentSize.
Here is the code:
func textViewDidChange(_ textView: UITextView) {
let newHeight = textView.contentSize.height
let newConstraintConst = max(MinTextViewHeight, min(MaxTextViewHeight, newHeight))
self.textViewHeightConstraint.constant = newConstraintConst
}
This works well, it resizes the frame up to MaxTextViewHeight and then the text view can scroll. However, when there are an even number of lines in the text view, the text view adds a kind of offset to the bottom of its NSTextContainer, causing the top line to be cut off:
However, when there are odd lines the NSTextContainer is no longer offset:
At first I thought it was somehow being controlled by the text view's textContainerInset but that is only used to pad the space inside the NSTextContainer, as setting it to .zero removes the space inside but does not affect the offset (and incidentally makes it even worse, as the top line almost completely disappears):
I have looked through the UITextView class reference and I don't see any property that would let me manipulate or even get the value of this offset.
As a workaround I am increasing the text container's top inset and removing the bottom inset:
textView.textContainerInset = UIEdgeInsetsMake(10, 0, 0, 0)
This works so far, but I arrived at a value of 10 by trial-and-error, and so far I've only tested it on a single device.
I am not interested in more hacky workarounds that require fragile, fixed values; I am trying to understand how this offset is being set and a proper way to fix it. I'm hoping that someone can provide some insight, thanks!
Just a speculation, but I think the problem is that the text view assumes that the height of itself does not change while calling textViewDidChange, so it scrolls when it thinks it has to, regardless of you changing its frame.
Not sure if you think my solution is too hacky, but this will stop it from scrolling when you don't want it. I simply pin the content offset to the top as long as the wanted content size is smaller than your max size.
Just add this:
func scrollViewDidScroll(scrollView: UIScrollView) {
if textView.contentSize.height <= MaxTextViewHeight && textView.contentOffset.y > 0.0 {
textView.contentOffset.y = 0.0;
}
}

How to make UIView change it size as it scrolls

I am implementing a scroll view picker I have implemented most of the part but I'm stuck at changing the size when it scrolls.
I'm trying to do this :
I have got till here and i don't know how to change size using scroll offset i tried many things but failed i need help
I'm using SwipeView to get the scroll
func swipeViewDidScroll(swipeView: SwipeView!) {
//USE swipeView.currentItemView to access current view
//USE swipeView.itemViewAtIndex(swipeView.currentItemIndex - 1) to access previous view
//USE swipeView.itemViewAtIndex(swipeView.currentItemIndex + 1) to access next View
swipeView.currentItemView.frame = CGRect(x: swipeView.currentItemView.bounds.origin.x, y: swipeView.currentItemView.bounds.origin.y , width: (swipeView.currentItemView.bounds.width + swipeView.scrollOffset) - CGFloat((280 * swipeView.currentItemIndex)), height: swipeView.currentItemView.bounds.height)
}
I have attached the project to make your work easier understanding my work
LINK TO PROJECT
What about this:
create a special class for the cells in the slider
when the cell is created, add NSLayoutContraints of width and aspect ratio to the view
create a method to expand the cell using the constraint inside the class, like
-(void)expandCell {
self.widthConstraint.constant = normalWidth * 1.05f;
}
-(void)normalizeCell {
self.widthConstraint.constant = normalWidth;
}
when the view is at the center you call the method expandCell to expand it 5% and when the cell is out you call the normalizeCell. To make things prettier you just animate that.

Animated width label with swift

I want to change the width of my label since my swift code.
If possible, do it in a annimation prograssif for a change. Is it possible ?
When I do:
self.lblChoice1.frame.size.width += 50
My exchange label width not ... Why?
Thank you in advance.
EDIT :
The first response is not working.
print(self.lblChoice1.frame.size.width)
self.lblChoice1.frame.size.width += 150
self.lblChoice1.contentMode = UIViewContentMode.Redraw
self.lblChoice1.setNeedsDisplay()
print(self.lblChoice1.frame.size.width)
This code displays me well in my console:
150.0
300.0
But my label size does not change the display ...
You are changing the frame, but you aren't telling the view that it needs to redraw itself. After changing the frame you should then call
self.lblchoice1.setNeedsDisplay()
Although you may need to change the label's content mode to UIViewContentModeRedraw to make sure it redraws.
Although it would be better to use UIView block animation methods to do this.
I dont think you can edit the UILabel's frame directly. You should change entire frame instead.
var lblChoice1Frame = self.lblChoice1.frame
lblChoice1Frame.size.width += 150
UIView.animateWithDuration(0.3) { () -> Void in
self.lblChoice1.frame = lblChoice1Frame
}

After changing my UItableView's Height, my scroll does not work again. Cant reach data at the bottom

So I am currently very new to ios programming and I am having a bit of an issue with my table view. First I call my web API to get the data I required to populate my table View. Using the data I am able to calculate the number of rows and sections that would exist on my table view. After that I calculate the correct height of my table view. I change the height of my table view and reload the table. It looks like this
func tableViewHight(numberOfRows : Int)
{
let sectionHeight = CGFloat(30) * CGFloat(numberOfSections - 1)
//This is the height of all the sections in my tableview put together(except the first section since its height will always be 0)
let tableviewMaximumHeight = UIScreen.mainScreen().bounds.size.height - self.myTableView.frame.origin.y
//Maximum height would be the distance from the y position of my table view, all the way to the bottom of the device.
if(tableviewMaximumHeight <= (cellRowHeight * CGFloat(numberOfRows) + sectionHeight))
{
self.myTableView.frame.size.height = tableviewMaximumHeight
}
else
{
self.myTableView.frame.size.height = cellRowHeight * CGFloat(numberOfRows) + sectionHeight
}
self.myTableView.reloadData()
}
My table view is able to change height and reload data perfectly. The only Problem is that I am not able to reach the bottom of my table view. I do not know what else to do. I have already check that my table view has
myTableView.scrollEnabled = true
myTableView.scrollTop = false
If you guys have any advice, I would appreciate it :).
The problem when you manually set the height of a UITableView is that you'll then also have to manually set its content height.
Use Autolayout instead to set the height.
Have an IBOutlet for an NSLayoutConstraint variable (say, tableHeightConstraint) that sets the height of your table, then, in your code:
tableHeightConstraint.constant = tableviewMaximumHeight
or
tableHeightConstraint.constant = cellRowHeight * CGFloat(numberOfRows) + sectionHeight
I found the main root of my problem. The issued lied in my maximumTableviewHeight variable. The problem was that I would the value for this variable in the view did load and apparently the y position of the my table view would always give zero in the view did load. Once the maximum table view height was resolve. The application worked like a a charm.

iCarousel - How to shift the focus to the left side

I need to implement iCarousel in a way so that it looks like this:
I have done all the modifications at my end to make it look like this but now the problem is that iCarousel works with the center image in the focus. Can I make it so that if there are only two images, they don't appear in the center but rather on the left? Think about it like the "left indented" content.
How do I do this?
iCarousal provide a property to sift focus left or right by set the width offset.
For right side use this code for swift 2.3 -
let widthOffset: Float = -120.0
self.customCarousel.viewpointOffset = CGSize(width: CGFloat(widthOffset), height: CGFloat(0))
This should be the property in iCarousel you are looking for viewpointOffset
Example...
// Modifiy widthOffset so it works well in your case
float widthOffset = 100.0;
[_yourCarousel setViewpointOffset:CGSizeMake(widthOffset, 0)];
The viewpointOffset property doesn't really work that way. It will let you align to one edge, but then when you scroll to the end you'll have the same problem.
iCarousel wasn't designed to do this. I suggest you switch to SwipeView instead (http://github.com/nicklockwood/SwipeView) which has the same delegate/datasource interface, but has an alignment property that you can use to set edge alignment, like this:
swipeView.alignment = SwipeViewAlignmentEdge;
Visit https://github.com/nicklockwood/iCarousel/issues/142
it may help.
nicklockwood (author) answer:
You could use the delegate and create a custom transform that offsets all of your views by a negative amount. Something like this:
- (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
{
float OFFSET_WIDTH = ...; // set this to about half the width of your view
return CATransform3DMakeTranslation(offset * itemWidth - OFFSET_WIDTH, 0, 0);
}
The only problem would be that when you reach the rightmost end of the
carousel there would be a gap, but you could use placeholder views to
fill the gap up.
I tripped over the same problem. After simple math I've found a more accurate answer. I've put this code in my viewDidAppear() function, because when I put it in viewDidLoad() the view.frame.width and view.frame.height took the original width of my storyboard, which didn't fit to bigger devices.
My use case was the following. My iCarousel items are simple squares. That means, I have for example a height of 3 and a width of 3. But the width of my iCarousel view is 5. In sum I have 5-3=2 space, 1 left and 1 right (because we know it's default is centered). So last step is to divide with 2 to get the width on one site = 1. With this knowledge we just have to set the viewPointOffset to 1 (in this case).
Final formular: let widthOffset = (view.frame.width - view.frame.height) / 2
Example in my code:
let widthOffset: Float = Float((mDetailCarousel.frame.width - mDetailCarousel.frame.height) / 2 )
mDetailCarousel.viewpointOffset = CGSize(width: CGFloat(widthOffset), height: CGFloat(0))

Resources