আমি কীভাবে মানচিত্র অ্যাপ থেকে নীচের শীটটি নকল করতে পারি?


201

আইওএস 10-এ নতুন মানচিত্র অ্যাপের নীচে শীটটি কীভাবে নকল করতে পারি তা আমাকে কেউ বলতে পারেন?

অ্যান্ড্রয়েডে, আপনি এমন ব্যবহার করতে পারেন BottomSheetযা এই আচরণটিকে নকল করে, তবে আমি আইওএসের মতো কিছু পাইনি।

এটি কি কোনও সামগ্রীর ইনসেট সহ একটি সাধারণ স্ক্রোল ভিউ, যাতে অনুসন্ধান বারটি নীচে থাকে?

আমি আইওএস প্রোগ্রামিংয়ে মোটামুটি নতুন তাই যদি কেউ এই লেআউটটি তৈরি করতে আমাকে সহায়তা করতে পারে তবে তা প্রশংসিত হবে।

এটি "নীচের শীট" বলতে যা বোঝায়:

মানচিত্রে ধসে পড়া নীচের শীটের স্ক্রিনশট

মানচিত্রে প্রসারিত নীচের শীটের স্ক্রিনশট


1
আপনি নিজেকে এটি তৈরি করতে হবে আমি ভীত। অস্পষ্ট ব্যাকগ্রাউন্ড ভিউ এবং কিছু অঙ্গভঙ্গি সনাক্তকারীদের সাথে এটি একটি দৃশ্য।
খানহ এনগুইন

@ খানহগুয়েইন হ্যাঁ আমি জানি এটি আমার নিজের তৈরি করতে হবে তবে আমি কী ভাবছি তা এই প্রভাবটি
সংরক্ষণাগার রাখতে

অস্পষ্ট প্রভাবের সাথে এটি ভিজ্যুয়াল এফেক্ট ভিউ। এই এসও প্রশ্নটি দেখুন
খানহ এনগুইন

1
আমি মনে করি আপনি নীচের দৃশ্যে একটি প্যান অঙ্গভঙ্গি সনাক্তকারীকে যুক্ত করতে পারেন এবং সেই অনুসারে ভিউটি সরিয়ে নিতে পারেন (অঙ্গভঙ্গি সনাক্তকারীর ইভেন্টগুলির মধ্যে y স্থানাঙ্কগুলি সংরক্ষণ করে পরিবর্তনগুলি পর্যবেক্ষণ করে এবং পার্থক্যটি গণনা করতে পারেন)।
খানহ এনগুইন

2
আমি আপনার প্রশ্ন পছন্দ করি। আমি এরকম কিছু বাস্তবায়নের পরিকল্পনা করছি। কেউ কিছু উদাহরণ লিখতে পারলে সুন্দর হত।
ওয়াভিয়ানিয়া

উত্তর:


328

আমি জানি না ঠিক কীভাবে নতুন মানচিত্র অ্যাপের নীচের শীটটি ব্যবহারকারীর ইন্টারঅ্যাকশনগুলিতে সাড়া দেয় respond তবে আপনি একটি কাস্টম ভিউ তৈরি করতে পারবেন যা স্ক্রিনশটগুলির মতো দেখতে এবং এটিকে মূল দৃশ্যে যুক্ত করতে পারেন।

আমি ধরে নিলাম আপনি কীভাবে জানেন:

1- স্টোরিবোর্ডের মাধ্যমে বা এক্সিব ফাইল ব্যবহার করে ভিউ কন্ট্রোলার তৈরি করুন।

2- গুগল্যাপস বা অ্যাপলের ম্যাপকিট ব্যবহার করুন।

উদাহরণ

1- 2 টি ভিউ কন্ট্রোলার যেমন, ম্যাপভিউকন্ট্রোলার এবং বটমশিটভিউ কনট্রোলার তৈরি করুন । প্রথম নিয়ামক মানচিত্রটি হোস্ট করবে এবং দ্বিতীয়টি নীচে শীট হবে।

ম্যাপভিউকন্ট্রোলার কনফিগার করুন

নীচের শীট দৃশ্যটি যুক্ত করতে একটি পদ্ধতি তৈরি করুন।

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)
}

এবং এটিকে ভিউডিড এয়ার পদ্ধতিতে কল করুন:

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

নীচে শীটভিউকন্ট্রোলার কনফিগার করুন

1) পটভূমি প্রস্তুত

অস্পষ্টতা এবং স্পন্দিত প্রভাব যুক্ত করার জন্য একটি পদ্ধতি তৈরি করুন

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)
}

আপনার ভিউউইল অ্যাপয়ারে এই পদ্ধতিটি কল করুন

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

আপনার নিয়ামকের দেখার ব্যাকগ্রাউন্ডের রঙ সাফ রঙের তা নিশ্চিত করুন।

2) নীচে শীট উপস্থিতি প্রাণবন্ত

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 আপনি চান হিসাবে পরিবর্তন করুন।

4) আপনার দৃষ্টিতে প্যান অঙ্গভঙ্গি সনাক্তকারীকে যুক্ত করুন।

আপনার ভিউডিডলড পদ্ধতিতে ইউআইপিএনগাস্টারআর সনাক্তকারীকে যুক্ত করুন।

override func viewDidLoad() {
    super.viewDidLoad()

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

}

এবং আপনার অঙ্গভঙ্গির আচরণটি বাস্তবায়ন করুন:

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)
}

স্ক্রোলযোগ্য নীচের শীট:

যদি আপনার কাস্টম ভিউটি কোনও স্ক্রোল ভিউ বা উত্তরাধিকার সূত্রে প্রাপ্ত অন্য কোনও ভিউ হয়, তবে আপনার কাছে দুটি বিকল্প রয়েছে:

প্রথম:

শিরোনামের দর্শন দিয়ে ভিউটি ডিজাইন করুন এবং প্যাডগ্যাসচারটি শিরোনামে যুক্ত করুন। (খারাপ ব্যবহারকারীর অভিজ্ঞতা)

দ্বিতীয়ত:

1 - প্যানগ্যাসচারটি নীচের শিট ভিউতে যুক্ত করুন।

2 - ইউআইজিএসচাররনগাইনাইজারডেলিগেট বাস্তবায়ন করুন এবং প্যানগ্যাসচারের প্রতিনিধিটিকে নিয়ামকের কাছে সেট করুন।

3- বাস্তবায়িত হওয়া উচিত একই সাথে ডেলিগেটের ফাংশন সহ সনাক্ত করুন এবং দুটি ক্ষেত্রে স্ক্রোলভিউসস্ক্রোলভুক্ত সম্পত্তিটি অক্ষম করুন :

  • দৃশ্যটি আংশিকভাবে দৃশ্যমান।
  • দৃশ্যটি সম্পূর্ণ দৃশ্যমান, স্ক্রোলভিউ কন্টেন্টঅফসেট সম্পত্তি 0 এবং ব্যবহারকারী ভিউটিকে নীচের দিকে টেনে নিচ্ছেন

অন্যথায় স্ক্রোলিং সক্ষম করুন।

  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
  }

বিঃদ্রঃ

আপনি যদি নমুনা প্রকল্পের মতো একটি অ্যানিমেশন বিকল্প হিসাবে .allUserInteration সেট করেন তবে ব্যবহারকারী যদি স্ক্রল করছে তবে আপনাকে অ্যানিমেশন সমাপ্তির বন্ধে স্ক্রোলিং সক্ষম করতে হবে।

নমুনা প্রকল্প

আমি এই রেপোতে আরও বিকল্প সহ একটি নমুনা প্রকল্প তৈরি করেছি যা আপনার প্রবাহটি কীভাবে অনুকূলিতকরণ করতে পারে সে সম্পর্কে আরও ভাল অন্তর্দৃষ্টি দিতে পারে।

ডেমোতে, অ্যাডবটমশীটভিউ () ফাংশন নিয়ন্ত্রণ করে যে দর্শনটি নীচের শিট হিসাবে ব্যবহার করা উচিত।

নমুনা প্রকল্পের স্ক্রিনশট

- আংশিক দেখুন

এখানে চিত্র বর্ণনা লিখুন

- বিস্তারিত

এখানে চিত্র বর্ণনা লিখুন

- স্ক্রোলযোগ্য ভিউ

এখানে চিত্র বর্ণনা লিখুন


3
এটি চাইল্ডভিউ এবং সাবভিউয়ের জন্য একটি ভাল টিউটোরিয়াল। আপনাকে ধন্যবাদ :)
এডিসন

@ আহেমেডলাটিউটি কীভাবে আমি এক্সবিতে টেবিলভিউ যুক্ত করতে এবং নীচের শীট হিসাবে লোড করতে পারি? আপনি যদি সহায়তা করতে পারেন তবে অগ্রিম ধন্যবাদ!
নিখিল নাঙ্গিয়া

3
@ নিখিলনাঙ্গিয়া আমি সবেমাত্র অন্য ভিউকন্ট্রোলার "স্ক্রোলবেলটমশীটভিউ কনট্রোলারআরউইফ্ট" এর সাথে রেপো আপডেট করেছি যাতে একটি টেবিল ভিউ রয়েছে। উত্তরটি যত তাড়াতাড়ি সম্ভব আপডেট করব। এটিও github.com/AhmedElassuty/IOS- নীচে পত্রক
আহমদ ইলাচিউটি

12
আমি লক্ষ্য করেছি যে অ্যাপল মানচিত্রের নীচের শীটটি একটি মসৃণ গতিতে শীট ড্র্যাগ অঙ্গভঙ্গি থেকে স্ক্রোল ভিউ স্ক্রোল অঙ্গভঙ্গিতে স্থানান্তরিত পরিচালনা করে, অর্থাত্ স্ক্রোলিং শুরু করার জন্য ব্যবহারকারীকে একটি অঙ্গভঙ্গি থামাতে এবং একটি নতুন শুরু করার দরকার নেই। আপনার উদাহরণটি এটি করে না। কীভাবে এটি সম্পন্ন হতে পারে সে সম্পর্কে আপনার কোনও ধারণা আছে? ধন্যবাদ, এবং একটি রেপোতে উদাহরণ পোস্ট করার জন্য একটি টন ধন্যবাদ!
স্টোফ

2
@ রাফায়েললাউরেনো আপনি আমার উত্তরকে সহায়ক বলে খুঁজে পেয়েছেন বলে আমি সত্যিই খুশি! ধন্যবাদ!
আহমদ ইলেসটিউ

55

আমি নীচে আমার উত্তর উপর ভিত্তি করে একটি গ্রন্থাগার মুক্তি ।

এটি শর্টকাট অ্যাপ্লিকেশন ওভারলে নকল করে। বিশদ জন্য এই নিবন্ধটি দেখুন ।

লাইব্রেরির প্রধান উপাদান OverlayContainerViewController। এটি এমন একটি অঞ্চলকে সংজ্ঞায়িত করে যেখানে ভিউ কন্ট্রোলারটিকে উপরে এবং নীচে টেনে আনা যায়, এর নীচে থাকা সামগ্রী লুকিয়ে রাখতে বা প্রকাশ করতে পারে।

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

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

window?.rootViewController = containerController

বাস্তবায়ন OverlayContainerViewControllerDelegateআকাঙ্ক্ষিত notches সংখ্যা নির্দিষ্ট করতে:

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
    }
}

পূর্ববর্তী উত্তর

আমি মনে করি একটি উল্লেখযোগ্য পয়েন্ট রয়েছে যা প্রস্তাবিত সমাধানগুলিতে চিকিত্সা করা হয় না: স্ক্রোল এবং অনুবাদের মধ্যে রূপান্তর।

স্ক্রোল এবং অনুবাদের মধ্যে মানচিত্রের রূপান্তর

মানচিত্রে, যেমন আপনি লক্ষ্য করেছেন, টেবিলভিউ পৌঁছে contentOffset.y == 0গেলে নীচের শীটটি স্লাইড হয় বা নীচে যায়।

বিষয়টিটি মুশকিল কারণ আমাদের প্যান অঙ্গভঙ্গিটি অনুবাদটি শুরু করার পরে আমরা কেবল স্ক্রোলটি সক্ষম / অক্ষম করতে পারি না। কোনও নতুন স্পর্শ শুরু না হওয়া পর্যন্ত এটি স্ক্রোলটি থামিয়ে দেবে। এখানে প্রস্তাবিত বেশিরভাগ সমাধানের ক্ষেত্রে এটিই।

এই গতিটি বাস্তবায়নের জন্য আমার চেষ্টা এখানে।

শুরুর পয়েন্ট: মানচিত্র অ্যাপ্লিকেশন

আমাদের তদন্ত শুরু করতে, আসুন মানচিত্রের চিত্রক্রমটি ভিজ্যুয়ালাইজ করা যাক (একটি সিমুলেটরে মানচিত্র শুরু করুন এবং>>> এক্সকোড 9 এ > নির্বাচন Debugকরুন )।Attach to process by PID or NameMaps

মানচিত্রের ডিবাগ ভিউয়ের স্তরক্রম

এটি গতিটি কীভাবে কাজ করে তা বলে না, তবে এটির যুক্তি বুঝতে আমাকে সহায়তা করেছিল। আপনি এলএলডিবি এবং ভিউ হায়ারার্কি ডিবাগার দিয়ে খেলতে পারেন।

আমাদের দেখুন নিয়ামক স্ট্যাক

আসুন মানচিত্র ভিউ কন্ট্রোলার আর্কিটেকচারের একটি প্রাথমিক সংস্করণ তৈরি করি।

আমরা একটি BackgroundViewController(আমাদের মানচিত্রের দৃশ্য) দিয়ে শুরু করি :

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

আমরা একটি উত্সর্গীকৃত টেবিল ভিউ রাখি UIViewController:

class OverlayViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    lazy var tableView = UITableView()

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

    [...]
}

এখন, ওভারলে এম্বেড করতে এবং এর অনুবাদ পরিচালনা করতে আমাদের একটি ভিসি দরকার। সমস্যাটিকে সহজ করার জন্য, আমরা বিবেচনা করি যে এটি ওভারলেটিকে একটি স্থিতিশীল বিন্দু OverlayPosition.maximumথেকে অন্য স্থানে অনুবাদ করতে পারে OverlayPosition.minimum

আপাতত অবস্থানের পরিবর্তনটি অ্যানিমেটেড করার জন্য এটির জন্য একটি জনসাধারণ পদ্ধতি রয়েছে এবং এর স্বচ্ছ দৃষ্টিভঙ্গি রয়েছে:

enum OverlayPosition {
    case maximum, minimum
}

class OverlayContainerViewController: UIViewController {

    let overlayViewController: OverlayViewController
    var translatedViewHeightContraint = ...

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

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

সবগুলি এম্বেড করার জন্য অবশেষে আমাদের একটি ভিউকন্ট্রোলার দরকার:

class StackViewController: UIViewController {

    private var viewControllers: [UIViewController]

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

আমাদের অ্যাপডেলিগেটে, আমাদের প্রারম্ভিক ক্রমটি দেখে মনে হচ্ছে:

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

ওভারলে অনুবাদ পিছনে অসুবিধা

এখন, কীভাবে আমাদের ওভারলে অনুবাদ করবেন?

প্রস্তাবিত বেশিরভাগ সমাধানগুলিতে একটি উত্সর্গীকৃত প্যান অঙ্গভঙ্গি সনাক্তকারী ব্যবহার করে তবে আমাদের ইতিমধ্যে একটি রয়েছে: টেবিলের দৃশ্যের প্যান অঙ্গভঙ্গি। তদ্ব্যতীত, আমাদের স্ক্রোল এবং অনুবাদটি সিঙ্ক্রোনাইজ করা এবং আমাদের UIScrollViewDelegateসমস্ত ইভেন্টের দরকার আছে!

একটি নিষ্পাপ বাস্তবায়ন দ্বিতীয় প্যান অঙ্গভঙ্গি ব্যবহার করবে এবং contentOffsetঅনুবাদটি আসার পরে সারণী দর্শনটির পুনরায় সেট করার চেষ্টা করবে :

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

কিন্তু এটা কাজ করে না। contentOffsetনিজস্ব প্যান অঙ্গভঙ্গি সনাক্তকারী ক্রিয়াটি ট্রিগার করা হয় বা এর ডিসপ্লেলিঙ্ক কলব্যাক কল করার সময় টেবিলভিউ এটি আপডেট করে । সফলভাবে ওভাররাইড করার পরে আমাদের শনাক্তকারী ঠিক তখনই ট্রিগার করতে পারে এমন কোনও সম্ভাবনা নেই contentOffset। আমাদের একমাত্র সুযোগটি হ'ল লেআউট পর্বের অংশ নেওয়া ( layoutSubviewsস্ক্রোল ভিউয়ের প্রতিটি ফ্রেমে স্ক্রোল ভিউ কলগুলি ওভাররাইড করে ) বা didScrollপ্রতিবার contentOffsetসংশোধিত হওয়ার সময় ডেলিগ্রেটের পদ্ধতিতে সাড়া দেওয়া । এর এক চেষ্টা করুন।

অনুবাদ বাস্তবায়ন

OverlayVCস্ক্রোলভিউয়ের ইভেন্টগুলি আমাদের অনুবাদ হ্যান্ডলারের কাছে প্রেরণে আমরা একটি প্রতিনিধি যুক্ত করি 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)
    }
}

আমাদের পাত্রে, আমরা একটি এনাম ব্যবহার করে অনুবাদটি ট্র্যাক করি:

enum OverlayInFlightPosition {
    case minimum
    case maximum
    case progressing
}

বর্তমান অবস্থানের গণনা দেখে মনে হচ্ছে:

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

অনুবাদটি পরিচালনা করতে আমাদের 3 টি পদ্ধতি দরকার:

প্রথমটি আমাদের জানান যে আমাদের অনুবাদ শুরু করতে হবে কিনা।

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
    }
}

দ্বিতীয়টি অনুবাদ সম্পাদন করে। এটি translation(in:)স্ক্রোলভিউর প্যান অঙ্গভঙ্গির পদ্ধতিটি ব্যবহার করে ।

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)
    )
}

তৃতীয়টি অনুবাদকের শেষটি অ্যানিমেট করে যখন ব্যবহারকারী তার আঙুলটি প্রকাশ করে। আমরা বেগ এবং দৃশ্যের বর্তমান অবস্থান ব্যবহার করে অবস্থান গণনা করি।

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

আমাদের ওভারলে-র প্রতিনিধি বাস্তবায়ন কেবল এ রকম দেখায়:

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()
    }
}

চূড়ান্ত সমস্যা: ওভারলে কন্টেইনারটির ছোঁয়া প্রেরণ

অনুবাদ এখন বেশ দক্ষ। তবে এখনও একটি চূড়ান্ত সমস্যা রয়েছে: স্পর্শগুলি আমাদের পটভূমিতে দেখার জন্য সরবরাহ করা হয় না। এগুলি সমস্ত ওভারলে কন্টেইনারের দৃষ্টিতে আটকে রয়েছে। আমরা সেট isUserInteractionEnabledকরতে পারি না falseকারণ এটি আমাদের টেবিল ভিউতে মিথস্ক্রিয়াটিকে অক্ষম করে। সমাধান হ'ল ম্যাপস অ্যাপে ব্যাপকভাবে ব্যবহৃত হয় 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
    }
}

এটি প্রতিক্রিয়াশীল চেইন থেকে নিজেকে সরিয়ে দেয়।

ইন OverlayContainerViewController:

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

ফলাফল

ফলাফল এখানে:

ফলাফল

আপনি কোডটি এখানে খুঁজে পেতে পারেন ।

আপনি যদি কোনও বাগ দেখতে পান তবে আমাকে জানান! মনে রাখবেন যে আপনার বাস্তবায়ন অবশ্যই দ্বিতীয় প্যান অঙ্গভঙ্গি ব্যবহার করতে পারে, বিশেষত যদি আপনি নিজের ওভারলেতে শিরোনাম যোগ করেন।

আপডেট 23/08/18

আমরা প্রতিস্থাপন করতে পারেন scrollViewDidEndDraggingসঙ্গে willEndScrollingWithVelocityবদলে enabling/ disablingস্ক্রল যখন ব্যবহারকারী প্রান্ত টেনে:

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

গতি প্রবাহকে আরও উন্নত করতে আমরা অ্যানিমেট করার সময় একটি বসন্ত অ্যানিমেশন ব্যবহার করতে পারি এবং ব্যবহারকারীর মিথস্ক্রিয়াকে অনুমতি দিতে পারি:

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)
}

অ্যানিমেশন পর্যায়ে এই পদ্ধতির ইন্টারেক্টিভ হয় না। উদাহরণস্বরূপ, মানচিত্রে, শিটটি প্রসারিত হওয়ার সাথে সাথে আমি আমার আঙুল দিয়ে ধরতে পারি। আমি তারপরে বা নীচে প্যান করে অ্যানিমেশনটি স্ক্রাব করতে পারি। এটি যে কোনও স্পটে নিকটতম অবস্থানে ফিরে আসবে। আমি বিশ্বাস করি এটি ব্যবহার করে সমাধান করা যেতে পারে UIViewPropertyAnimator(যার মধ্যে বিরতি দেওয়ার ক্ষমতা রয়েছে), তারপরে fractionCompleteস্ক্রাবটি সম্পাদন করতে সম্পত্তিটি ব্যবহার করুন ।
Aust

1
আপনি ঠিক অস্ট আমি আমার আগের পরিবর্তনটিকে ধাক্কা দিতে ভুলে গেছি। এটা এখন ভাল করা উচিত। ধন্যবাদ।
গাটানজেড

এটি দুর্দান্ত ধারণা, তবে আমি এখনই একটি সমস্যা দেখতে পাচ্ছি। ইন translateView(following:)পদ্ধতি অনুবাদ উপর ভিত্তি করে উচ্চতা নিরূপণ, কিন্তু যে 0.0 তুলনায় বিভিন্ন মান থেকে শুরু করতে পারে (যেমন টেবিল ভিউ একটি সামান্য বিট স্ক্রল করা হয় এবং আস্তরণ বড় করা হয় যখন আপনি টেনে শুরু করেন) । এটির প্রাথমিক জাম্পের ফলস্বরূপ। আপনি scrollViewWillBeginDraggingকলব্যাকের মাধ্যমে এটি সমাধান করতে পারেন যেখানে আপনি contentOffsetসারণী দর্শনটির প্রারম্ভিক মনে রাখবেন এবং এটি translateView(following:)গণনাতে ব্যবহার করবেন।
জাকুব ট্রুহলি

1
@ গ্যাটানজেড আমি সিমুলেটারেও মানচিত্রের অ্যাপ্লিকেশনটিতে ডিবাগার সংযুক্ত করতে আগ্রহী ছিলাম, তবে "পিডের সাথে সংযুক্তি করা যায়নি:" 926 "" পরে নিশ্চিত করুন "মানচিত্র" চলছে না, এবং <ব্যবহারকারী নাম> এর অনুমতি রয়েছে এটি ডিবাগ করুন। " - আপনি কীভাবে এক্স.কোডকে মানচিত্র.এ্যাপে সংযুক্ত করার অনুমতি দিয়েছিলেন?
ম্যাটাম

1
@ ম্যাটম @ গ্যাটনজ আমার জন্য এক্সকোড 10.1 / মোজাভেতে কাজ করেছেন -> সিস্টেম ইন্টিগ্রিটি প্রোটেকশন (এসআইপি) অক্ষম করার জন্য কেবল অক্ষম করা দরকার। আপনার প্রয়োজন: 1) আপনার ম্যাক পুনরায় চালু করুন; 2) সেন্টিমিডি + আর ধরে রাখুন; 3) মেনু থেকে ইউটিলিটিগুলি নির্বাচন করুন তারপরে টার্মিনাল; 4) টার্মিনাল উইন্ডোতে টাইপ ইন: csrutil disable && reboot। এরপরে আপনার কাছে সমস্ত ক্ষমতা থাকবে যা রুটকে আপনাকে সাধারণত কোনও অ্যাপল প্রসেসের সাথে সংযুক্ত থাকতে সক্ষম করে should
ভালডিয়ার

18

পুলি চেষ্টা করুন :

পুলি হ'ল আইওএস 10 এর ম্যাপস অ্যাপ্লিকেশনে ড্রয়ারটি অনুকরণ করার জন্য একটি ড্রয়ারের লাইব্রেরি ব্যবহার করা সহজ। এটি একটি সাধারণ API উন্মুক্ত করে যা আপনাকে কোনও ইউআইভিউকন্ট্রোলার সাবক্লাসটি ড্রয়ার সামগ্রী বা প্রাথমিক সামগ্রী হিসাবে ব্যবহার করতে দেয়।

পুলি পূর্বরূপ

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


1
এটি অন্তর্নিহিত তালিকায় স্ক্রোলিং সমর্থন করে?
রিচার্ড লিন্ডাউট

@ রিচার্ড লিন্ডাউট - ডেমো চালানোর পরে দেখে মনে হচ্ছে এটি স্ক্রোলিং সমর্থন করে, তবে ড্রয়ারটি তালিকাটি স্ক্রোলিংয়ের দিকে সরানো থেকে মসৃণ রূপান্তর নয়।
স্টফ

উদাহরণটি নীচে বামদিকে অ্যাপল আইনী লিঙ্কটি লুকিয়ে রাখার জন্য প্রদর্শিত হচ্ছে।
গার্ড কাস্তান

1
খুব সহজ প্রশ্ন, আপনি নীচের শীটের শীর্ষে সূচকটি কীভাবে পেয়েছেন?
এ ইস্রাফিল

12

আপনি আমার উত্তরটি https://github.com/SCENEE/FloatingPanel চেষ্টা করতে পারেন । এটি "নীচের শীট" ইন্টারফেসটি প্রদর্শনের জন্য একটি ধারক ভিউ কন্ট্রোলার সরবরাহ করে।

এটি ব্যবহার করা সহজ এবং আপনি কোনও অঙ্গভঙ্গি সনাক্তকারীকে পরিচালনা করতে আপত্তি করবেন না! এছাড়াও প্রয়োজন হলে আপনি নীচের শীটে কোনও স্ক্রোল ভিউ (বা ভাইবাল ভিউ) ট্র্যাক করতে পারেন।

এটি একটি সহজ উদাহরণ। দয়া করে নোট করুন যে নীচের শীটে আপনার সামগ্রী প্রদর্শন করতে আপনাকে একটি ভিউ কন্ট্রোলার তৈরি করতে হবে।

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)    
    }
    ...
}

অ্যাপল মানচিত্রের মতো কোনও অবস্থান অনুসন্ধানের জন্য নীচের শীটটি প্রদর্শনের জন্য এখানে আরেকটি উদাহরণ কোড রয়েছে।

অ্যাপল মানচিত্রের মতো নমুনা অ্যাপ


fpc.set (কন্টেন্টভিউ কনট্রোলার: নিউজভিসি), লাইব্রেরিতে অনুপস্থিত পদ্ধতি
ফারিস মুহাম্মদ

1
খুব সহজ প্রশ্ন, আপনি নীচের শীটের শীর্ষে সূচকটি কীভাবে পেয়েছেন?
এ ইস্রাফিল

1
@ এআসরাফিল আমি মনে করি এটি কেবলমাত্র একটি
ইউআইভিউ

আমি মনে করি এটি সত্যিই দুর্দান্ত সমাধান, তবে আইওএস 13 এ এই ভাসমান প্যানেলের সাথে মডেল ভিউ কন্ট্রোলার উপস্থাপনের ক্ষেত্রে একটি সমস্যা আছে।
শেডটিড

11

আইও ম্যাপস অ্যাপ্লিকেশনটিতে উদ্দেশ্যপূর্ণ আচরণটি অর্জন করতে আমি নিজের লাইব্রেরিটি লিখেছি। এটি একটি প্রোটোকল ভিত্তিক সমাধান। সুতরাং আপনাকে কোনও বেস ক্লাস উত্তরাধিকারী হওয়ার পরিবর্তে একটি শীট নিয়ামক তৈরি করতে এবং আপনার ইচ্ছামত কনফিগার করার দরকার নেই। এটি ইউআইএনএভিগেশন কন্ট্রোলারের সাথে বা ছাড়া অভ্যন্তরীণ নেভিগেশন / উপস্থাপনা সমর্থন করে।

আরও তথ্যের জন্য নীচের লিঙ্ক দেখুন।

https://github.com/OfTheWolf/UBottomSheet

ইউবোটম শিট


এটির নির্বাচিত উত্তর হওয়া উচিত, যেহেতু আপনি এখনও পপআপের পিছনে ভিসিতে ক্লিক করতে পারেন।
জয়

খুব সহজ প্রশ্ন, আপনি নীচের শীটের শীর্ষে সূচকটি কীভাবে পেয়েছেন?
এ ইস্রাফিল

1

আমি সম্প্রতি একটি উপাদান তৈরি করেছি যার SwipeableViewনাম সাবক্লাস UIView, সুইফট 5.1 তে লেখা in এটি সমস্ত চারটি দিক সমর্থন করে, বেশ কয়েকটি কাস্টমাইজেশন বিকল্প রয়েছে এবং বিভিন্ন বৈশিষ্ট্য এবং আইটেমগুলিকে (যেমন লেআউট সীমাবদ্ধতা, পটভূমি / রঙের রঙ, অ্যাফাইন ট্রান্সফর্ম, আলফা চ্যানেল এবং দৃশ্য কেন্দ্র, এগুলি সমস্তই শো-এর ক্ষেত্রে দেখানো হয়েছে) সঞ্চারিত এবং সংযোগ করতে পারে। এটি সেট বা অটো সনাক্ত করা হলে এটি অভ্যন্তরীণ স্ক্রোল ভিউয়ের সাথে স্যুইপিং সমন্বয়কেও সমর্থন করে। ব্যবহার করা খুব সহজ এবং সোজা হওয়া উচিত (আমি আশা করি 🙂)

Https://github.com/LucaIaco/SwipeableView এ লিঙ্ক করুন

ধারণার প্রমাণ:

এখানে চিত্র বর্ণনা লিখুন

আশা করি এটা সাহায্য করবে


0

পুলি দ্বারা অনুপ্রাণিত হয়ে আপনি আমার উত্তর https://github.com/AnYuan/AYPannel চেষ্টা করতে পারেন । ড্রয়ারটি তালিকা থেকে স্ক্রোলিংয়ে সরানো থেকে মসৃণ রূপান্তর। আমি ধারক স্ক্রোল ভিউতে একটি প্যান অঙ্গভঙ্গি যুক্ত করেছি এবং YES ফেরত দেওয়ার জন্যRecognizeSim વા্যি উইথ গেরচারআর সনাক্তকারীকে সেট করেছিলাম। উপরের আমার গিথুব লিঙ্কে আরও বিশদ। সাহায্য করতে চান।


6
যদিও এই লিঙ্কটি প্রশ্নের উত্তর দিতে পারে, উত্তরের প্রয়োজনীয় অংশগুলি এখানে অন্তর্ভুক্ত করা এবং রেফারেন্সের জন্য লিঙ্কটি সরবরাহ করা ভাল। লিঙ্কযুক্ত পৃষ্ঠাগুলি পরিবর্তিত হলে লিঙ্ক-শুধুমাত্র উত্তরগুলি অবৈধ হতে পারে। যদিও এই লিঙ্কটি প্রশ্নের উত্তর দিতে পারে, উত্তরের প্রয়োজনীয় অংশগুলি এখানে অন্তর্ভুক্ত করা এবং রেফারেন্সের জন্য লিঙ্কটি সরবরাহ করা ভাল। লিঙ্কযুক্ত পৃষ্ঠাগুলি পরিবর্তিত হলে লিঙ্ক-শুধুমাত্র উত্তরগুলি অবৈধ হতে পারে।
পিরহো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.