У меня есть представление о коллекции. Когда я прикасаюсь к ячейке, анимация из класса Celloction Cellcelcell играет. Когда я нажимаю на ячейку, процесс загрузки файла начинается в методе DidSelectiTemat . Чтобы обновить процесс, я использую код здесь ReloadItem (IndexPath: IndexPath) Проблема в том, что, если при загрузке файла я пытаюсь коснуться ячейки, анимация будет воспроизводиться один раз, например, прыжок или зацеп Это вообще не будет работать при прикосновении, пока файл не будет загружен. Кроме того, во время загрузки, когда ячейка снова нажимается, метод DidSelectiTemat не будет вызван до тех пор, пока файл не будет загружен. Тот факт, что метод DidSelectiTemat не вызывается во время загрузки файлов, хорош. Это предотвращает загрузку одного и того же файла несколько раз. Но проблема в том, что я не понимаю, почему это происходит, потому что я нигде не написал такого кода. Как исправить анимацию и почему selectiTemat не вызывается во время загрузки файла?
cod > Я удалил весь код, связанный с загрузкой, чтобы сохранить рассматриваемое пространство и заменил его на таймер для моделирования прогресса загрузки файла < /p>
Коллекция: < /p>
class CarouselController: UIViewController, UICollectionViewDelegate {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource?
let sections = Bundle.main.decode([Section].self, from: "carouselData.json")
var progressA = 0.0
override func viewDidLoad() {
super.viewDidLoad()
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createCompositionalLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.isScrollEnabled = false
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .never
view.addSubview(collectionView)
collectionView.register(CarouselCell.self, forCellWithReuseIdentifier: CarouselCell.reuseIdentifier)
createDataSource()
reloadData()
}
@objc func createDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in
switch self.sections[indexPath.section].identifier {
case "carouselCell":
let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
cell.title.text = "\(self.progressA)"
print(self.progressA)
return cell
default: return self.configure(CarouselCell.self, with: item, for: indexPath)
}
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
_ = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true) { timer in
guard self.progressA UICollectionViewLayout {
UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupWidth = (layoutEnvironment.container.contentSize.width * 1.05)/3
let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(groupWidth),
heightDimension: .absolute(groupWidth))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(
top: (layoutEnvironment.container.contentSize.height/2) - (groupWidth/2),
leading: 0,
bottom: 0,
trailing: 0)
section.interGroupSpacing = 64
section.orthogonalScrollingBehavior = .groupPagingCentered
section.contentInsetsReference = .none
return section
}
}
func configure(_ cellType: T.Type, with item: Item, for indexPath: IndexPath) -> T {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { fatalError("\(cellType)") }
cell.configure(with: item)
return cell
}
func reloadData() {
var snapshot = NSDiffableDataSourceSnapshot()
snapshot.appendSections(sections)
for section in sections { snapshot.appendItems(section.item, toSection: section) }
dataSource?.apply(snapshot)
}
}
< /code>
cell < /p>
import Combine
class CarouselCell: UICollectionViewCell, SelfConfiguringCell {
static let reuseIdentifier: String = "carouselCell"
var imageView: UIImageView = {
let image = UIImageView()
image.contentMode = .scaleToFill
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
var textView: UIView = {
let view = UIView()
view.backgroundColor = .blue
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
var title: UILabel = {
let label = UILabel()
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override var isHighlighted: Bool {
didSet { if oldValue == false && isHighlighted { animateScale(to: 0.9, duration: 0.4) }
else if oldValue == true && !isHighlighted { animateScale(to: 1, duration: 0.38) }
}
}
var imageTask: AnyCancellable?
override func prepareForReuse() {
super.prepareForReuse()
imageView.image = nil
imageTask?.cancel()
}
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(imageView)
contentView.addSubview(textView)
textView.addSubview(title)
imageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0).isActive = true
imageView.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: 0.7).isActive = true
imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true
imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true
textView.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: 0.16).isActive = true
textView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 24).isActive = true
textView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -24).isActive = true
textView.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: -6).isActive = true
textView.layer.cornerRadius = contentView.frame.size.height*0.16/2
title.leadingAnchor.constraint(equalTo: textView.leadingAnchor, constant: 0).isActive = true
title.trailingAnchor.constraint(equalTo: textView.trailingAnchor, constant: 0).isActive = true
title.topAnchor.constraint(equalTo: textView.topAnchor, constant: 0).isActive = true
title.bottomAnchor.constraint(equalTo: textView.bottomAnchor, constant: 0).isActive = true
}
private func animateScale(to scale: CGFloat, duration: TimeInterval) {
UIView.animate( withDuration: duration, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.5, options: [.beginFromCurrentState], animations: {
self.imageView.transform = .init(scaleX: scale, y: scale)
self.textView.transform = .init(scaleX: scale, y: scale)
}, completion: nil)
}
func configure(with item: Item) {
title.text = "item.title"
textView.backgroundColor = .green
imageTask = Future() { promise in
UIImage(named: item.image)?.prepareForDisplay(completionHandler: { loadedImage in
promise(Result.success(loadedImage))
})
}
.receive(on: DispatchQueue.main)
.sink { image in
self.imageView.image = UIImage(named: "cover2")
}
}
required init?(coder: NSCoder) {
fatalError("error")
}
}
< /code>
exother: < /p>
extension Bundle {
func decode(_ type: T.Type, from file: String) -> T {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode(T.self, from: data) else {
fatalError("Failed to decode \(file) from bundle.")
}
return loaded
}
}
protocol SelfConfiguringCell {
static var reuseIdentifier: String { get }
func configure(with item: Item)
}
public struct Section: Decodable, Hashable { let identifier: String; let item: [Item] }
public struct Item: Decodable, Hashable { let index: Int; let title: String; let image: String }
[ {
"identifier": "carouselCell",
"item": [
{
"index": 1,
"title": "0",
"image": "cover1",
},
] }, ]
на основе ответа @Rob
kvo variant (не работает)
Я получаю прогресс внутри наблюдателя, но текст ячейки не обновляется. Почему? < /P>
var nameObservation: NSKeyValueObservation?
@objc dynamic var progress = 0.0
func createDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in
switch self.sections[indexPath.section].identifier {
case "carouselCell":
let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
self.nameObservation = self.observe(\.progress, options: .new) { vc, change in
cell.title.text = "\(self.progress)"
}
return cell
default: return self.configure(CarouselCell.self, with: item, for: indexPath)
}
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
_ = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true) { timer in
guard self.progress
Подробнее здесь: https://stackoverflow.com/questions/793 ... ction-view
Как исправить анимационную сцепку в представлении коллекции? ⇐ IOS
Программируем под IOS
-
Anonymous
1738251979
Anonymous
У меня есть представление о коллекции. Когда я прикасаюсь к ячейке, анимация из класса Celloction Cellcelcell играет. Когда я нажимаю на ячейку, процесс загрузки файла начинается в методе DidSelectiTemat . Чтобы обновить процесс, я использую код здесь ReloadItem (IndexPath: IndexPath) Проблема в том, что, если при загрузке файла я пытаюсь коснуться ячейки, анимация будет воспроизводиться один раз, например, прыжок или зацеп Это вообще не будет работать при прикосновении, пока файл не будет загружен. Кроме того, во время загрузки, когда ячейка снова нажимается, метод DidSelectiTemat не будет вызван до тех пор, пока файл не будет загружен. Тот факт, что метод DidSelectiTemat не вызывается во время загрузки файлов, хорош. Это предотвращает загрузку одного и того же файла несколько раз. Но проблема в том, что я не понимаю, почему это происходит, потому что я нигде не написал такого кода. Как исправить анимацию и почему selectiTemat не вызывается во время загрузки файла?
[b] cod > Я удалил весь код, связанный с загрузкой, чтобы сохранить рассматриваемое пространство и заменил его на таймер для моделирования прогресса загрузки файла < /p>
Коллекция: < /p>
class CarouselController: UIViewController, UICollectionViewDelegate {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource?
let sections = Bundle.main.decode([Section].self, from: "carouselData.json")
var progressA = 0.0
override func viewDidLoad() {
super.viewDidLoad()
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createCompositionalLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.isScrollEnabled = false
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .never
view.addSubview(collectionView)
collectionView.register(CarouselCell.self, forCellWithReuseIdentifier: CarouselCell.reuseIdentifier)
createDataSource()
reloadData()
}
@objc func createDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in
switch self.sections[indexPath.section].identifier {
case "carouselCell":
let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
cell.title.text = "\(self.progressA)"
print(self.progressA)
return cell
default: return self.configure(CarouselCell.self, with: item, for: indexPath)
}
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
_ = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true) { timer in
guard self.progressA UICollectionViewLayout {
UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupWidth = (layoutEnvironment.container.contentSize.width * 1.05)/3
let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(groupWidth),
heightDimension: .absolute(groupWidth))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(
top: (layoutEnvironment.container.contentSize.height/2) - (groupWidth/2),
leading: 0,
bottom: 0,
trailing: 0)
section.interGroupSpacing = 64
section.orthogonalScrollingBehavior = .groupPagingCentered
section.contentInsetsReference = .none
return section
}
}
func configure(_ cellType: T.Type, with item: Item, for indexPath: IndexPath) -> T {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { fatalError("\(cellType)") }
cell.configure(with: item)
return cell
}
func reloadData() {
var snapshot = NSDiffableDataSourceSnapshot()
snapshot.appendSections(sections)
for section in sections { snapshot.appendItems(section.item, toSection: section) }
dataSource?.apply(snapshot)
}
}
< /code>
cell < /p>
import Combine
class CarouselCell: UICollectionViewCell, SelfConfiguringCell {
static let reuseIdentifier: String = "carouselCell"
var imageView: UIImageView = {
let image = UIImageView()
image.contentMode = .scaleToFill
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
var textView: UIView = {
let view = UIView()
view.backgroundColor = .blue
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
var title: UILabel = {
let label = UILabel()
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override var isHighlighted: Bool {
didSet { if oldValue == false && isHighlighted { animateScale(to: 0.9, duration: 0.4) }
else if oldValue == true && !isHighlighted { animateScale(to: 1, duration: 0.38) }
}
}
var imageTask: AnyCancellable?
override func prepareForReuse() {
super.prepareForReuse()
imageView.image = nil
imageTask?.cancel()
}
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(imageView)
contentView.addSubview(textView)
textView.addSubview(title)
imageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0).isActive = true
imageView.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: 0.7).isActive = true
imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true
imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true
textView.heightAnchor.constraint(equalTo: contentView.heightAnchor, multiplier: 0.16).isActive = true
textView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 24).isActive = true
textView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -24).isActive = true
textView.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: -6).isActive = true
textView.layer.cornerRadius = contentView.frame.size.height*0.16/2
title.leadingAnchor.constraint(equalTo: textView.leadingAnchor, constant: 0).isActive = true
title.trailingAnchor.constraint(equalTo: textView.trailingAnchor, constant: 0).isActive = true
title.topAnchor.constraint(equalTo: textView.topAnchor, constant: 0).isActive = true
title.bottomAnchor.constraint(equalTo: textView.bottomAnchor, constant: 0).isActive = true
}
private func animateScale(to scale: CGFloat, duration: TimeInterval) {
UIView.animate( withDuration: duration, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.5, options: [.beginFromCurrentState], animations: {
self.imageView.transform = .init(scaleX: scale, y: scale)
self.textView.transform = .init(scaleX: scale, y: scale)
}, completion: nil)
}
func configure(with item: Item) {
title.text = "item.title"
textView.backgroundColor = .green
imageTask = Future() { promise in
UIImage(named: item.image)?.prepareForDisplay(completionHandler: { loadedImage in
promise(Result.success(loadedImage))
})
}
.receive(on: DispatchQueue.main)
.sink { image in
self.imageView.image = UIImage(named: "cover2")
}
}
required init?(coder: NSCoder) {
fatalError("error")
}
}
< /code>
exother: < /p>
extension Bundle {
func decode(_ type: T.Type, from file: String) -> T {
guard let url = self.url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
guard let loaded = try? decoder.decode(T.self, from: data) else {
fatalError("Failed to decode \(file) from bundle.")
}
return loaded
}
}
protocol SelfConfiguringCell {
static var reuseIdentifier: String { get }
func configure(with item: Item)
}
public struct Section: Decodable, Hashable { let identifier: String; let item: [Item] }
public struct Item: Decodable, Hashable { let index: Int; let title: String; let image: String }
[ {
"identifier": "carouselCell",
"item": [
{
"index": 1,
"title": "0",
"image": "cover1",
},
] }, ]
на основе ответа @Rob [/b]
[b] kvo variant (не работает) [/b]
Я получаю прогресс внутри наблюдателя, но текст ячейки не обновляется. Почему? < /P>
var nameObservation: NSKeyValueObservation?
@objc dynamic var progress = 0.0
func createDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in
switch self.sections[indexPath.section].identifier {
case "carouselCell":
let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
self.nameObservation = self.observe(\.progress, options: .new) { vc, change in
cell.title.text = "\(self.progress)"
}
return cell
default: return self.configure(CarouselCell.self, with: item, for: indexPath)
}
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
_ = Timer.scheduledTimer(withTimeInterval: 0.10, repeats: true) { timer in
guard self.progress
Подробнее здесь: [url]https://stackoverflow.com/questions/79397856/how-to-fix-animation-hitch-in-collection-view[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия