How to zoom a UIImageView that takes up a fullscreen cell in a UICollectionView image?
Since UICollectionView is a subclass of UIScrollView it should be fairly simple..
I tried to set minimumZoomScale, maximumZoomScale and viewForZoomingInScrollView: but the result is a mess.
In viewForZoomingInScrollView i returned the UIImageView, but that does not work.
Now i'm trying to return the visualized cell, but on zooming the image changes to the first cell.
it zooms but messes up the collection view.
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
if let selectedIndex = self.collectionView.indexPathsForVisibleItems().last as? NSIndexPath
{
let cell = self.collectionView.cellForItemAtIndexPath(selectedIndex)
return cell
}
return nil
}
So, what i need to do to zoom the image (cell) currently on screen?
Moreover pagingEnabled goes off automatically (that's good for panning the zoomed image, but not for scrolling the collection)
You need to put a new UIScrollView inside the cell of your UICollectionView since you should not mess with the zooming of the CollectionView itself.
Related
I am trying to zoom in and out a TableView. The TableView is in a View which is inside a ScrollView. The TableView is scrollable but the pinch to zoom isn't working like it works with ImageView.
I would really appreciate if anyone could shed some light to this problem and share a working example.
I have already tried setting min and max zoom for UIScrollView in attribute inspector.
You can do that by:
first you have to make your table view content size intrinsic by make it subclass the below class.
class IntrinsicTableView: UITableView {
override open var contentSize: CGSize {
didSet{
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize{
return contentSize
}
}
Then you will stop scrolling of your table view from the storyboard.
Then you will configure scroll view to enable zooming.
That's it.
The thing I want to achieve is a gallery, it can contain up to 300 images, using a UIScrollView will result in non optimized ram/cpu usage since it doesn't do pooling (correct me if I'm wrong), and it has a limitation on width, I can't make it 300 times the width of the screen (again correct me if I'm wrong).
so the right choice would be to use a UITableView
1 - how to make it scroll horizontally like in this gif ?
2 - how to make it snap to cells centers ?
EDIT
I'm using this, it gives the result I want but it has a problem, it has no tolerance for how much I should swipe to move to the next cell, I still need help..
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool)
{
// Find collectionview cell nearest to the center of collectionView
// Arbitrarily start with the last cell (as a default)
var closestCell : UICollectionViewCell = collectionView.visibleCells()[0];
for cell in collectionView!.visibleCells() as [UICollectionViewCell]
{
let closestCellDelta = abs(closestCell.center.x - collectionView.bounds.size.width/2.0)
let cellDelta = abs(cell.center.x - collectionView.bounds.size.width/2.0)
if (cellDelta < closestCellDelta)
{
closestCell = cell
}
}
let indexPath = collectionView.indexPathForCell(closestCell)
collectionView.scrollToItemAtIndexPath(indexPath!, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
}
func scrollViewWillBeginDecelerating(scrollView: UIScrollView)
{
// Find collectionview cell nearest to the center of collectionView
// Arbitrarily start with the last cell (as a default)
var closestCell : UICollectionViewCell = collectionView.visibleCells()[0];
for cell in collectionView!.visibleCells() as [UICollectionViewCell]
{
let closestCellDelta = abs(closestCell.center.x - collectionView.bounds.size.width/2.0)
let cellDelta = abs(cell.center.x - collectionView.bounds.size.width/2.0)
if (cellDelta < closestCellDelta)
{
closestCell = cell
}
}
let indexPath = collectionView.indexPathForCell(closestCell)
collectionView.scrollToItemAtIndexPath(indexPath!, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)
}
EDIT :-
I managed to do it without above code.
You should use UICollectionView with one cell or UIPageViewController to achieve this kind of effect. There is no way to use tableview horizontally. Somehow you can say UICollectionView as a horizontal representation of UITableView. UIPageViewcontroller is also good solution. You should read about both in detail and then decide what's more suitable for you!
and yes that's not good to use single scroll view with that much different size. It can create memory or performance issue!!
Update :
Have you tried to enable paging in your collection view's scroll view ?
look at screenshot below
Check the checkbox paging enable!
then after If you not feel smooth effect then you should try to uncheck adjust scroll view insets under viewcontroller under attribute inspector which you got by selecting your view controller
check the screenshot for that
EDIT by person who asked the question : -
adding this worked for me, as UICollectionView don't have
adjust scroll view insets option.
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
you can use UICollectionView and configure collection view cell
set collectionViewLayout size... This size based on above view
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(250, 150);
}
The Problem
I have a UITextView inside of a custom UITableViewCell subclass that is producing some odd behavior.
Here is a gif of the problem I'm seeing (relevant items are colored):
The height resizes correctly, but the full contents of the cell are not shown.
But when I pause execution and print out frames of the following:
Cell
Cell's content view
Text View
the frames are all correct!
Further, when I inspect the view using the view hierarchy debugger, the frames are all correct there too. There is one difference when using the view debugger though, and that is that I'm able to view the contents of the text view.
Here is what I see on the simulator vs in the debugger:
There seems to be an extraneous cell separator at the point where the yellow stops. Other than that, I can't find any sort of indicator of why the cell is not expanding past its original height.
My Code
In the storyboard, the UITextView has top, bottom and trailing constraints to the cell's content view, and a vertical spacing constraint to the UIImageView. The UIImageView has a fixed width and has a leading constraint to the cell's content view. I believe my constraints are set up correctly. Oh yeah, and scrolling is disabled on the UITextView.
As for code, I have a custom protocol that informs the table view controller when the notes field has changed:
protocol AddContactCellDelegate {
func notesViewDidChange(textView: UITextView)
}
Here is the relevant code from my UITableViewCell subclass:
class AddContactCell: UITableViewCell, UITextViewDelegate {
var delegate: AddContactCellDelegate?
func textViewDidChange(textView: UITextView) {
delegate?.notesViewDidChange(textView)
}
}
and from my UITableViewController subclass:
class AddContactViewController: UITableViewController, AddContactCellDelegate {
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 60.0
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let row = rows[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier(row.cellIdentifier, forIndexPath: indexPath) as! AddContactCell
cell.configureForRow(row)
cell.delegate = self
return cell
}
func notesViewDidChange(textView: UITextView) {
tableView.beginUpdates()
tableView.endUpdates()
}
}
Discussion
I've tried adding setNeedsLayout(), in to either the cell, the cell's content view, the tableview, or the textview, in just about every place, to no avail.
I rebuilt the entire view in the storyboard from scratch, same thing.
I tried creating a bare-bones project that has basically only the code above, and the sizing works correctly.
I've ruled out tons of other variables as being the culprit (for example, the tableview is in a container view, but the behavior persists without that).
One final weird point is that sometimes if I scroll the notes cell off the screen, leave the page, and come back again, everything looks as it should. The cell is fully resized and everything is visible. However, the problem resumes as soon as the text view goes to the next line, this time with all the previous text visible but none of the additional text.
If anyone has any ideas on what I might try next, it would be extremely helpful. Thanks!
Thanks to Steve asking for an example project that exhibits the behavior, I was able to figure out what is causing this issue.
To get the rounded corner effect, I had been using a layer mask on my cells. The mask uses the bounds of the cell to calculate its path, so when the cell updated itself to reflect the height of the text view, the mask was still in place and covered up the rest of the cell.
I didn't catch it because the rounding implementation was abstracted away in an extension. Whoops!
I'm building an iOS app with Swift where a user can scroll through a feed of images up and down (like instagram) and can also scroll left or right on the cell to see more images. Refer to this album(not able to upload images yet) and see F1 for how the UI is laid out.
My problem is when I scroll over to image 1C, the 3rd cell is also scrolling over to 3C. So when I scroll down to the third cell, it's already at 3C. See F2.
Additionally, if I scroll on the 3rd cell to 3B, it also repositions the first cell to 1B. See F3.
I'd like some help in understanding what's going on...
I've created a custom class for the cell with a function to load the images.
(Where I also initialize the imageView frames, scrollView frame and content size, and other properties which I'm not including in the code below.)
class CustomCell: UITableViewCell {
var imageView1: UIImageView = UIImageView()
var imageView2: UIImageView = UIImageView()
var imageView3: UIImageView = UIImageView()
func loadImages(#image1: String, image2: String, image3: String){
imageView1.image = UIImage(named: image1)
imageView2.image = UIImage(named: image2)
imageView3.image = UIImage(named: image3)
}}
and in my View Controller - cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:CustomCell = self.tableView.dequeueReusableCellWithIdentifier("CustomCell") as CustomCell
var (firstImage, secondImage, thirdImage) = images[indexPath.row]
cell.loadImages(image1: firstImage, image2: secondImage, image3: thirdImage)
return cell
}
FYI: This appears to only be happening when the view is the root view controller. It works fine when the view has been presented. ???
Thanks!
The UITableView dequeues reusable cells. That means that your horizontal scrollview in your cell will have the same content offset as the cell he dequeued. So if you scroll to let's say contentOffset.x = 100.0 in cell 1 and than scroll down in your tableview, it might happen that one of the following cells will have its scrollview subview with the same contentOffset.
Just set contentOffset.y = 0 in your cellForRowAtIndexPath.
Or better: Save the cell's selected imageIndex and set an appropriate contentOffset.
Reuseable means exactly that: to speed things up the cells gets reused. But as you are changing view properties these are present when the cell is populated with new values. Set the values back on population in cellF orRiwAtIndexPath or – cleaner IMHO – in cellWillDisplay.
I have a UICollectionView that holds a bunch of a photos.
However, if I scroll to the bottom the scrollview does not let me scroll to the bottom of the last few rows (it snaps back). I have tried override the collectionView.contentSize and just adding 1000 to the height but it doesn't fix the problem.
collectionView.contentSize = CGSizeMake(collectionView.contentSize.width, collectionView.contentSize.height + 1000)
Here is a video of the problem:
https://www.youtube.com/watch?v=fH57_pL0OjQ&list=UUIctdpq1Pzujc0u0ixMSeVw
Here is my code to create cells:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("selectPhotoCell", forIndexPath: indexPath) as B_SelectPhotoControllerViewCell
let reuseCount = ++cell.reuseCount
let asset = currentAssetAtIndex(indexPath.item)
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize:_cellSize, contentMode: .AspectFit, options: nil)//the target size here can be set to CGZero for a super blurry preview
{
result, info in
if reuseCount == cell.reuseCount
{
cell.imageView.image = result
cell.imageView.frame = CGRectMake(0, 0,self._cellSize.width,self._cellSize.height)
}
}
return cell
}
private func currentAssetAtIndex(index:NSInteger)->PHAsset
{
if let fetchResult = _assetsFetchResults
{
return fetchResult[index] as PHAsset
}else
{
return _selectedAssets[index]
}
}
Update:
Because I am adding this as a child view controller, there seems to be some problems with the offsetting of the scrollview. I haven't fixed it yet but when open this view without adding it as a child view to another view controller, the scrollview is the correct size
The problem was I was adding this as a child view controller.
As a result, after doing some animations, the UICollectionView bounds were sizing to the view it was attached to. As a result its height was wrong and hence why it was getting cut off.
I just came across this question from a quick Google and felt I could add something useful.
I am running a segmentedControl with a UIView that changes to different UICollectionViews on the segment change and I couldn't get the collectionView to scroll fully down.
This may not be the solution for all, but I found that if I went to the XIB I was loading in the view and set size to freeform and decrease it by the size of a cell I had removed the problem.
suspect your CollectionView's bottomAchor was not set correctly to the parent uiview's safeAreaLayoutGuide bottomAnchor