JXSegmentedView Documentation

repository·master·Indexed 25 days ago

https://github.com/pujiaxin33/jxsegmentedview

A highly customizable segmented view and paging component for iOS designed to replicate category-switching behaviors found in mainstream applications. It supports segmented controls, paging views, and category views using protocol-oriented programming for customizable indicators and lazy loading via JXSegmentedListContainerView.

Tokens
10.8K
Snippets
24
Records
65
Agent score
83%

What's inside JXSegmentedView

  1. Overview of JXSegmentedView features

    master

    JXSegmentedView is a powerful Swift-based segmented view component for iOS (supporting iOS 9.0+). It is designed to replace standard segmented controls, paging views, and category views with highly customizable effects.

    Key advantages include:

    • Protocol-Oriented Indicator Logic: Easily extendable indicator behaviors.
    • Rich Visual Effects: Supports a wide variety of popular app-style indicators and cell animations.
    • Subclass-based Cell Management: Clearer logic for managing custom cell styles through subclassing.
  2. JXSegmentedView Project Overview

    master

    JXSegmentedView is a powerful and easy-to-use segmented view component for iOS (supporting segmented control, paging view, page view, page control, and category view). It is designed to mimic the category switching scrolling views found in mainstream apps like Tencent News, Toutiao, QQ Music, NetEase Cloud Music, JD, iQIYI, Tencent Video, Taobao, Tmall, and Weibo.

    Key Advantages

    • Protocol Oriented Programming: The indicator logic is based on protocols, allowing for highly customizable indicator effects.
    • Rich Effects: Supports a wide range of mainstream app styles.
    • Subclassing for Cells: Uses subclassing to manage cell styles, making logic clearer and extensions easier.
    • Lifecycle Support: The list supports full lifecycle methods.
  3. Install JXSegmentedView via Swift Package Manager

    master

    To install JXSegmentedView using Swift Package Manager, follow these steps:

    1. Add the dependency to your Package.swift file:
    dependencies: [
      .package(url: "https://github.com/pujiaxin33/JXSegmentedView.git", from: "1.2.1")
    ]
    1. Build using the command line:
    swift build
    dependencies: [
      .package(url: "https://github.com/pujiaxin33/JXSegmentedView.git", from: "1.2.1")
    ]
    
    # Then run:
    swift build
  4. Initialize and use JXSegmentedView

    master

    To use the basic segmented view, initialize JXSegmentedView, set its delegate, and add it to your view hierarchy. You must also provide a data source that conforms to JXSegmentedViewDataSource.

    Important: The dataSource object must be strongly held by a property in your class to prevent it from being deallocated.

    // 1. Initialize JXSegmentedView
    self.segmentedView = JXSegmentedView()
    self.segmentedView.delegate = self
    self.view.addSubview(self.segmentedView)
    
    // 2. Initialize dataSource (must be strongly held)
    self.segmentedDataSource = JXSegmentedTitleDataSource()
    self.segmentedDataSource.titles = ["猴哥", "青蛙王子", "旺财"]
    self.segmentedDataSource.isTitleColorGradientEnabled = true
    self.segmentedDataSource.reloadData(selectedIndex: 0)
    self.segmentedView.dataSource = self.segmentedDataSource
    
    // 3. Initialize Indicator
    let indicator = JXSegmentedIndicatorLineView()
    indicator.indicatorWidth = 20
    self.segmentedView.indicators = [indicator]
  5. Use JXSegmentedListContainerView for Content Lists

    master

    For managing the content views (lists) associated with each segment, it is highly recommended to use JXSegmentedListContainerView instead of a raw UIScrollView.

    Advantages of JXSegmentedListContainerView:

    • High level of abstraction and centralized code.
    • Lazy Loading: Lists are initialized only when they are displayed, improving performance.
    • Supports UICollectionView as a container for better memory management.
    • Supports the full lifecycle methods of the list items.

    1. Initialize the Container

    Associate the container with the segmentedView using the listContainer property.

    2. Implement JXSegmentedListContainerViewDataSource

    Provide the number of lists and the instance that conforms to JXSegmentedListContainerViewListDelegate for each index.

    3. Implement JXSegmentedListContainerViewListDelegate

    Your list items (can be UIView or UIViewController) must implement this to provide their view and lifecycle callbacks.

    // 1. Initialize JXSegmentedListContainerView
    listContainerView = JXSegmentedListContainerView(dataSource: self)
    view.addSubview(self.listContainerView)
    // Associate the list with the segmented view
    segmentedView.listContainer = listContainerView
    
    // 2. Implement JXSegmentedListContainerViewDataSource
    func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int {
        return segmentedDataSource.titles.count
    }
    
    func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate {
        return ListBaseViewController()
    }
    
    // 3. Implement JXSegmentedListContainerViewListDelegate
    // For a ViewController, return vc.view. For a View, return self.
    func listView() -> UIView {
        return view
    }
    
    func listWillAppear() {}
    func listDidAppear() {}
    func listDidDisappear() {}
    func listDidDisappear() {}
  6. Install JXSegmentedView via Carthage

    master

    To install JXSegmentedView using Carthage, add the following line to your Cartfile:

    gituh "pujiaxin33/JXSegmentedView"

    Then, run the following command in your terminal:

    carthage update --platform iOS
    github "pujiaxin33/JXSegmentedView"
    
    # Then run:
    carthage update --platform iOS
  7. Remove custom naviController for UIViewController lists

    master

    If your list items are UIViewController instances, you can remove any custom naviController properties you were previously passing.

    JXSegmentedListContainerView now creates a JXSegmentedListContainerViewController internally. This controller detects if the list items are View Controllers and automatically calls addChildViewController to add them to the hierarchy. This allows list VCs to use self.navigationController directly without external injection.

    Note: If your list items are standard Views (not VCs), you must continue to pass the navigation controller as before.

  8. Handle lifecycle methods for UIViewController vs UIView based lists

    master

    Depending on whether your list implementation is a UIViewController or a UIView, you should choose which lifecycle methods to rely on:

    • If the list is a UIViewController: The system lifecycle methods (viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear) will trigger in the same sequence as the custom lifecycle methods. You can rely solely on the standard system lifecycle methods.
    • If the list is a UIView: You should rely on the custom JXSegmentedView lifecycle methods (listWillAppear, etc.) as standard system view lifecycle methods may not behave the same way for subviews.
  9. Configure screen edge gestures for JXSegmentedView

    master

    By default, the iOS screen edge swipe gesture (interactive pop gesture) might conflict with the segmented view's ability to scroll. To allow the user to swipe back to the previous page only when they are on the first segment (index 0), and allow horizontal scrolling of the segmented view on all other segments, implement the following logic.

    If you want the side-slip gesture to always trigger a back navigation regardless of the selected segment, you do not need to implement this guide.

    // 1. In viewWillAppear, enable back gesture only if the first segment is selected
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = (self.segmentedView.selectedIndex == 0)
    }
    
    // 2. In viewWillDisappear, restore the back gesture for other view controllers
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
    }
    
    // 3. In the JXSegmentedViewDelegate method, update the gesture state when the selection changes
    func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) {
        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = (self.segmentedView.selectedIndex == 0)
    }