UILabel with auto scroll - iphone

How I create UILabel with auto scroll from left to right?
like this http://www.youtube.com/watch?v=moI3ROPBm4Y
Thanks!
I use this code for this (From YouTube):
-(void)time:(NSTimer *)theTimer{
textLabel.center = CGPointMake(textLabel.center.x - 2.2, textLabel.center.y);
if (textLabel.center.x < -(textLabel.bounds.size.width/1.5)){
textLabel.center = CGPointMake(320 + (textLabel.bounds.size.width/1/5), textLabel.center.y);
}
how I to change the move label from left to right?

You can have a looping selector moving the viewarea of the frame slowly sideways. That should do the trick, without blocking the UI.

You would have to create a subclass of UILabel that overrides the drawRect. Then on a timer you would redraw the text with an offset, most easily with a ever increasing translation transform on the graphics context.
You also have to be careful to schedule the timer on the common modes because otherwise the scrolling of the label would stop as soon as the user starts scrolling any scroll view.

Related

Why will my label not change location when trying to add additional text field?

So I have a button on my storyboard. When that button is pressed, I want to move a certain label down a little bit and also add a new text field to the screen. Here is the simplified code:
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.addIngredientLabel.center.y += self.addIngredientLabel.bounds.height
}) { (_) -> Void in
let newIngredientTextField = UITextField(frame: CGRectMake(100, 110, 100, 100))
newIngredientTextField.center.y -= 50
newIngredientTextField.placeholder = "place text here"
newIngredientTextField.contentHorizontalAlignment = .Left
self.view.addSubview(newIngredientTextField)
}
The problem though, is that after the animation is completed, the label jumps back to its original location. It is like the animation is being pre-maturely terminated. The textField gets added and the label moves but it does not stay moved.
I have tried adding the text field at the end of the function instead of in a completion block. No kind of reordering seems to be helping.
I feel like I am not understanding something fundamental to animations. If anyone has any advice I would greatly appreciate it.
Since you're using the storyboard, you are most likely also using auto-layout. The positions of your controls are determined in your visual design (storyboard) and will adjust automatically to orientation changes and adapt to various device screen sizes. This is good but the flip size is that you cannot directly change the positions of your control using their x,y coordinates.
Instead, you can change values in the constraints you defined in the storyboard. for example, if you button has a "Top" distancs constraint with a control above it (or the edge of the view), you can change the constraint's "constant" attribute to indirectly change the position of the control.
In order to manipulate the contraints in your code, you can create IBOutlets for them just as you would do with any control.

UITableViewCell content moving around

I have an iPhone app in which I'm using a UITableView to format a set of text responses, one per row. I've set up the cell in the storyboard to have a label inside it, and set up a constraint saying that the label should be 10 points from the edge of the cell. I then set up a custom subclass of UITableViewCell, set the cell in the storyboard to be of that class, and connected the outlet.
However, when I load the table, I see the text in the cell moving slightly to the right under some circumstances: when I select the cell, or when I load additional cells into the table. In fact, in the latter case, sometimes everything gets shifted to the right, even cells which were already there!
What the heck is going on here? The only changes I'm making in tableView:cellForRowAtIndexPath: are to the text in the label, and I'm always setting it. And I've unset "Indent While Editing" on the cell in the storyboard.
Answering some of the questions: I'm setting the view up using the storyboard. Xcode isn't reporting any ambiguity with the constraints. Also, here are the screenshots, before and after:
My guess is that the constraints for the label are ambiguous. Ambiguity can make UI components jump around for inexplicable reasons. You probably need to set more constraints for the label to define its position on both axes.
Or, maybe all you need to do is set the label to the "size that fits content" (intrinsic content size) under the Editor menu in IB.
Did you add a new label to the UITableViewCell, or are you working with the textLabel that already exists in it? If you added a new one, consider removing it and using the cell's existing textLabel property instead. If that's not an option for some reason, double-check that the label you've added is in the contentView of the cell, and that all the constraints are relative to the parent view, not to the cell itself.
Also, for debugging, you could set the cell's contentView background color to red (cell.contentView.backgroundColor = [UIColor redColor];) - this might give you a better sense of what's moving, the label or the whole view.
This is just a guess without seeing your code. I had a similar problem once, when the app reused an existing cell, the dimensions of the label were not correct. So, I had to remove the old label in my cellForRowAtIndexPath method, before adding a new label. Here's how I removed the old one:
UIView *oldLabel = [cell viewWithTag:3];
if (oldLabel != nil)
{
[oldLabel removeFromSuperview];
}
Then I added a new label like this:
[cell.contentView addSubview:newLabelOrWhatever];
It might be worth checking to see that your string content doesn't have a space prefixed on it. Also, you could verify the actual position of the label by setting the background color.
I had a similar issue when the label would move when the cell was selected. It was a custom cell that I was loading from a custom Nib.
In the Nib I had not set the backgroundView of the UITableViewCell (superclass) to any view. Once I set it (I set it to the ContentView) the issue stopped.
My auto-layout constrains seems fine and had no issues, so I'm assuming it was the above that fixed it.
If you have a custom subclass of UITableViewCell, try implementing layoutSubviews. Let me try from the top of my head:
static CGFloat const kLeftMargin = 10.0f;
- (void) layoutSubviews
{
[super layoutSubviews];
/* Prepare for processing */
CGSize cellSize = self.bounds.size;
/* Change the textLabel frame */
{
/* Compute the new label frame */
CGSize labelSize = self.textLabel.bounds.size;
CGFloat xCoor = kLeftMargin;
CGFloat yCoor = roundf((cellSize.height - labelSize.height) / 2.0f);
CGRect labelFrame = CGRectMake(xCoor, yCoor,
labelSize.width, labelSize.height);
/* Set the new label frame */
self.textLabel.frame = labelFrame;
}
}
Now, this isn't what is usually recommended (since a lot of people use Storyboards and NIBs), but from experience, if you want some correct layouting done, implement layoutSubviews.

What is the best best way to disable cross fades on UICollectionView/UICollectionViewLayout rotates or bounds changes?

I have a subclass of UICollectionViewLayout which places cells in a circle. The layout returns YES for the call shouldInvalidateLayoutForBoundsChange:. On rotation, the cell in the initial position fades out and the cell in the final position fades in.
By adding the following code to my layout I can disable the fades and the
circle of items appears to to simply rotate with the orientation change:
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
return nil;
}
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
return [self layoutAttributesForItemAtIndexPath:itemIndexPath];
}
Why do the methods get called on a bounds change because documentation doesn't seem to suggest they do? Documentation seems to state they get called related to insertion and removal of items from the collection view.
Is there a better way to disable the cross fade during rotation?
Notes:
The initialLayoutAttributesForAppearingItemAtIndexPath: documentation
states that by default the method returns nil but calls to super returned
non-nil values.
I set symbolic breakspoints on the UICollectionView methods
deleteItemsAtIndexPaths:, moveItemAtIndexPath:toIndexPath: and
insertItemsAtIndexPaths: and none of them are hit during rotation.
The UICollectionViewLayout.h file states
// This set of methods is called when the collection view undergoes an
animated transition such as a batch update block or an animated
bounds change.
// For each element on screen before the invalidation,
finalLayoutAttributesForDisappearingXXX will be called and an
animation setup from what is on screen to those final attributes.
// For each element on screen after the invalidation,
initialLayoutAttributesForAppearingXXX will be called an an
animation setup from those initial attributes to what ends up on
screen.
which clearly says they are called on bounds changes. Rather than removal/insertion, "old state" and "new state" seems more accurate.

iPhone UITableView Add content at the top without scrolling

I have a potentially very long scrolling log of messages within a UITableView The user would be able to navigate the table by scrolling.
What I'm trying to do is add new content at the top of the table. If the top of the table is visible, the new row would push the rest of the content down. But if the first row of the table is not visible, the table would silently add another row on top without scrolling.
I'm doing this to prevent the table scrolling to the top from interrupting the user browsing data. If I ask the table to simply scroll to the new insertion point, the user's position within the table would be lost, frustrating the user.
One of the ways I can try to implement this is by inserting data into an NSMutableArray at index 0. Would this work? An extra question: how expensive is inserting data at the beginning of an NSMutableArray. I would expect that such operation is optimized, but would like to make sure. What am I missing with this implementation?
Thank you!
How to insert without bumping the view:
Use the tableView's (UIScrollView) contentOffset values to find where the user is currently scrolled to.
Add the new row at the top, with animated:NO
Update the tableView's contentOffset to be where the user was at plus whatever the height of your row is.
How to avoid causing issues doing this while the user is dragging:
Keep track of when the user is dragging, and if you want to insert rows during a drag / motion, add them to a queue that is executed after the user releases.
CGSize beforeContentSize = self.tableView.contentSize;
[self.tableView reloadData];
CGSize afterContentSize = self.tableView.contentSize;
CGPoint afterContentOffset = self.tableView.contentOffset;
CGPoint newContentOffset = CGPointMake(afterContentOffset.x, afterContentOffset.y + afterContentSize.height - beforeContentSize.height);
self.tableView.contentOffset = newContentOffset;
Just posted an answer with code snippets here
Keep uitableview static when inserting rows at the top
Basically:
Save the scroll offset where you would have called beginUpdate:.
In place of calls to InsertCell you add the cell's height to the saved offset.
Where you would have called endUpdate:, call reloadData, then scroll by the saved offset with NO animation.

iOS: Toggling between UIScrollView views without adding new views?

I am having a problem! When I use addSubview: and add a view to a UIScrollView, it adds a completely new view.
I want to either:
toggle between 3 predefined views, or
remove the last view from the UIScrollView before adding another one.
(All 3 views have some images so I'd imagine that the second option would be more efficient, memory-wise. However, perhaps the first option would be better on battery life? This is a 'subquestion'.)
How does one accomplish this?
You could accomplish your plan B by using removeFromSuperview function of your UIView.
Use it as below.
[mySecondImageView removeFromSuperview];
[myScrollView addSubview:myThirdImageView];
EDITED:
When you create UIImageView assign a tag value to each and also use and integer iVar to hold the tag value of your current view lets say it's currentViewTag ;
myFirstImageView.tag = 1;
mySecondImageView.tag = 2;
myThirdImageView.tag = 3;
currentViewTag = 1;
[myScrollView addSubview:myFirstImageView];
Now use as below
[[myScrollView viewWithTag:currentViewTag] removeFromSuperview];
[myScrollView addSubview:myThirdImageView];
currentViewTag = 3;
Sounds to me that you are trying to implement an infinite scrolling uiscrollview like the photos app.
If so, you don't need to remove any subviews and add them, you just need to create a UIScrollView that is as wide as three of your images and then when the scroll view is scrolled, change the image in either position 1 or 3 depending on which way the scroll is performed and then reset the position of the scroll view. If this is what you are trying to do, I can give more information if you need it.