Code Monkey home page Code Monkey logo

swipecellsui's Introduction

Swipe Cell SwiftUI

Swipe Cell SwiftUI is a simple swipe-to-reveal menu view written in Swift. It supports iOS / iPadOs 14 or later. The purpose is to replace the default SwiftUI List .onDelete(perform: ...) modifier since its functionality is limited to deletion only and only works on List rows. Moreover, rows in an iOS 14 LazyVStack do not support swipe to reveal out of the box. Swipe Cell SwiftUI allows adding multiple menu buttons on the left and right side and also features a swipe out functionality (e.g. swipe to delete).

Example project

This repo only contains the Swift package, no example XCode project. Please download the example project here. Simply add the swift package through the Swift Package mMnager (see below - Installation).

Features

  • Add multiple leading and/or trailing menu buttons

  • Fully customize each button view

  • Add swipe out behavior to one button on each side

  • Add a haptic feedback to indicate that the swipe out will be triggered

  • from version 2.0: auto closes an open cell if the user swipes another cell

  • from version 2.1: make an open cell close on tap on another cell (example below)

    Check out the example for details.

Installation

Installation through the Swift Package Manager (SPM) is recommended.

SPM: Select your project (not the target) and then select the Swift Packages tab. Click + and type SwipeCellSUI should find the package on github. Otherwise copy and paste the whole URL of this repo.

Check out the version history below for the current version.

Make sure to import SwipeCellSUI in every file where you use SwipeCellSUI.

    import SwipeCellSUI

Known issues

Before version 2.1.2, the swipe cell modifier seems to block List scrolling. This was fixed in 2.1.2. However, tapping the revealed buttons still does not seem to work properly with List views. The touch event works only for one button even if another button was tapped.

Usage

Check out the following example. This repo only contains the Swift package, no example code. Please download the example project here.

SwipeCellSUI example

SwipeCellSUI example

Code example: Attach swipeCellSUI to the a row view

struct RowView: View {
    var availableWidth: CGFloat
    var item: String
    @State private var isPinned: Bool = false
    var deletionCallback: (String)->()
    @Binding var currentUserInteractionCellID: String?
    
    var body: some View {
        Text(item).frame(width: availableWidth, height:100)
        .background(RoundedRectangle(cornerRadius: 5).foregroundColor(.green))
        .swipeCell(id: self.item, cellWidth: availableWidth, leadingSideGroup: leftGroup(), trailingSideGroup: rightGroup(), currentUserInteractionCellID: $currentUserInteractionCellID)  
        .onTapGesture {
            // this will make another cell close, in case its side panel is open:  
            self.currentUserInteractionCellID = item
            // implement other functionality associated to tapping the row if required.
        }
        
        // you can customize settings by adding the settings parameter at the end
     
    }
    
    func leftGroup()->[SwipeCellActionItem] {
        return [ SwipeCellActionItem(buttonView: {
            
            self.pinView(swipeOut: false)
            
        }, swipeOutButtonView: {
            self.pinView(swipeOut: true)
        }, buttonWidth: 80, backgroundColor: .yellow, swipeOutAction: true, swipeOutHapticFeedbackType: .success, swipeOutIsDestructive: false)
        {
            print("pin action!")
            self.isPinned.toggle()
        }]
    }
    
    func pinView(swipeOut: Bool)->AnyView {

            Group {
                Spacer()
                VStack(spacing: 2) {
                    Image(systemName: self.isPinned ? "pin.slash": "pin").font(.system(size: 24)).foregroundColor(.white)
                    Text(self.isPinned ? "Unpin": "Pin").fixedSize().font(.system(size: 14)).foregroundColor(.white)
                }.frame(maxHeight: 80).padding(.horizontal, swipeOut ? 20 : 5)
                if swipeOut == false {
                    Spacer()
                } 
            }.animation(.default).castToAnyView()

    }

    func rightGroup()->[SwipeCellActionItem] {

        let items =  [
            SwipeCellActionItem(buttonView: {
    
                    VStack(spacing: 2)  {
                    Image(systemName: "person.crop.circle.badge.plus").font(.system(size: 22)).foregroundColor(.white)
                        Text("Share").fixedSize().font(.system(size: 12)).foregroundColor(.white)
                    }.frame(maxHeight: 80).castToAnyView()

            }, backgroundColor: .blue)
            {
                print("share action!")
            },
            SwipeCellActionItem(buttonView: {
                    VStack(spacing: 2)  {
                    Image(systemName: "folder.fill").font(.system(size: 22)).foregroundColor(.white)
                        Text("Move").fixedSize().font(.system(size: 12)).foregroundColor(.white)
                    }.frame(maxHeight: 80).castToAnyView()
          
            }, backgroundColor: .purple, actionCallback: {
                print("folder action")
            }),
            
            SwipeCellActionItem(buttonView: {
                self.trashView(swipeOut: false)
            }, swipeOutButtonView: {
                self.trashView(swipeOut: true)
            }, backgroundColor: .red, swipeOutAction: true, swipeOutHapticFeedbackType: .warning, swipeOutIsDestructive: true) {
                print("delete action")
               self.deletionCallback(item)
            }
          ]
        
        return items
    }
    
    func trashView(swipeOut: Bool)->AnyView {
            VStack(spacing: 3)  {
                Image(systemName: "trash").font(.system(size: swipeOut ? 28 : 22)).foregroundColor(.white)
                Text("Delete").fixedSize().font(.system(size: swipeOut ? 16 : 12)).foregroundColor(.white)
            }.frame(maxHeight: 80).animation(.default).castToAnyView()
        
    }
}

Change log

mihapp's fix for usage with List - buttons are triggered separately now.

Fixed scrolling issue for List views. Caution: Tapping the revealed menu buttons still doesn't work properly if you attach the swipe cell modifier to the rows of a List (better use ScrollView + LazyVStack).

minor change: updated documentation.

  • changed parameter name currentDragCellID to currentUserInteractionCellID and its type to Binding<String?>
  • set the currentUserInteractionCellID binding to the current id of your row or cell (e.g. onTap) if you want another open cell to close on tapping. For this to work, it is required to override the id parameter of the swipe cell modifier!

Breaking changes:

  • now only supporting iOS 14 or newer.
  • you need to set a currentDragCellID optional UUID binding now (either originating from your view model as published var or in the parent view itself as State variable). This property will ascertain that if there are several swipe cells (as is typically the case in a list) and the user swipes a cell, another cell whose side menu is currently open, will automatically close (similar behavior as in the Apple iOS Notes app)

Swipe Cell menu opening less easily now.

Settings properties can now be changed as expected.

Initial public release.

Author

[email protected]

License

SwipeCellSUI is available under the MIT license. See the LICENSE file for more info.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.