No Description

PhotoDetailViewController.swift 14KB

    // // PhotoDetailViewController.swift // Paiai_iOS // // Created by FFIB on 16/4/6. // Copyright © 2016年 FFIB. All rights reserved. // import UIKit import RxSwift import RxCocoa import RxDataSources import PaiaiDataKit import PaiaiUIKit final class PhotoDetailViewController: UIViewController { @IBOutlet weak var enterGroupView: UIView! @IBOutlet weak var group_avatar: UIImageView! @IBOutlet weak var group_name: UILabel! @IBOutlet weak var photoCollectionView: UICollectionView! @IBOutlet weak var userAvatar: UIImageView! @IBOutlet weak var userName: UILabel! @IBOutlet weak var photoTime: UILabel! @IBOutlet weak var thumbupCount: UILabel! @IBOutlet weak var thumbupView: UIView! @IBOutlet weak var commentCount: UILabel! @IBOutlet weak var commentTableView: UITableView! @IBOutlet weak var commentEditingView: UIView! @IBOutlet weak var commentHeight: NSLayoutConstraint! @IBOutlet weak var commentTextField: UITextField! @IBOutlet weak var sendBtn: UIButton! @IBOutlet weak var buyView: UIView! @IBOutlet weak var waterMarkView: UIView! @IBOutlet weak var waterMarkImage: UIImageView! @IBOutlet weak var waterMarkLabel: UILabel! @IBOutlet var keyboardGestureRcognizer: UITapGestureRecognizer! @IBOutlet weak var thumbupViewHeightConstraint: NSLayoutConstraint! @IBOutlet weak var commentEditYConstraint: NSLayoutConstraint! // MARK: data property var viewModel: PhotoDetailViewModel! let disposeBag = DisposeBag() // MARK: view function override func viewDidLoad() { super.viewDidLoad() navigationItem.title = "详情" binding() setup() } func setup() { setupCommentTextField() setupWaterMarkView() } func setupCommentTextField() { commentTextField.addLeftPadding(7) } func setupWaterMarkView() { guard let image = UIImage.PhotoDetail.purchaseBackground else { return } waterMarkView.backgroundColor = UIColor(patternImage: image) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(true) viewModel.viewWillAppear.accept(()) } } /// bind storyboard gesture action extension PhotoDetailViewController { @IBAction func recyclingKeyboard(_ sender: UITapGestureRecognizer) { commentTextField.resignFirstResponder() } @IBAction func purchase(_ sender: UITapGestureRecognizer) { viewModel.purchase() } @IBAction func enterGroup(_ sender: UITapGestureRecognizer) { viewModel.navigateToGroup() } } /// bind storyboard button action extension PhotoDetailViewController { @IBAction func share() { // let ctl = ShareViewController UIStoryboard.photoDetail.instantiateController(ShareViewController.self) // ctl.shareContent = "我使用拍爱分享了一张美图,你也快来试试吧" // // ctl.shareImgUrlThumb = datas[currentPhotoIndex].photo_thumbnail_url // // ctl.shareUrl = datas[currentPhotoIndex].photo_share_url // presentController(ctl) } @IBAction func comment() { commentTextField.becomeFirstResponder() } @IBAction func sendComment() { guard let text = commentTextField.text else { return } viewModel.submitComment(text: text) commentTextField.resignFirstResponder() } @IBAction func thumbup() { viewModel.submitThumbup() } } /// bind rx extension PhotoDetailViewController { var commentDataSource: RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoCommentItem>> { return RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoCommentItem>>( configureCell: {(_, tableView, indexPath, item) in let cell = tableView.dequeueReusableCell(withIdentifier: "photoDetailCommentCell", for: indexPath) as! PhotoDetailCommentCell cell.setInfo(item) return cell }) } var photoDataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>> { return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>>( configureCell: {(_, collectionView, indexPath, item) in let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoDetailImageCell", for: indexPath) as! PhotoDetailImageCell cell.imageView.setImage(item.murl.isEmpty ? item.photo_thumbnail2_url : item.murl, placeholder: UIImage.photoPlaceholder) return cell }) } func binding() { bindEnterGroupViewHiddenState() bindViewModelToGroupName() bindViewModelToGroupAvatar() bindViewModelToUserName() bindgingViewModelToUserAvatar() bindViewModelToPhotoTime() bindViewModelToThumbupCount() bindViewModelToThumbupView() bindViewModelToCommentCount() bindViewModelToCommentTableView() bindBuyViewIsVisiable() bindCommentTextFieldToSendBtn() bindCollectionViewDelegate() bindCollectionViewSelected() bindCollectionViewToListViewModel() bindListViewModelToCollectionView() bindViewModelToWatermarkImage() bindViewModelToWatermarkLabel() bindViewModelToWatermarkImageWithBought() bindViewModelToWatermarkLabelWithBought() bindViewWillAppear() monitorKeyboardWillShow() monitorKeyboardWillHide() } func bindEnterGroupViewHiddenState() { viewModel.isHiddenEnterGroupBtn.bind(to: enterGroupView.rx.isHidden).disposed(by: disposeBag) } func bindViewModelToGroupName() { viewModel.group_name.bind(to: group_name.rx.text).disposed(by: disposeBag) } func bindViewModelToGroupAvatar() { viewModel.group_avatar .map { UIImage(named: #"Group\#($0)"#)} .bind(to: group_avatar.rx.image) .disposed(by: disposeBag) } func bindgingViewModelToUserAvatar() { viewModel.userAvatar .subscribe(onNext: {[weak self] (avatar) in guard let `self` = self else { return } self.userAvatar.setImage(avatar) }).disposed(by: disposeBag) } func bindViewModelToUserName() { viewModel.userName.bind(to: userName.rx.text).disposed(by: disposeBag) } func bindViewModelToPhotoTime() { viewModel.photoTime.bind(to: photoTime.rx.text).disposed(by: disposeBag) } func bindViewModelToThumbupCount() { viewModel.thumbupCount.bind(to: thumbupCount.rx.text).disposed(by: disposeBag) } func bindViewModelToThumbupView() { viewModel.thumbupItems .asDriver(onErrorJustReturn: []) .drive(onNext: { [weak self] (items) in self?.setupThumbupView(items: items) }).disposed(by: disposeBag) } func bindViewModelToCommentCount() { viewModel.commentCount.bind(to: commentCount.rx.text).disposed(by: disposeBag) } func bindViewModelToCommentTableView() { viewModel.commentItems .bind(to: commentTableView.rx.items(dataSource: commentDataSource)) .disposed(by: disposeBag) } func bindBuyViewIsVisiable() { viewModel.canBuy.map { !$0 }.bind(to: buyView.rx.isHidden).disposed(by: disposeBag) } func bindCommentTextFieldToSendBtn() { commentTextField.rx.text .map { !($0?.isEmpty)! } .bind(to: sendBtn.rx.isEnabled) .disposed(by: disposeBag) } func bindCollectionViewDelegate() { photoCollectionView.rx.setDelegate(self).disposed(by: disposeBag) } func bindListViewModelToCollectionView() { viewModel.content .bind(to: photoCollectionView.rx.items(dataSource: photoDataSource)) .disposed(by: disposeBag) } func bindCollectionViewToListViewModel() { photoCollectionView.rx.willDisplayCell .asDriver() .drive(onNext: { [unowned self] in self.viewModel.willShow(index: $0.at.row) }) .disposed(by: disposeBag) } func bindCollectionViewSelected() { photoCollectionView.rx.itemSelected .asDriver(onErrorJustReturn: IndexPath(item: 0, section: 0)) .drive(onNext: { [unowned self] _ in self.viewModel.didSelected() }) .disposed(by: disposeBag) } func bindViewModelToWatermarkImage() { viewModel.watermarkImage.bind(to: waterMarkImage.rx.isHidden).disposed(by: disposeBag) } func bindViewModelToWatermarkLabel() { viewModel.watermarkText.bind(to: waterMarkLabel.rx.text).disposed(by: disposeBag) } func bindViewModelToWatermarkImageWithBought() { viewModel.watermarkImageWithBought.bind(to: waterMarkImage.rx.isHidden).disposed(by: disposeBag) } func bindViewModelToWatermarkLabelWithBought() { viewModel.watermarkTextWithBought.bind(to: waterMarkLabel.rx.text).disposed(by: disposeBag) } func bindViewWillAppear() { viewModel.viewWillAppear .asDriver() .drive(onNext: { [unowned self] _ in self.photoCollectionView.scrollToItem(at: IndexPath(item: self.viewModel.currIndex, section: 0), at: .right, animated: false) }) .disposed(by: disposeBag) } func monitorKeyboardWillShow() { NotificationCenter.default.rx .notification(UIResponder.keyboardWillShowNotification) .takeUntil(self.rx.deallocated) .subscribe { [unowned self] notification in self.keyboardGestureRcognizer.isEnabled = true guard let userInfo = notification.element?.userInfo, let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect, let timeInterval = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval, let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? Int else { return } UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: curve) ?? .linear) UIView.animate(withDuration: timeInterval, animations: { self.commentEditYConstraint.constant = keyboardFrame.height self.view.layoutIfNeeded() }) }.disposed(by: disposeBag) } func monitorKeyboardWillHide() { NotificationCenter.default.rx .notification(UIResponder.keyboardWillHideNotification) .takeUntil(self.rx.deallocated) .subscribe { [unowned self] notification in self.keyboardGestureRcognizer.isEnabled = false guard let userInfo = notification.element?.userInfo, let timeInterval = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval, let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? Int else { return } UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: curve) ?? .linear) UIView.animate(withDuration: timeInterval, animations: { self.commentEditYConstraint.constant = -56 self.view.layoutIfNeeded() }) self.commentTextField.clear() }.disposed(by: disposeBag) } } extension PhotoDetailViewController { func setupThumbupView(items: [PhotoThumbupUserItem]) { thumbupView.subviews.forEach { $0.removeFromSuperview() } let row = (Int(kScreenWidth) - 6) / 34 var topConstraint: CGFloat = 6 var last: UIImageView? for (index, item) in items.enumerated() { let imageView = UIImageView() imageView.cornerRadius = 5 imageView.translatesAutoresizingMaskIntoConstraints = false imageView.setImage(item.avatar, placeholder: UIImage.defaultAvatar) thumbupView.addSubview(imageView) if index % row == 0 && index != 0 { topConstraint += 28 + 6 last = nil } NSLayoutConstraint.activate([ imageView.widthAnchor.constraint(equalToConstant: 28), imageView.heightAnchor.constraint(equalToConstant: 28), imageView.topAnchor.constraint(equalTo: thumbupView.topAnchor, constant: topConstraint), imageView.leadingAnchor.constraint(equalTo: last?.trailingAnchor ?? thumbupView.leadingAnchor, constant: 6) ]) last = imageView } thumbupViewHeightConstraint.constant = items.isEmpty ? 1 : topConstraint + 34 commentTableView.tableHeaderView?.height = 532 + thumbupViewHeightConstraint.constant } } extension PhotoDetailViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: kScreenWidth, height: 359) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 0 } } extension PhotoDetailViewController: NavigationBackViewController {} extension PhotoDetailViewController: Storyboarded { static func instantiate() -> PhotoDetailViewController { return UIStoryboard.photoDetail.instantiateViewController(type: PhotoDetailViewController.self) } }