UIViewController+Ring.swift 6 KB
Newer Older
1
/*
Quentin Muret's avatar
Quentin Muret committed
2
 *  Copyright (C) 2017-2018 Savoir-faire Linux Inc.
3 4
 *
 *  Author: Thibault Wittemberg <thibault.wittemberg@savoirfairelinux.com>
Quentin Muret's avatar
Quentin Muret committed
5
 *  Author: Quentin Muret <quentin.muret@gmail.com>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */

import Foundation
import UIKit
import RxSwift

26 27
// swiftlint:disable identifier_name

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
extension UIViewController {

    /// Find the active UITextField if it exists
    ///
    /// - Parameters:
    ///     - view: The UIView to search into
    /// - Returns: The active UITextField (ie: isFirstResponder)
    func findActiveTextField(in view: UIView) -> UITextField? {

        guard !view.subviews.isEmpty else { return nil }

        for currentView in view.subviews {
            if  let textfield = currentView as? UITextField,
                textfield.isFirstResponder {
                return textfield
            }

            if let textField = findActiveTextField(in: currentView) {
                return textField
            }
        }

        return nil
    }

Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
    func findPathWithActiveTextField(in table: UITableView) -> IndexPath? {
        if table.numberOfSections <= 0 {return nil}
        for i in 0..<table.numberOfSections {
            if table.numberOfRows(inSection: i) == 0 {return nil}
            for k in 0..<table.numberOfRows(inSection: i) {
                let path = IndexPath(row: k, section: i)
                if let row = table.cellForRow(at: path) {
                    if self.findActiveTextField(in: row) != nil {
                        return path
                    }
                }
            }
        }
        return nil
    }

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    /// Scroll the UIScrollView to the right position
    /// according to keyboard's height
    ///
    /// - Parameters:
    ///     - scrollView: The scrollView to adapt
    ///     - disposeBag: The RxSwift DisposeBag linked to the UIViewController life cycle
    func adaptToKeyboardState (for scrollView: UIScrollView, with disposeBag: DisposeBag) {

        NotificationCenter.keyboardHeight.observeOn(MainScheduler.instance).subscribe(onNext: { [unowned self, unowned scrollView] (height) in
            let trueHeight = height>0 ? height+100 : 0.0
            let contentInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: trueHeight, right: 0.0)

            scrollView.contentInset = contentInsets

            // If active text field is hidden by keyboard, scroll it so it's visible
            // Your app might not need or want this behavior.
            if let activeField = self.findActiveTextField(in: scrollView) {
                var aRect = self.view.frame
                aRect.size.height -= trueHeight

                if !aRect.contains(activeField.frame.origin) {
                    scrollView.scrollRectToVisible(activeField.frame, animated: true)
                }
            }

        }).disposed(by: disposeBag)

    }
97

Kateryna Kostiuk's avatar
Kateryna Kostiuk committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
    func adaptTableToKeyboardState (for tableView: UITableView, with disposeBag: DisposeBag, topOffset: CGFloat? = nil, bottomOffset: CGFloat? = nil) {

        NotificationCenter.keyboardHeight.observeOn(MainScheduler.instance).subscribe(onNext: { [unowned self, unowned tableView] (height) in
            let trueHeight = height > 0  ? height + 100 : 0.0
            // reset insets if they were changed before
            if tableView.contentInset.bottom > 0  && trueHeight <= 0  {
                var contentInsets = tableView.contentInset
                contentInsets.bottom = 0
                tableView.contentInset = contentInsets
                if let topOffset = topOffset {
                    var contentOffset = tableView.contentOffset
                    contentOffset.y = -topOffset
                    tableView.setContentOffset(contentOffset, animated: false)
                }
            }
            if let activeFieldRowPath = self.findPathWithActiveTextField(in: tableView), let cell = tableView.cellForRow(at: activeFieldRowPath) {
                var contentInsets = tableView.contentInset
                if trueHeight > 0 {
                    contentInsets.bottom += height
                    tableView.contentInset = contentInsets
                }
                var aRect = self.view.frame
                aRect.size.height -= trueHeight
                if !aRect.contains(cell.frame.origin) {
                    tableView.scrollToRow(at: activeFieldRowPath, at: .top, animated: true)
                }
            }

        }).disposed(by: disposeBag)
    }

129
    func configureRingNavigationBar() {
Quentin Muret's avatar
Quentin Muret committed
130
        self.navigationController?.navigationBar.barTintColor = UIColor.jamiNavigationBar
131 132 133 134 135
        self.navigationController?.navigationBar.layer.shadowColor = UIColor.black.cgColor
        self.navigationController?.navigationBar.layer.shadowOffset = CGSize(width: 0.0, height: 2.5)
        self.navigationController?.navigationBar.layer.shadowOpacity = 0.2
        self.navigationController?.navigationBar.layer.shadowRadius = 3
        self.navigationController?.navigationBar.layer.masksToBounds = false
136 137
        self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
        self.navigationController?.navigationBar.shadowImage = UIImage()
Quentin Muret's avatar
Quentin Muret committed
138
        let textAttributes = [NSAttributedStringKey.foregroundColor: UIColor.jamiMain]
139
        self.navigationController?.navigationBar.titleTextAttributes = textAttributes
Quentin Muret's avatar
Quentin Muret committed
140
        self.navigationController?.navigationBar.tintColor = UIColor.jamiMain
141
    }
142
}