Alt sayfayı Haritalar uygulamasından nasıl taklit edebilirim?


202

Biri bana iOS 10'daki yeni Haritalar uygulamasındaki alt sayfayı nasıl taklit edebileceğimi söyleyebilir mi?

Android'de bir BottomSheet bu davranışı taklit eden , ancak iOS için böyle bir şey bulamadım.

Bu, içerik çubuğuna sahip basit bir kaydırma görünümüdür, böylece arama çubuğu altta olur mu?

İOS programlamasında oldukça yeniyim, bu yüzden birisi bu düzeni oluşturmama yardımcı olabilirse, bu çok takdir edilecektir.

"Alt sayfa" ile kastettiğim budur:

Haritalar'daki daraltılmış alt sayfanın ekran görüntüsü

Haritalar'daki genişletilmiş alt sayfanın ekran görüntüsü


1
Korkarım kendin inşa etmelisin. Arka plan bulanık görünümüne ve bazı jest tanıyıcılara sahip bir görünümdür.
Khanh Nguyen

@KhanhNguyen evet kendim inşa etmek zorunda olduğumu biliyorum, ama merak ediyorum, bu görünümün arşivlenmesi için hangi görünümlerin kullanıldığı ve nasıl sipariş edildiği vb.
qwertz

Bu görsel efekt görünümü ile bulanıklık efekti. Bu SO sorusuna
Khanh Nguyen

1
Alt görünüme bir kaydırma hareketi tanıyıcı ekleyebilir ve görünümü buna göre hareket ettirebilirsiniz (hareket tanıyıcı olayları arasındaki y koordinatlarını kaydederek ve farkı hesaplayarak).
Khanh Nguyen

2
Sorularınızı beğendim. Böyle bir şey uygulamayı planlıyorum. Birisi bir örnek yazabilseydi iyi olurdu.
wviana

Yanıtlar:


330

Yeni Haritalar uygulamasının alt sayfasının kullanıcı etkileşimlerine nasıl yanıt verdiğini bilmiyorum. Ancak, ekran görüntülerindekine benzeyen özel bir görünüm oluşturabilir ve ana görünüme ekleyebilirsiniz.

Nasıl yapacağınızı bildiğinizi varsayıyorum:

1- hikaye tahtaları veya xib dosyaları kullanarak görünüm denetleyicileri oluşturun.

2- googleMaps veya Apple'ın MapKit'ini kullanın.

Misal

1- MapViewController ve BottomSheetViewController gibi 2 görünüm denetleyicisi oluşturun . İlk denetleyici haritayı barındıracak ve ikincisi alt sayfanın kendisidir.

MapViewController'ı yapılandırın

Alt sayfa görünümünü eklemek için bir yöntem oluşturun.

func addBottomSheetView() {
    // 1- Init bottomSheetVC
    let bottomSheetVC = BottomSheetViewController()

    // 2- Add bottomSheetVC as a child view 
    self.addChildViewController(bottomSheetVC)
    self.view.addSubview(bottomSheetVC.view)
    bottomSheetVC.didMoveToParentViewController(self)

    // 3- Adjust bottomSheet frame and initial position.
    let height = view.frame.height
    let width  = view.frame.width
    bottomSheetVC.view.frame = CGRectMake(0, self.view.frame.maxY, width, height)
}

Ve viewDidAppear yönteminde çağırın:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    addBottomSheetView()
}

BottomSheetViewController'ı yapılandırma

1) Arka plan hazırlayın

Bulanıklık ve canlılık efektleri eklemek için bir yöntem oluşturun

func prepareBackgroundView(){
    let blurEffect = UIBlurEffect.init(style: .Dark)
    let visualEffect = UIVisualEffectView.init(effect: blurEffect)
    let bluredView = UIVisualEffectView.init(effect: blurEffect)
    bluredView.contentView.addSubview(visualEffect)

    visualEffect.frame = UIScreen.mainScreen().bounds
    bluredView.frame = UIScreen.mainScreen().bounds

    view.insertSubview(bluredView, atIndex: 0)
}

görünümünüzde bu yöntemi çağırın

override func viewWillAppear(animated: Bool) {
   super.viewWillAppear(animated)
   prepareBackgroundView()
}

Denetleyicinizin görünüm arka plan renginin açık olduğundan emin olunColor.

2) Alt sayfa canlandırın

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    UIView.animateWithDuration(0.3) { [weak self] in
        let frame = self?.view.frame
        let yComponent = UIScreen.mainScreen().bounds.height - 200
        self?.view.frame = CGRectMake(0, yComponent, frame!.width, frame!.height)
    }
}

3) xib'inizi istediğiniz gibi değiştirin.

4) Görünümünüze Pan Hareket Tanıyıcı ekleyin.

ViewDidLoad yönteminizde UIPanGestureRecognizer öğesini ekleyin.

override func viewDidLoad() {
    super.viewDidLoad()

    let gesture = UIPanGestureRecognizer.init(target: self, action: #selector(BottomSheetViewController.panGesture))
    view.addGestureRecognizer(gesture)

}

Ve jest davranışınızı uygulayın:

func panGesture(recognizer: UIPanGestureRecognizer) {
    let translation = recognizer.translationInView(self.view)
    let y = self.view.frame.minY
    self.view.frame = CGRectMake(0, y + translation.y, view.frame.width, view.frame.height)
     recognizer.setTranslation(CGPointZero, inView: self.view)
}

Kaydırılabilir Alt Tabaka:

Özel görünümünüz bir kaydırma görünümü veya devralınan başka bir görünümse, iki seçeneğiniz vardır:

İlk:

Üstbilgi görünümü ile görünümü tasarlayın ve panGesture öğesini üstbilgiye ekleyin. (kötü kullanıcı deneyimi) .

İkinci:

1 - panGesture'u alt sayfa görünümüne ekleyin.

2 - UIGestureRecognizerDelegate'i uygulayın ve panGesture temsilcisini denetleyiciye ayarlayın.

Uygulama 3- shouldRecognizeSimultaneouslyWith temsilci fonksiyonu ve devre dışı scrollview isScrollEnabled iki durumda özelliği:

  • Görünüm kısmen görülebilir.
  • Görünüm tamamen görünür, scrollView contentOffset özelliği 0'dır ve kullanıcı görünümü aşağı doğru sürükler.

Aksi takdirde kaydırmayı etkinleştirin.

  func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
      let gesture = (gestureRecognizer as! UIPanGestureRecognizer)
      let direction = gesture.velocity(in: view).y

      let y = view.frame.minY
      if (y == fullView && tableView.contentOffset.y == 0 && direction > 0) || (y == partialView) {
          tableView.isScrollEnabled = false
      } else {
        tableView.isScrollEnabled = true
      }

      return false
  }

NOT

.AllowUserInteraction öğesini örnek projede olduğu gibi bir animasyon seçeneği olarak ayarlamanız durumunda, kullanıcı yukarı kaydırıyorsa animasyon tamamlama kapanışında kaydırmayı etkinleştirmeniz gerekir.

Örnek Proje

Bu repoda, akışın nasıl özelleştirileceği hakkında daha iyi bilgiler verebilecek daha fazla seçenek içeren örnek bir proje oluşturdum .

Demoda, addBottomSheetView () işlevi, alt görünüm olarak hangi görünümün kullanılması gerektiğini denetler.

Örnek Proje Ekran Görüntüleri

- Kısmi görüntü

resim açıklamasını buraya girin

- Tam görüntü

resim açıklamasını buraya girin

- Kaydırılabilir Görüntü

resim açıklamasını buraya girin


3
Bu aslında childViews ve subViews için iyi bir öğreticidir. Teşekkür ederim :)
Edison

@AhmedElassuty nasıl xib içinde tableview ekleyebilir ve alt tabaka olarak yükleyebilirim? Eğer yardımcı olabilirseniz harika olurdu Şimdiden teşekkürler!
nikhil nangia

3
@nikhilnangia Ben sadece bir tableView içeren başka bir viewController "ScrollableBottomSheetViewController.swift" ile güncelledi. Cevabı en kısa zamanda güncelleyeceğim. Bunu da kontrol et github.com/AhmedElassuty/IOS-BottomSheet/issues/1
Ahmad Elassuty

12
Apple Maps alt sayfasının, sayfa sürükleme hareketinden kaydırma görünümü kaydırma hareketine tek bir hareketle geçiş yaptığını fark ettim, yani kullanıcının görünümü kaydırmaya başlamak için bir hareketi durdurması ve yeni bir hareket başlatması gerekmez. Örneğiniz bunu yapmıyor. Bunun nasıl başarılabileceği hakkında düşünceleriniz var mı? Teşekkür ve bir repo örnek göndermek için teşekkür bir ton!
Stoph

2
@ RafaelaLourenço Cevabımı faydalı bulduğunuz için çok mutluyum! Teşekkür ederim!
Ahmad Elassuty,

56

Bir kütüphane yayınladımAşağıdaki cevabım temelinde .

Kısayollar uygulama katmanını taklit eder. Bkz bu yazıyı bakın.

Kütüphanenin ana bileşeni OverlayContainerViewController. Bir görünüm denetleyicisinin altındaki içeriği gizleyerek veya göstererek aşağı ve yukarı sürüklenebileceği bir alan tanımlar.

let contentController = MapsViewController()
let overlayController = SearchViewController()

let containerController = OverlayContainerViewController()
containerController.delegate = self
containerController.viewControllers = [
    contentController,
    overlayController
]

window?.rootViewController = containerController

OverlayContainerViewControllerDelegateİstenen çentik sayısını belirtmek için uygulayın :

enum OverlayNotch: Int, CaseIterable {
    case minimum, medium, maximum
}

func numberOfNotches(in containerViewController: OverlayContainerViewController) -> Int {
    return OverlayNotch.allCases.count
}

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    heightForNotchAt index: Int,
                                    availableSpace: CGFloat) -> CGFloat {
    switch OverlayNotch.allCases[index] {
        case .maximum:
            return availableSpace * 3 / 4
        case .medium:
            return availableSpace / 2
        case .minimum:
            return availableSpace * 1 / 4
    }
}

Önceki cevap

Önerilen çözümlerde ele alınmayan önemli bir nokta olduğunu düşünüyorum: kaydırma ve çeviri arasındaki geçiş.

Haritalar kaydırma ve çeviri arasındaki geçiş

Haritalar'da, fark etmiş olabileceğiniz gibi, tableView ulaştığında contentOffset.y == 0 , alt sayfa yukarı kayar veya aşağı iner.

Nokta zordur, çünkü kaydırma hareketimiz çeviriyi başlattığında kaydırma işlemini etkinleştiremez / devre dışı bırakamazız. Yeni bir dokunuş başlayana kadar kaydırma durur. Burada önerilen çözümlerin çoğunda durum böyledir.

İşte bu hareketi uygulamaya çalışıyorum.

Başlangıç ​​noktası: Haritalar Uygulaması

Soruşturmayı başlatmak için, hadi Maps görünüm hiyerarşisi görselleştirmek (bir simülatörde Maps başlatmak ve seçmek Debug> Attach to process by PID or Name> MapsXcode 9'da).

Google Haritalar hata ayıklama görünümü hiyerarşisi

Hareketin nasıl işlediğini söylemiyor, ama onun mantığını anlamama yardımcı oldu. Lldb ve görünüm hiyerarşisi hata ayıklayıcısı ile oynayabilirsiniz.

Görünüm denetleyici yığınlarımız

Maps ViewController mimarisinin temel bir sürümünü oluşturalım.

Bir BackgroundViewController(harita görünümümüz) ile başlıyoruz :

class BackgroundViewController: UIViewController {
    override func loadView() {
        view = MKMapView()
    }
}

TableView öğesini özel bir alana koyduk UIViewController:

class OverlayViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    lazy var tableView = UITableView()

    override func loadView() {
        view = tableView
        tableView.dataSource = self
        tableView.delegate = self
    }

    [...]
}

Şimdi kaplamayı yerleştirmek ve çevirisini yönetmek için bir VC'ye ihtiyacımız var. Sorunu basitleştirmek için, bindirmeyi bir statik noktadan OverlayPosition.maximumdiğerine çevirebileceğini düşünüyoruzOverlayPosition.minimum .

Şimdilik, pozisyon değişikliğini canlandırmak için sadece bir genel yöntemi var ve şeffaf bir görünüme sahip:

enum OverlayPosition {
    case maximum, minimum
}

class OverlayContainerViewController: UIViewController {

    let overlayViewController: OverlayViewController
    var translatedViewHeightContraint = ...

    override func loadView() {
        view = UIView()
    }

    func moveOverlay(to position: OverlayPosition) {
        [...]
    }
}

Son olarak, hepsini gömmek için bir ViewController'a ihtiyacımız var:

class StackViewController: UIViewController {

    private var viewControllers: [UIViewController]

    override func viewDidLoad() {
        super.viewDidLoad()
        viewControllers.forEach { gz_addChild($0, in: view) }
    }
}

AppDelegate'imizde başlangıç ​​dizimiz şöyle:

let overlay = OverlayViewController()
let containerViewController = OverlayContainerViewController(overlayViewController: overlay)
let backgroundViewController = BackgroundViewController()
window?.rootViewController = StackViewController(viewControllers: [backgroundViewController, containerViewController])

Yer paylaşımlı çevirinin arkasındaki zorluk

Şimdi, bindirmemizi nasıl çevirebiliriz?

Önerilen çözümlerin çoğunda özel bir pan jest tanıyıcı kullanılır, ancak aslında zaten bir tane var: tablo görünümünün pan hareketi. Dahası, kaydırma ve çeviriyi senkronize tutmamız gerekiyor ve ihtiyacımız olan UIScrollViewDelegatetüm olaylar var!

Saf bir uygulama ikinci bir kaydırma hareketi contentOffsetkullanır ve çeviri gerçekleştiğinde tablo görünümünü sıfırlamaya çalışır :

func panGestureAction(_ recognizer: UIPanGestureRecognizer) {
    if isTranslating {
        tableView.contentOffset = .zero
    }
}

Ama bu çalışmıyor. TableView onun günceller contentOffsetzaman kendi tava jest tanıyıcı eylem tetikler veya DisplayLink geri arama çağrıldığında. Tanıyıcımızın başarılı bir şekilde geçersiz kılma işleminden hemen sonra tetikleme şansı yoktur contentOffset. Tek şansımız ya yerleşim aşamasının bir parçası olmak ( layoutSubviewskaydırma görünümünün her karesinde kaydırma görünümü çağrılarını geçersiz kılmak suretiyle) ya da didScrollher contentOffsetdeğiştirildiğinde çağrılan temsilci yöntemine yanıt vermektir. Bunu deneyelim.

Çeviri Uygulaması

OverlayVCScrollview'ın olaylarını çeviri işleyicimize göndermek için bir temsilci ekliyoruz OverlayContainerViewController:

protocol OverlayViewControllerDelegate: class {
    func scrollViewDidScroll(_ scrollView: UIScrollView)
    func scrollViewDidStopScrolling(_ scrollView: UIScrollView)
}

class OverlayViewController: UIViewController {

    [...]

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        delegate?.scrollViewDidScroll(scrollView)
    }

    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        delegate?.scrollViewDidStopScrolling(scrollView)
    }
}

Konteynırımızda çeviriyi bir numaralandırma kullanarak takip ediyoruz:

enum OverlayInFlightPosition {
    case minimum
    case maximum
    case progressing
}

Mevcut konum hesaplaması aşağıdaki gibidir:

private var overlayInFlightPosition: OverlayInFlightPosition {
    let height = translatedViewHeightContraint.constant
    if height == maximumHeight {
        return .maximum
    } else if height == minimumHeight {
        return .minimum
    } else {
        return .progressing
    }
}

Çeviriyi ele almak için 3 yönteme ihtiyacımız var:

İlki bize çeviriye başlamamız gerekip gerekmediğini söyler.

private func shouldTranslateView(following scrollView: UIScrollView) -> Bool {
    guard scrollView.isTracking else { return false }
    let offset = scrollView.contentOffset.y
    switch overlayInFlightPosition {
    case .maximum:
        return offset < 0
    case .minimum:
        return offset > 0
    case .progressing:
        return true
    }
}

İkincisi çeviriyi yapar. translation(in:)ScrollView'in pan hareketinin yöntemini kullanır .

private func translateView(following scrollView: UIScrollView) {
    scrollView.contentOffset = .zero
    let translation = translatedViewTargetHeight - scrollView.panGestureRecognizer.translation(in: view).y
    translatedViewHeightContraint.constant = max(
        Constant.minimumHeight,
        min(translation, Constant.maximumHeight)
    )
}

Üçüncüsü, kullanıcı parmağını serbest bıraktığında çevirinin sonunu canlandırır. Pozisyonu, görünümün hızını ve mevcut konumunu kullanarak hesaplıyoruz.

private func animateTranslationEnd() {
    let position: OverlayPosition =  // ... calculation based on the current overlay position & velocity
    moveOverlay(to: position)
}

Yer paylaşımımızın delege uygulaması şöyle görünür:

class OverlayContainerViewController: UIViewController {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard shouldTranslateView(following: scrollView) else { return }
        translateView(following: scrollView)
    }

    func scrollViewDidStopScrolling(_ scrollView: UIScrollView) {
        // prevent scroll animation when the translation animation ends
        scrollView.isEnabled = false
        scrollView.isEnabled = true
        animateTranslationEnd()
    }
}

Son sorun: yer paylaşımı kabının dokunuşlarını gönderme

Çeviri artık oldukça etkili. Ancak yine de son bir sorun var: dokunuşlar arka plan görünümümüze sunulmuyor. Bunların hepsi, yer paylaşımı kabının görünümü tarafından engellenir. Biz ayarlayamıyor isUserInteractionEnablediçin falsede bizim tablo görünümünde etkileşimi devre dışı çünkü. Çözüm, Haritalar uygulamasında büyük ölçüde kullanılan çözümdür PassThroughView:

class PassThroughView: UIView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let view = super.hitTest(point, with: event)
        if view == self {
            return nil
        }
        return view
    }
}

Kendini cevaplayıcı zincirinden çıkarır.

İçinde OverlayContainerViewController:

override func loadView() {
    view = PassThroughView()
}

Sonuç

İşte sonuç:

Sonuç

Kodu burada bulabilirsiniz .

Herhangi bir hata görürseniz lütfen bana bildirin! Uygulamanızın, özellikle yer paylaşımınıza bir başlık eklerseniz, ikinci bir kaydırma hareketi kullanabileceğini unutmayın.

Güncelleme 23/08/18

Kullanıcı sürüklemeyi bitirdiğinde / kaydırma yerine / scrollViewDidEndDraggingile değiştirebiliriz :willEndScrollingWithVelocityenablingdisabling

func scrollView(_ scrollView: UIScrollView,
                willEndScrollingWithVelocity velocity: CGPoint,
                targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    switch overlayInFlightPosition {
    case .maximum:
        break
    case .minimum, .progressing:
        targetContentOffset.pointee = .zero
    }
    animateTranslationEnd(following: scrollView)
}

Hareket akışını daha iyi hale getirmek için bir yay animasyonu kullanabilir ve animasyon yaparken kullanıcı etkileşimi sağlayabiliriz:

func moveOverlay(to position: OverlayPosition,
                 duration: TimeInterval,
                 velocity: CGPoint) {
    overlayPosition = position
    translatedViewHeightContraint.constant = translatedViewTargetHeight
    UIView.animate(
        withDuration: duration,
        delay: 0,
        usingSpringWithDamping: velocity.y == 0 ? 1 : 0.6,
        initialSpringVelocity: abs(velocity.y),
        options: [.allowUserInteraction],
        animations: {
            self.view.layoutIfNeeded()
    }, completion: nil)
}

Bu yaklaşım animasyon aşamaları sırasında etkileşimli değildir. Örneğin, Google Haritalar'da sayfayı genişletirken parmağımla yakalayabilirim. Daha sonra yukarı veya aşağı kaydırarak animasyonu fırçalayabilirim. En yakın noktaya geri dönecektir. Bunun UIViewPropertyAnimator(duraklama yeteneğine sahip) kullanılarak çözülebileceğine inanıyorum , daha sonra fractionCompletefırçalamayı gerçekleştirmek için özelliği kullanın.
Ağustos

1
Haklısın @aust. Önceki değişikliğimi zorlamayı unuttum. Şimdi iyi olmalı. Teşekkürler.
GaétanZ

Bu harika bir fikir, ancak bir problemi hemen görebiliyorum. Olarak translateView(following:)yöntem, çeviri göre yüksekliğini hesaplamak ama 0.0 den farklı bir değer başlayabileceğini (örneğin Tablo görünümü biraz kayar ve sürükleme başlangıç paylaşımlı maksimize edilir) . Bu ilk sıçramayla sonuçlanır. Bunu , tablo görünümünün scrollViewWillBeginDraggingbaşlangıcını hatırlayacağınız contentOffsetve translateView(following:)'hesaplamasında kullanabileceğiniz geri arama ile çözebilirsiniz .
Jakub Truhlář

1
@ GaétanZ Simülatörde Maps.app'a hata ayıklayıcı eklemekle de ilgileniyordum, ancak "Pid'e eklenemedi:" 9276 "" ve ardından "Haritalar" ın çalışmadığından emin olun ve <kullanıcı adı> hata ayıkla. " - Xcode'u Maps.app'a eklenmesine izin vermek için nasıl kandırdın?
mat

1
@matm @ GaétanZ benim için Xcode 10.1 / Mojave'de çalıştı -> Sistem Bütünlüğü Korumasını (SIP) devre dışı bırakmak için devre dışı bırakmanız yeterli. Yapmanız gerekenler: 1) Mac'inizi yeniden başlatın; 2) cmd + R tuşlarını basılı tutun; 3) Menüden Yardımcı Programlar ve ardından Terminal; 4) Terminal penceresi türünde: csrutil disable && reboot. Daha sonra, bir Apple işlemine ekleme yapabilmeniz de dahil olmak üzere, kökün normalde size vermesi gereken tüm güçlere sahip olacaksınız.
valdyr

18

Kasnak deneyin :

Kasnak, iOS 10'un Haritalar uygulamasında çekmeceyi taklit etmek için kullanımı kolay bir çekmece kütüphanesidir. Herhangi bir UIViewController alt sınıfını çekmece içeriği veya birincil içerik olarak kullanmanızı sağlayan basit bir API ortaya koyar.

Pulley Önizleme

https://github.com/52inc/Pulley


1
Temel listede kaydırmayı destekliyor mu?
Richard Lindhout

@RichardLindhout - Demoyu çalıştırdıktan sonra kaydırmayı destekliyor gibi görünüyor, ancak çekmeceyi hareket ettirmeden listeyi kaydırmaya kadar yumuşak bir geçiş değil.
Stoph

Örnek, sol alt köşedeki Elmalar yasal bağlantısını gizliyor gibi görünüyor.
Gerd Castan

1
Çok basit bir soru, alt sayfanın üst kısmındaki göstergeyi nasıl aldınız?
A Israfil

12

Cevabımı https://github.com/SCENEE/FloatingPanel deneyebilirsiniz . Bir "alt tabaka" arayüzünü görüntülemek için bir kap görünümü denetleyicisi sağlar.

Kullanımı kolaydır ve herhangi bir jest tanıyıcı işlemeye aldırmazsınız! Ayrıca, gerekirse bir alt sayfada kaydırma görünümünü (veya kardeş görünümünü) izleyebilirsiniz.

Bu basit bir örnek. İçeriğinizi alt sayfada görüntülemek için bir görünüm denetleyicisi hazırlamanız gerektiğini lütfen unutmayın.

import UIKit
import FloatingPanel

class ViewController: UIViewController {
    var fpc: FloatingPanelController!

    override func viewDidLoad() {
        super.viewDidLoad()

        fpc = FloatingPanelController()

        // Add "bottom sheet" in self.view.
        fpc.add(toParent: self)

        // Add a view controller to display your contents in "bottom sheet".
        let contentVC = ContentViewController()
        fpc.set(contentViewController: contentVC)

        // Track a scroll view in "bottom sheet" content if needed.
        fpc.track(scrollView: contentVC.tableView)    
    }
    ...
}

İşte Apple Maps gibi bir konum aramak için alt sayfasını görüntülemek için başka bir örnek kodudur.

Apple Maps gibi örnek bir uygulama


fpc.set (contentViewController: newsVC), kütüphanede yöntem eksik
Faris Muhammed

1
Çok basit bir soru, alt sayfanın üst kısmındaki göstergeyi nasıl aldınız?
A Israfil

1
@AIsrafil Bence bu sadece bir UIView
ShadeToD

Bence gerçekten güzel bir çözüm, ancak iOS 13'te bu kayan panelle modal görünüm denetleyicisini sunmada bir sorun var.
ShadeToD

12

İOS Maps uygulamasında amaçlanan davranışı elde etmek için kendi kütüphanemi yazdım. Protokol odaklı bir çözümdür. Bu nedenle, herhangi bir temel sınıfı devralmanız gerekmez, bunun yerine bir sayfa denetleyicisi oluşturun ve istediğiniz gibi yapılandırın. Ayrıca UINavigationController ile veya olmadan iç gezinme / sunumu destekler.

Daha fazla ayrıntı için aşağıdaki bağlantıya bakın.

https://github.com/OfTheWolf/UBottomSheet

ubottom sayfası


Açılır pencerenin arkasındaki VC'yi tıklayabildiğiniz için, bu seçilen cevap olmalıdır.
Jay

Çok basit bir soru, alt sayfanın üst kısmındaki göstergeyi nasıl aldınız?
A Israfil

1

Kısa bir süre önce Swift 5.1'de yazılmış SwipeableViewalt sınıf olarak adlandırılan bir bileşen oluşturdum UIView. Tüm 4 yönünü destekler, çeşitli özelleştirme seçeneklerine sahiptir ve farklı nitelikleri ve öğeleri canlandırabilir ve enterpolasyon yapabilir (mizanpaj kısıtlamaları, arka plan / renk tonu, afin dönüşüm, alfa kanalı ve görünüm merkezi, hepsi ilgili gösteri durumuyla demo haline getirilir). Ayrıca, ayarlanmış veya otomatik olarak algılanırsa iç kaydırma görünümü ile kaydırma koordinasyonunu da destekler. Kullanılması oldukça kolay ve basit olmalıdır (umarım 🙂)

En Bağlantı https://github.com/LucaIaco/SwipeableView

kavramın ispatı:

resim açıklamasını buraya girin

Umarım yardımcı olur


0

Belki de cevabımı Pulley'den esinlenerek https://github.com/AnYuan/AYPannel deneyebilirsiniz . Çekmeceyi hareket ettirmeden listeyi kaydırmaya sorunsuz geçiş. Kapsayıcı kaydırma görünümünde bir kaydırma hareketi ekledim ve EVET'i döndürmek için shouldRecognizeSimultaneouslyWithGestureRecognizer'ı ayarladım. Yukarıdaki github bağlantımda daha fazla ayrıntı. Yardım etmek isterdim.


6
Bu bağlantı soruyu cevaplayabilse de, cevabın temel kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir. Bu bağlantı soruyu cevaplayabilse de, cevabın temel kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir.
pirho
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.