From cea0925672ef328659eb7ffb743f5fe42a500ff8 Mon Sep 17 00:00:00 2001 From: Dibya Malla Date: Sun, 19 Mar 2023 21:57:15 +0545 Subject: [PATCH] [Update] Slider in home screen --- GME Remit.xcodeproj/project.pbxproj | 12 + GME Remit/Extensions/String+Ext.swift | 11 + .../View/Cell/CarouselCell.swift | 67 ++++++ .../View/Custom/HomeCarouselView.swift | 207 ++++++++++++++++++ .../View/Custom/HomeExchangeRateView.swift | 51 ++++- .../Home/User Interface/View/Home.storyboard | 2 +- .../View/HomeViewController.swift | 14 +- .../exchangeRateButton.imageset/Contents.json | 21 ++ .../exchangeRateButton.svg | 10 + .../CustomUI/CustomPageControl.swift | 130 +++++++++++ .../Utilities/ExchangeRateCustomView.swift | 9 + 11 files changed, 530 insertions(+), 4 deletions(-) create mode 100644 GME Remit/Modules/Home/User Interface/View/Cell/CarouselCell.swift create mode 100644 GME Remit/Modules/Home/User Interface/View/Custom/HomeCarouselView.swift create mode 100644 GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/Contents.json create mode 100644 GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/exchangeRateButton.svg create mode 100644 GME Remit/Utilities/CustomUI/CustomPageControl.swift diff --git a/GME Remit.xcodeproj/project.pbxproj b/GME Remit.xcodeproj/project.pbxproj index 2e029c12..0ca2acef 100644 --- a/GME Remit.xcodeproj/project.pbxproj +++ b/GME Remit.xcodeproj/project.pbxproj @@ -44,6 +44,9 @@ 2454866D29BA2AE60065E1DD /* volte-lightitalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866329BA2AE60065E1DD /* volte-lightitalic.otf */; }; 2454866E29BA2AE60065E1DD /* volte-semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866429BA2AE60065E1DD /* volte-semibold.otf */; }; 2454866F29BA2AE60065E1DD /* volte-regularitalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866529BA2AE60065E1DD /* volte-regularitalic.otf */; }; + 247222DE29C7419800732E55 /* HomeCarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247222DD29C7419800732E55 /* HomeCarouselView.swift */; }; + 247222E029C7425700732E55 /* CarouselCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247222DF29C7425700732E55 /* CarouselCell.swift */; }; + 247222E529C74AE600732E55 /* CustomPageControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247222E429C74AE600732E55 /* CustomPageControl.swift */; }; 247A601629B4428500922B7F /* CustomTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247A601529B4428500922B7F /* CustomTabBar.swift */; }; 24A4502029B831EF0049CE29 /* HomeExchangeRateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A4501F29B831EF0049CE29 /* HomeExchangeRateView.swift */; }; 24A4502229B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A4502129B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift */; }; @@ -878,6 +881,9 @@ 2454866329BA2AE60065E1DD /* volte-lightitalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-lightitalic.otf"; sourceTree = ""; }; 2454866429BA2AE60065E1DD /* volte-semibold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-semibold.otf"; sourceTree = ""; }; 2454866529BA2AE60065E1DD /* volte-regularitalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-regularitalic.otf"; sourceTree = ""; }; + 247222DD29C7419800732E55 /* HomeCarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCarouselView.swift; sourceTree = ""; }; + 247222DF29C7425700732E55 /* CarouselCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselCell.swift; sourceTree = ""; }; + 247222E429C74AE600732E55 /* CustomPageControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomPageControl.swift; sourceTree = ""; }; 247A601529B4428500922B7F /* CustomTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTabBar.swift; sourceTree = ""; }; 24A4501F29B831EF0049CE29 /* HomeExchangeRateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeExchangeRateView.swift; sourceTree = ""; }; 24A4502129B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeExchangeRateCollectionViewCell.swift; sourceTree = ""; }; @@ -1847,6 +1853,7 @@ children = ( 244C69B629B7A01600D7B69A /* HomeAccountDetailView.swift */, 24A4501F29B831EF0049CE29 /* HomeExchangeRateView.swift */, + 247222DD29C7419800732E55 /* HomeCarouselView.swift */, ); path = Custom; sourceTree = ""; @@ -3333,6 +3340,7 @@ 7384B27F22CB375400DD04D9 /* GMEAlert */, 4099AF0025235C45003FA012 /* CircleBorderedView.swift */, 4073BA9125295F5B0043258E /* GradientView.swift */, + 247222E429C74AE600732E55 /* CustomPageControl.swift */, ); path = CustomUI; sourceTree = ""; @@ -6083,6 +6091,7 @@ D9AFE855215C7166005F3A25 /* HomeCollectionTableViewCell.swift */, D923EBB8215C7421008A3026 /* HomeCollectionCollectionViewCell.swift */, 24A4502129B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift */, + 247222DF29C7425700732E55 /* CarouselCell.swift */, ); path = Cell; sourceTree = ""; @@ -7653,6 +7662,7 @@ D95B5E4121311057000C0B33 /* GmeContactsViewInterface.swift in Sources */, 73157BA022DC1EEC009B836F /* PopupNotificationPresenter.swift in Sources */, 73157BA322DC1EEC009B836F /* PopupNotificationViewInterface.swift in Sources */, + 247222DE29C7419800732E55 /* HomeCarouselView.swift in Sources */, 7388A6D822E17F9400A57891 /* CountryEnum.swift in Sources */, D97785A6215DC55F00754079 /* TransactionHistoryViewController.swift in Sources */, 40218EFB24D2B1940047FBF5 /* UserRegistrationInteractor.swift in Sources */, @@ -7721,6 +7731,7 @@ 73FBBF2C23F231A8009D7627 /* DetailNotificationViewController.swift in Sources */, D9DC107A21639078008F3C51 /* MessageComposeService.swift in Sources */, 7EDBFBFE24B3031B00AD5D4D /* WithdrawFromWalletModuleInterface.swift in Sources */, + 247222E029C7425700732E55 /* CarouselCell.swift in Sources */, 73FBBF2623F231A8009D7627 /* DetailNotificationInteractor.swift in Sources */, 28AB139B28E552C200191695 /* NotificationDetailViewController.swift in Sources */, D96A4FD521460B4A00CFD507 /* SplashScreenService.swift in Sources */, @@ -8151,6 +8162,7 @@ 7318534E230EACA400BA9AE3 /* SendMoneyTransFerReasonViewModel.swift in Sources */, 281EF60528ACCC4D0092E5E6 /* HowToDepositPresenter.swift in Sources */, 73195ABB22FD14D500151434 /* SetupRecipientViewModelInterface.swift in Sources */, + 247222E529C74AE600732E55 /* CustomPageControl.swift in Sources */, 7389601922C2FADD003FEA90 /* TableCell.swift in Sources */, D92B802A2140C3CB00A25B26 /* MainPresenter.swift in Sources */, 738714B4237CE86E0038FCB1 /* InboundReceiptServiceType.swift in Sources */, diff --git a/GME Remit/Extensions/String+Ext.swift b/GME Remit/Extensions/String+Ext.swift index 6883f919..0fa8b05b 100644 --- a/GME Remit/Extensions/String+Ext.swift +++ b/GME Remit/Extensions/String+Ext.swift @@ -7,6 +7,7 @@ // import Foundation +import UIKit enum CurrencyType { case usd @@ -128,3 +129,13 @@ extension String{ return predicate.evaluate(with: self) } } + +extension String { + func attributedText(color: UIColor, font: UIFont) -> NSMutableAttributedString { + let range = (self as NSString).range(of: self) + let attributedString = NSMutableAttributedString(string:self) + attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range) + attributedString.addAttribute(NSAttributedString.Key.font, value: font, range: range) + return attributedString + } +} diff --git a/GME Remit/Modules/Home/User Interface/View/Cell/CarouselCell.swift b/GME Remit/Modules/Home/User Interface/View/Cell/CarouselCell.swift new file mode 100644 index 00000000..85acce94 --- /dev/null +++ b/GME Remit/Modules/Home/User Interface/View/Cell/CarouselCell.swift @@ -0,0 +1,67 @@ +// + +import Foundation +import UIKit +import SDWebImage + + +class CarouselCollectionCell: UICollectionViewCell{ + + static let identifier: String = "CarouselCollectionCellID" + + private let backgroundImgView: UIImageView = { + let view = UIImageView() + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private let containerView: UIView = { + let view = UIView() + view.backgroundColor = .clear + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + + private let titleLabel: UILabel = { + let view = UILabel() + view.font = UIFont.sanfrancisco(.bold, size: 21) + view.textColor = .themeWhite + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + private func setup(){ + containerView.backgroundColor = .blue + containerView.layer.cornerRadius = 10 + containerView.clipsToBounds = true + + contentView.addSubview(containerView) + containerView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true + containerView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true + containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16).isActive = true + containerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16).isActive = true + + containerView.addSubview(backgroundImgView) + backgroundImgView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true + backgroundImgView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true + backgroundImgView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true + backgroundImgView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true + + } + + func update(_ event: String){ + DispatchQueue.main.async { + //let imageUrl = UrlManager.sharedInstance.baseImageUrl + "/" + "\(event.imageUrl ?? "")" + self.backgroundImgView.sd_setImage(with: URL(string: event), placeholderImage: UIImage(named: "flag_bahamas")) + } + } +} diff --git a/GME Remit/Modules/Home/User Interface/View/Custom/HomeCarouselView.swift b/GME Remit/Modules/Home/User Interface/View/Custom/HomeCarouselView.swift new file mode 100644 index 00000000..fa918817 --- /dev/null +++ b/GME Remit/Modules/Home/User Interface/View/Custom/HomeCarouselView.swift @@ -0,0 +1,207 @@ +// + +import Foundation +import UIKit + +class HomeCarouselView: UIView { + + private var events: [String] = [] + private var timer: Timer? + + private let collectionView: UICollectionView = { + let flowlayout = UICollectionViewFlowLayout() + flowlayout.scrollDirection = .horizontal + + let view = UICollectionView(frame: CGRect.zero, collectionViewLayout: flowlayout) + view.register(CarouselCollectionCell.self, forCellWithReuseIdentifier: CarouselCollectionCell.identifier) + view.backgroundColor = .white + view.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) + view.showsHorizontalScrollIndicator = false + view.translatesAutoresizingMaskIntoConstraints = false + view.isPagingEnabled = true + return view + }() + + private let pageControl: CustomPageControl = { + let view = CustomPageControl(frame: .zero) + view.currentPageIndicatorTintColor = .theme2E89FF + view.pageIndicatorTintColor = .themeGray2 + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + static let identifier: String = "HomeCarouselCellID" + + /// whether or not dragging has ended + fileprivate var endDragging = false + + /// the current page + @objc open dynamic var currentIndex: Int = 0 { + didSet { + updateAccessoryViews() + } + } + + + func updateAccessoryViews() { + pageControl.currentPage = currentIndex + + } + + + override init(frame: CGRect) { + super.init(frame: .zero) + setup() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + + private func setup(){ + self.backgroundColor = .themeWhite + self.addSubview(pageControl) + pageControl.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true + pageControl.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true + pageControl.heightAnchor.constraint(equalToConstant: 30).isActive = true + + self.addSubview(collectionView) + collectionView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true + collectionView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true + collectionView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true + collectionView.bottomAnchor.constraint(equalTo: pageControl.topAnchor, constant: 0).isActive = true + + collectionView.delegate = self + collectionView.dataSource = self + } + + override open func layoutSubviews() { + super.layoutSubviews() + collectionView.performBatchUpdates(nil, completion: nil) + moveToPage(currentIndex, animated: false) + } + + open func moveToPage(_ page: Int, animated: Bool) { + // outside the range + if page < 0 || page >= collectionView.numberOfItems(inSection: 0) { + return + } + + currentIndex = page + collectionView.scrollToItem(at: IndexPath(item: currentIndex, section: 0), + at: .left, animated: animated) + } + + + func update(_ events: [String]){ + self.events = events + pageControl.numberOfPages = events.count + self.collectionView.reloadData() + stopTimer() + startTimer() + } + + + /** + Scroll to Next Cell + */ + @objc func scrollToNextCell(){ + let nextpage = self.currentIndex + 1 + if nextpage >= self.events.count{ + moveToPage(0, animated: true) + }else{ + moveToPage(nextpage, animated: true) + } + } + + /** + Invokes Timer to start Automatic Animation with repeat enabled + */ + private func startTimer() { + self.timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(self.scrollToNextCell), userInfo: nil, repeats: true) + } + + private func stopTimer(){ + self.timer?.invalidate() + self.timer = nil + } + +} + +//MARK:- UICollectionViewDelegate +extension HomeCarouselView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{ + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CarouselCollectionCell.identifier, for: indexPath) as! CarouselCollectionCell + cell.update(self.events[indexPath.row]) + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return self.events.count + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + return CGSize(width: collectionView.frame.width, height: collectionView.frame.height) + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + return 0.001 + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { + return 0.001 + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + //self.didSelect?(self.events[indexPath.row]) + } + + + /** + size of the collection view + - parameter collectionView: the collection view + - parameter collectionViewLayout: the collection view flow layout + - parameter indexPath: the index path + */ + // public func collectionView(_ collectionView: UICollectionView, + // layout collectionViewLayout: UICollectionViewLayout, + // sizeForItemAt indexPath: IndexPath) -> CGSize { + // return collectionView.bounds.size + // } + + /** + scroll view did end dragging + - parameter scrollView: the scroll view + - parameter decelerate: wether the view is decelerating or not. + */ + public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + if !decelerate { + endScrolling(scrollView) + } else { + endDragging = true + } + } + + /** + Scroll view did end decelerating + */ + public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + if endDragging { + endDragging = false + endScrolling(scrollView) + } + } + + /** + end scrolling + */ + fileprivate func endScrolling(_ scrollView: UIScrollView) { + let width = scrollView.bounds.width + let page = (scrollView.contentOffset.x + (0.5 * width)) / width + currentIndex = Int(page) + self.stopTimer() + self.startTimer() + } +} diff --git a/GME Remit/Modules/Home/User Interface/View/Custom/HomeExchangeRateView.swift b/GME Remit/Modules/Home/User Interface/View/Custom/HomeExchangeRateView.swift index 17111d81..0da4f801 100644 --- a/GME Remit/Modules/Home/User Interface/View/Custom/HomeExchangeRateView.swift +++ b/GME Remit/Modules/Home/User Interface/View/Custom/HomeExchangeRateView.swift @@ -75,6 +75,14 @@ class HomeExchangeRateView: UIView { return button }() + private let exchangeButton: UIButton = { + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.heightAnchor.constraint(equalToConstant: 32).isActive = true + button.widthAnchor.constraint(equalToConstant: 32).isActive = true + return button + }() + //exRate private var transferFeeIncluded: UIStackView! @@ -140,6 +148,7 @@ class HomeExchangeRateView: UIView { containerView.addSubviews(collectionView, sendMoneyView, + exchangeButton, recivedMoneyView, transferFeeIncluded, guranteedView, @@ -172,6 +181,14 @@ class HomeExchangeRateView: UIView { paddingRight: 0 ) + exchangeButton.anchor(top: sendMoneyView.bottomAnchor, + paddingTop: -8, + bottom: recivedMoneyView.topAnchor, + paddingBottom: 8, + left: sendMoneyView.leadingAnchor, + paddingLeft: 16) + + transferFeeIncluded.anchor( top: recivedMoneyView.bottomAnchor, paddingTop: 16, @@ -221,6 +238,14 @@ class HomeExchangeRateView: UIView { recivedMoneyView.set(borderWidth: 2, of: .black) recivedMoneyView.set(cornerRadius: 10) recivedMoneyView.title = "receipient_gets_text".localized() + + exchangeButton.setTitle("", for: .normal) + exchangeButton.setImage(UIImage(named: "exchangeRateButton"), for: .normal) + exchangeButton.layer.cornerRadius = 10 + exchangeButton.backgroundColor = .themeGray1 + exchangeButton.layer.borderWidth = 2 + exchangeButton.layer.borderColor = UIColor.black.cgColor + } func textChanged() { @@ -249,11 +274,35 @@ class HomeExchangeRateView: UIView { func set(_ model: ExchangeRateDetailModel?) { guard let model = model else { - return + return } sendMoneyView.updatedText = model.senderAmount?.likeCommaMoney() recivedMoneyView.updatedText = model.recipientAmount?.likeCommaMoney() + + let transferFee = ("\(model.transferFee?.likeCommaMoney() ?? "" ) JPY ") + .attributedText(color: .themeBlack, font: .sanfrancisco(.semibold, size: 14)) + + let transferInfo = "transfer_fee_included_text".localized().attributedText(color: .theme2E89FF, font: .sanfrancisco(.semibold, size: 14)) + + let transfer = NSMutableAttributedString() + + transfer.append(transferFee) + transfer.append(transferInfo) + + transferFeeIncludedText.attributedText = transfer + + let exchangeRate = model.exchangeRate ?? "" + let exchangeRateAttributed = ("1000 JPY = \(exchangeRate) \(selectedExchangeRateModel?.currency ?? "") ").attributedText(color: .themeBlack, font: .sanfrancisco(.semibold, size: 14)) + + let exchangeRateInfo = ("Guranteed rate for 24 hr").attributedText(color: .theme2E89FF, font: .sanfrancisco(.semibold, size: 14)) + + let gurrantedText = NSMutableAttributedString() + + gurrantedText.append(exchangeRateAttributed) + gurrantedText.append(exchangeRateInfo) + + guranteedRateText.attributedText = gurrantedText } func set(_ model: ExchangeRateModel?) { diff --git a/GME Remit/Modules/Home/User Interface/View/Home.storyboard b/GME Remit/Modules/Home/User Interface/View/Home.storyboard index 06495622..a06fb000 100644 --- a/GME Remit/Modules/Home/User Interface/View/Home.storyboard +++ b/GME Remit/Modules/Home/User Interface/View/Home.storyboard @@ -239,7 +239,7 @@ - + diff --git a/GME Remit/Modules/Home/User Interface/View/HomeViewController.swift b/GME Remit/Modules/Home/User Interface/View/HomeViewController.swift index ac2ea6e9..18ead263 100644 --- a/GME Remit/Modules/Home/User Interface/View/HomeViewController.swift +++ b/GME Remit/Modules/Home/User Interface/View/HomeViewController.swift @@ -46,7 +46,14 @@ class HomeViewController: UIViewController { view.translatesAutoresizingMaskIntoConstraints = false return view }() - + + private let homeCarouselView: HomeCarouselView = { + let view = HomeCarouselView() + view.translatesAutoresizingMaskIntoConstraints = false + view.heightAnchor.constraint(equalToConstant: 132).isActive = true + return view + }() + @IBOutlet weak var accountDetailView: UIView! @IBOutlet weak var notificationItem: UIBarButtonItem! @@ -321,6 +328,8 @@ class HomeViewController: UIViewController { stackView.translatesAutoresizingMaskIntoConstraints = false stackView.addArrangedSubview(exchangeRateView) + stackView.addArrangedSubview(homeCarouselView) + exchangeRateView.openCountryList = { [weak self] in self?.showCountryList() } @@ -428,7 +437,7 @@ class HomeViewController: UIViewController { walletNumberLabel.text = walletNumber == "" ? "N/A" : walletNumber copyButton.setTitle("", for: .normal) mainContainerView.setupCornerRadius(20,maskedCorners: [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]) - userName.title = "HI" + " " + (GMEDB.shared.user.string(.userId) ?? "") + userName.title = " HI Rabin"//"HI" + " " + (GMEDB.shared.user.string(.userId) ?? "") } private func configureText() { @@ -760,6 +769,7 @@ extension HomeViewController: HomeViewInterface { func setModel(with model: ExchangeRateDetailModel?) { self.exchangeRateDetailModel = model self.exchangeRateView.set(model) + self.homeCarouselView.update(["test1", "test2", "test3671"]) //reload(0, Sections.collection.rawValue) } diff --git a/GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/Contents.json b/GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/Contents.json new file mode 100644 index 00000000..c210966e --- /dev/null +++ b/GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "exchangeRateButton.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/exchangeRateButton.svg b/GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/exchangeRateButton.svg new file mode 100644 index 00000000..a8f04c9b --- /dev/null +++ b/GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/exchangeRateButton.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/GME Remit/Utilities/CustomUI/CustomPageControl.swift b/GME Remit/Utilities/CustomUI/CustomPageControl.swift new file mode 100644 index 00000000..fe384c8f --- /dev/null +++ b/GME Remit/Utilities/CustomUI/CustomPageControl.swift @@ -0,0 +1,130 @@ +// + +import Foundation +import UIKit + +@IBDesignable +class CustomPageControl: UIControl { + //MARK:- Properties + + private var numberOfDots = [UIView]() { + didSet{ + if numberOfDots.count == numberOfPages { + setupViews() + } + } + } + + @IBInspectable var numberOfPages: Int = 0 { + didSet{ + + for tag in 0 ..< numberOfPages { + let dot = getDotView() + dot.tag = tag + dot.backgroundColor = pageIndicatorTintColor + self.numberOfDots.append(dot) + } + } + } + + var currentPage: Int = 0 { + didSet{ + onPageControlSwipe() + } + } + + @IBInspectable var pageIndicatorTintColor: UIColor? = .blue + @IBInspectable var currentPageIndicatorTintColor: UIColor? = .green + + private lazy var stackView = UIStackView.init(frame: self.bounds) + private lazy var constantSpace = ((stackView.spacing) * CGFloat(numberOfPages - 1) + ((self.bounds.height * 0.45) * CGFloat(numberOfPages)) - self.bounds.width) + + + override var bounds: CGRect { + didSet{ + self.numberOfDots.forEach { (dot) in + self.setupDotAppearance(dot: dot) + } + } + } + + //MARK:- Intialisers + convenience init() { + self.init(frame: .zero) + } + + init(withNoOfPages pages: Int) { + self.numberOfPages = pages + self.currentPage = 0 + super.init(frame: .zero) + setupViews() + } + + override init(frame: CGRect) { + super.init(frame: frame) + setupViews() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + } + private func setupViews() { + + self.numberOfDots.forEach { (dot) in + self.stackView.addArrangedSubview(dot) + } + + stackView.alignment = .center + stackView.axis = .horizontal + stackView.distribution = .fillEqually + stackView.spacing = 8 + stackView.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(stackView) + + self.addConstraints([ + stackView.centerXAnchor.constraint(equalTo: self.centerXAnchor), + stackView.centerYAnchor.constraint(equalTo: self.centerYAnchor), + stackView.heightAnchor.constraint(equalTo: self.heightAnchor), + ]) + + self.numberOfDots.forEach { dot in + self.addConstraints([ + dot.centerYAnchor.constraint(equalTo: self.stackView.centerYAnchor), + dot.widthAnchor.constraint(equalToConstant: 7), + dot.heightAnchor.constraint(equalToConstant: 7), + ]) + } + self.numberOfDots.forEach { dot in + dot.layer.cornerRadius = dot.bounds.height / 2 + } + } + + @objc private func onPageControlSwipe() { + _ = numberOfDots.map { (dot) in + setupDotAppearance(dot: dot) + if dot.tag == currentPage { + UIView.animate(withDuration: 0.2, animations: { + dot.layer.cornerRadius = dot.bounds.height / 5 + dot.transform = CGAffineTransform.init(scaleX: 2, y: 1) + dot.backgroundColor = self.currentPageIndicatorTintColor + }) + } + } + } + + //MARK: Helper methods... + private func getDotView() -> UIView { + let dot = UIView() + self.setupDotAppearance(dot: dot) + dot.translatesAutoresizingMaskIntoConstraints = false + return dot + } + + private func setupDotAppearance(dot: UIView) { + dot.transform = .identity + dot.layer.cornerRadius = dot.bounds.height / 2 + dot.layer.masksToBounds = true + dot.backgroundColor = pageIndicatorTintColor + } +} diff --git a/GME Remit/Utilities/ExchangeRateCustomView.swift b/GME Remit/Utilities/ExchangeRateCustomView.swift index 95217295..691278e3 100644 --- a/GME Remit/Utilities/ExchangeRateCustomView.swift +++ b/GME Remit/Utilities/ExchangeRateCustomView.swift @@ -35,6 +35,7 @@ class ExchangeRateCustomView: UIView { private var textfield: CurrencyTextField = { let textfield = CurrencyTextField() + textfield.tintColor = .theme2E89FF textfield.textColor = .init(hex: "#2E89FF").withAlphaComponent(0.87) textfield.font = .sanfrancisco(.semibold, size: 16) textfield.translatesAutoresizingMaskIntoConstraints = false @@ -124,6 +125,9 @@ class ExchangeRateCustomView: UIView { paddingY: 0) rightStackView.leadingAnchor.constraint(greaterThanOrEqualTo: leftStackView.trailingAnchor, constant: 8).isActive = true + + let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))) + leftStackView.addGestureRecognizer(tap) } @@ -136,6 +140,7 @@ class ExchangeRateCustomView: UIView { titleLabel.textColor = .themeBlack.withAlphaComponent(0.6) titleLabel.font = .sanfrancisco(.semibold, size: 14) + if(isReciver) { countryListTapGuesture = UITapGestureRecognizer(target: self, action: #selector(showCurrencyCountryPickerview)) rightStackView.addGestureRecognizer(countryListTapGuesture ?? UITapGestureRecognizer()) @@ -144,6 +149,10 @@ class ExchangeRateCustomView: UIView { } } + @objc func handleTap(_ sender: UITapGestureRecognizer? = nil) { + textfield.becomeFirstResponder() + } + @objc private func showCurrencyCountryPickerview() { didSelectCountry?() }