ExpyTableView icon indicating copy to clipboard operation
ExpyTableView copied to clipboard

ContentOffset/ScrollView is jumping when expanding/collapsing cells

Open gaborcsontos opened this issue 7 years ago • 6 comments

Hi Guys.

Thanks for this awesome library, it saved my life. Perhaps I met with an annoying bug. When I collapsed/expanded a section, the tableview's contentoffset had a weird jumping. After spent some hours of researching to solve this really annoying problem, I found out the best solution is to set an observer when the contentOffset is changing.

After implementing some properties and the observer, the jumping affect disappears.

fileprivate var isCellUpdateInProgress: Bool = false
fileprivate var lastScrollOffset: CGPoint!
open override var dataSource: UITableViewDataSource? {
	get {
		return super.dataSource
	}
	set(dataSource) {
		guard let dataSource = dataSource else { return }
		expyDataSource = dataSource as? ExpyTableViewDataSource
		super.dataSource = self
        self.addObserver(self, forKeyPath: "contentOffset", options: NSKeyValueObservingOptions.new, context: nil)
	}
}

private func startAnimating(_ tableView: ExpyTableView, with type: ExpyActionType, forSection section: Int) {

	let headerCell = (self.cellForRow(at: IndexPath(row: 0, section: section)))
	let headerCellConformant = headerCell as? ExpyTableViewHeaderCell
	
    
	CATransaction.begin()

	headerCell?.isUserInteractionEnabled = false
	
	//Inform the delegates here.
	headerCellConformant?.changeState((type == .expand ? .willExpand : .willCollapse), cellReuseStatus: false)
	expyDelegate?.tableView?(tableView, expyState: (type == .expand ? .willExpand : .willCollapse), changeForSection: section)

	CATransaction.setCompletionBlock { [weak self] () -> (Void) in
		//Inform the delegates here.
		headerCellConformant?.changeState((type == .expand ? .didExpand : .didCollapse), cellReuseStatus: false)
		
		self?.expyDelegate?.tableView?(tableView, expyState: (type == .expand ? .didExpand : .didCollapse), changeForSection: section)
		headerCell?.isUserInteractionEnabled = true
        self?.isCellUpdateInProgress = false
	}
    isCellUpdateInProgress = true
    lastScrollOffset = tableView.contentOffset
	tableView.beginUpdates()
    
	//Don't insert or delete anything if section has only 1 cell.
	if let sectionRowCount = expyDataSource?.tableView(tableView, numberOfRowsInSection: section), sectionRowCount > 1 {
		
		var indexesToProcess: [IndexPath] = []
		
		//Start from 1, because 0 is the header cell.
		for row in 1..<sectionRowCount {
			indexesToProcess.append(IndexPath(row: row, section: section))
		}
		//Expand means inserting rows, collapse means deleting rows.
		if type == .expand {
			self.insertRows(at: indexesToProcess, with: expandingAnimation)
		}else if type == .collapse {
			self.deleteRows(at: indexesToProcess, with: collapsingAnimation)
		}
	}
    
    tableView.endUpdates()
    tableView.layer.removeAllAnimations()
    self.setContentOffset(self.lastScrollOffset, animated: false)
	CATransaction.commit()
}

override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "contentOffset" {
        if isCellUpdateInProgress {
            self.setContentOffset(self.lastScrollOffset, animated: false)
        }
    }
}

Hope it will help!

gaborcsontos avatar Mar 04 '18 17:03 gaborcsontos

Hi! I'm not able to reproduce this. Can it be caused by some "scroll-to-show-expanded-cell" code? Do you have an example project that reproduces this issue? @gaborcsontos

okhanokbay avatar Mar 08 '18 04:03 okhanokbay

I had this issue with the original code during the animation, when the cells were expanding/collapsing. After added the code above, it solved the scroll jumping.

gaborcsontos avatar Mar 08 '18 15:03 gaborcsontos

Can you please tell if it happens in Customization Example or Basic Example or in both @gaborcsontos

okhanokbay avatar Mar 08 '18 22:03 okhanokbay

It happened in my project, not in the examples.

gaborcsontos avatar Mar 09 '18 02:03 gaborcsontos

Thanks! Will look into this soon.

okhanokbay avatar Mar 16 '18 01:03 okhanokbay

@gaborcsontos I also have this problem. I solved by your opening. Thank you!!

tatsuya0505 avatar Apr 20 '19 12:04 tatsuya0505