StackUI just like SwiftUI

Related tags

SwiftUI App StackUI
Overview

StackUI

中文文档

Use UIStackView like SwiftUI.

Use @propertyWrapper, @resultBuilder, chain syntax and other features used by SwiftUI, making UIStackView easy to use. For classes such as Label, Button, and ImageView, it is still the way to use UIKit, but it is encapsulated with chain syntax.

Because SwiftUI requires an iOS13+ system to be used, it is almost impossible to use SwiftUI in actual projects. But the features of SwiftUI are really fascinating, so StackUI is the implementation of SwiftUI in the scope of UIStackView. You can experience some of the features of SwiftUI in StackUI, so that you can learn the new features earlier.

If you are tired of configuring the constraints of UIKit, then StackUI will be a good helper for you. The declarative layout make world better.

Features

  • Declarative syntax similar to SwiftUI;
  • Data-driven UI, update data then UI automatically updates;
  • Support HScrollStack, VScrollStack, when the content exceeds the width or height of the stack, scrolling is automatically turned on;
  • Chained syntax configuration UIKit;
  • Can flexibly extend custom classes to support StackUI;

Require

  • iOS 9.0+
  • XCode 13.0+
  • Swift 5.4+

Install

CocoaPods

target'<Your Target Name>' do
    pod'StackUI'
    //If you want to use RxSwift
    pod'StackUI/RxSwift'
end

Execute pod repo update first, then execute pod install

SPM

Example

HStack

    HStack(alignment: .center, spacing: 5) {
        ImageView().image(UIImage(named: "avatar")).size(width: 40, height: 40)
        Label("user nickname").font(.systemFont(ofSize: 18, weight: .medium))
    }

VStack

    VStack {
        Label("user nickname").font(.systemFont(ofSize: 18, weight: .medium))
        Label().text("The user is lazy, nothing left!").font(.systemFont(ofSize: 12)).textColor(.gray)
    }

HScrollStack and ForIn

    var users = [UserModel]()
    for index in 0...25 {
        let model = UserModel(avatar: "avatar", name: "user\(index)", desc: "user description\(index)")
        users.append(model)
    }
    HScrollStack() {
        for model in users {
            HStack(alignment: .center, spacing: 5) {
                Spacer(spacing: 12)
                ImageView().image(UIImage(named: model.avatar)).size(width: 80, height: 80)
                VStack {
                    Label(model.name).font(.systemFont(ofSize: 18, weight: .medium))
                    Label().text(model.desc).font(.systemFont(ofSize: 12)).textColor(.gray)
                }
                Divider()
            }.size(width: 300)
        }
    }

@Live

Add @Live in front of the property, and add the $ symbol prefix when using it. When updating properties, the associated UIKit will automatically update the interface.

    //definition
    @Live var nickName: String? = "User nickname"
    @Live var desc: String? = "The user is lazy, and nothing is left!"
    
    //use
    HStack(distribution: .equalCentering, alignment: .center) {
        HStack(alignment: .center, spacing: 5) {
            ImageView().image(UIImage(named: "avatar")).size(width: 40, height: 40)
            VStack {
                Label($nickName).font(.systemFont(ofSize: 18, weight: .medium))
                Label().text($desc).font(.systemFont(ofSize: 12)).textColor(.gray)
            }
        }
        ImageView().image(UIImage(named: "arrow_right"))
    }
    
    //update
    nickName = "Jay Chou"
    desc = "Ouch, not bad ❤️"

Driver of RxSwift

    //definition
    var nickName = PublishSubject<String?>()
    var desc = PublishSubject<String?>()
    
    //use
    HStack(distribution: .equalCentering, alignment: .center) {
        HStack(alignment: .center, spacing: 5) {
            ImageView().image(UIImage(named: "avatar")).size(width: 40, height: 40)
            VStack {
                Label(nickName.asDriver(onErrorJustReturn: nil)).font(.systemFont(ofSize: 18, weight: .medium))
                Label().text(desc.asDriver(onErrorJustReturn: nil)).font(.systemFont(ofSize: 12)).textColor(.gray)
            }
        }
        ImageView().image(UIImage(named: "arrow_right"))
    }
    
    //update
    nickName.onNext("Jay Chou")
    desc.onNext("Ouch, not bad ❤️")

Custom View supports StackUI

You can customize the parent class

Inherit from View, Label, etc., and then extend custom attributes.

class CustomView: View {
    var customColor: UIColor = .black
    
    func customColor(_ customColor: UIColor) -> Self {
        self.customColor = customColor
        self.backgroundColor = customColor
        return self
    }
}
class CustomLabel: Label {
    var customColor: UIColor = .black
    
    func customColor(_ customColor: UIColor) -> Self {
        self.customColor = customColor
        self.textColor = customColor
        return self
    }
}

If Statement

     var isShowInfo: Bool = false
     HStack(distribution: .equalCentering, alignment: .center) {
         HStack(alignment: .center, spacing: 5) {
             ImageView().image(UIImage(named: "avatar")).size(width: 40, height: 40)
             if self.isShowInfo == true {
                 VStack {
                     Label("User nickname").font(.systemFont(ofSize: 18, weight: .medium))
                     Label().text("The user is lazy, nothing left!").font(.systemFont(ofSize: 12)).textColor(.gray)
                 }
             }else {
                 Label("No Information")
             }
         }
         ImageView().image(UIImage(named: "arrow_right"))
     }

The parent class cannot be modified, conform the protocol

Conform protocols such as StackUIView and StackUILabel, and then extend custom attributes.

class CustomViewFromProtocol: UIView, StackUIView {
    var customColor: UIColor = .black
    
    func customColor(_ customColor: UIColor) -> Self {
        self.customColor = customColor
        self.backgroundColor = customColor
        return self
    }
}
class CustomLabelFromProtocol: UILabel, StackUILabel {
    var customColor: UIColor = .black
    
    func customColor(_ customColor: UIColor) -> Self {
        self.customColor = customColor
        self.textColor = customColor
        return self
    }
}

Attribute configuration not supported by chain syntax yet

Unified configuration through apply closure

HStack(alignment: .center, spacing: 5) {
     Label().text(model.desc).apply {label in
         //If there are attributes that are not defined by the chain syntax, they can be configured in the apply closure, or they can be submitted to Issue for support.
         label.font = UIFont.systemFont(ofSize: 10)
         label.textColor = .gray
     }
}

ViewBox use

Sometimes the view needs margins. At this time, you can put the view into the ViewBox, and then set the paddings, so you can indirectly set the top, bottom, left, and right margins of the view. As shown in the following code: Label has margins of top: 10, left: 20, bottom: 10, right: 20.

ViewBox(paddings: .init(top: 10, left: 20, bottom: 10, right: 20)) {
     Label("Hobbies: writing code;").font(. systemFont(ofSize: 15)).numberOfLines(0)
}.backgroundColor(.lightGray)

Currently supported classes

  • Layer:The relevant properties of Layer are configured in the View class
  • View
  • ImageView
  • Control
  • Label
  • Button
  • TextField
  • TextView
  • Stepper
  • SwitchUI
  • PageControl
  • Slider
  • Spacer
  • Divider
  • ActivityIndicatorView
  • ScrollView
  • TableView
  • CollectionView

If there are other classes and attributes that need to be supported, please submit an Issue or Pull Request.

You might also like...
🎲 100% SwiftUI 2.0, classic 2048 game [SwiftUI 2.0, iOS 14.0+, iPadOS 14.0+, macOS 11.0+, Swift 5.3].
🎲 100% SwiftUI 2.0, classic 2048 game [SwiftUI 2.0, iOS 14.0+, iPadOS 14.0+, macOS 11.0+, Swift 5.3].

swiftui-2048 If you like the project, please give it a star ⭐ It will show the creator your appreciation and help others to discover the repo. ✍️ Abou

A simple SwiftUI Application to demonstrate creation of UI using SwiftUI.
A simple SwiftUI Application to demonstrate creation of UI using SwiftUI.

WatchShop_UI A simple SwiftUI Application to demonstrate creation of UI using SwiftUI. How to run the project ? Fork the project. Run the project usin

E-commerce app built in SwiftUI. Built in the course SwiftUI Masterclass in Udemy.
E-commerce app built in SwiftUI. Built in the course SwiftUI Masterclass in Udemy.

Touchdown-SwiftUI E-commerce app built in SwiftUI. Built in the course SwiftUI Masterclass in Udemy. Main components and concepts used: @EnvironmentOb

A multiplatform SwiftUI project demonstrating various SwiftUI features.

WikiDemo A multiplatform SwiftUI project demonstrating various SwiftUI features, including creating a master-detail interface. It's a multiplatform ve

SwiftUI Projects from Udemy SwiftUI Masterclass

SwiftUI Masterclass Repos: AsyncImage (N/A) Fructus (finished): an app for getting information about different fruits. Data comes from json files. Afr

Best architecture for SwiftUI + CombineBest architecture for SwiftUI + Combine

Best architecture for SwiftUI + Combine The content of the presentation: First of the proposed architectures - MVP + C Second of the proposed architec

Weather-swiftui - An example of using SwiftUI

weather-swiftui An example of using SwiftUI Installation Get openweather api key

Orbit-swiftui - Orbit design system implemented in SwiftUI for iOS

Orbit is a SwiftUI component library which provides developers the easiest possi

SwiftUI Resume - A simple resume writed by swiftUI + Combine
SwiftUI Resume - A simple resume writed by swiftUI + Combine

SwiftUI_Resume a simple "resume" writed by swiftUI + Combine

Comments
  • 怎么样才能宽高自适应呢

    怎么样才能宽高自适应呢

    image

    let stack = VStack { Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)) Label("昵称").font(.systemFont(ofSize: 18, weight: .medium)).backgroundColor(UIColor.red)

      TextButton().apply { button in
        button.text = "xxxxxxx"
        button.contentMode = .center
      }
      Button().title(nickName.asDriver(onErrorJustReturn: nil), for: .normal)
    }
    

    宽度被撑满了

    opened by qingweiSun 1
  • Use Sourcery generate boilerplate code

    Use Sourcery generate boilerplate code

    Since the project based on UIKit need to add many methods like the original one, this boilerplate code can be generated by tools, like https://github.com/Ernest0-Production/DeclarativeLayoutKit#how-to-extend-chaining-functionality

    I think we can do research to generate this type of code https://github.com/pujiaxin33/StackUI/blob/main/Sources/Core/Label.swift

    opened by EkkoG 0
Owner
暴走的鑫鑫
既然你是你,那就让你是你!
暴走的鑫鑫
WeChat-like Moments App implemented using Swift 5.5 and SwiftUI

Moments SwiftUI This is a re-implementation of Moments App using Swift 5.5 and SwiftUI. Features: Aysnc/Await Actor AysncImage MVVM BFF Screenshot Als

Jake Lin 46 Jan 5, 2023
In this mini app covered the concepts like basics of SwiftUI and Navigations and Animations and List with CRUD functions and MVVM and App Launch and App icons adding and also applied persistence using UserDefaults Concept.

TodoList In this application used the concepts from the beginner level project of SwiftUI_Evolve_1 The following concepts covered in this mini app Swi

Sivaram Yadav 2 Dec 4, 2021
Tinder like ui using SwiftUI

// // User.swift // CardUI // // Created by paige on 2021/12/09. // import SwiftUI struct User: Identifiable { var id = UUID().uuidString

paigeshin 0 Dec 9, 2021
GroceryMartApp-iOS-practice - To Practice fundamental SwiftUI feature like navigation, state mamagement, customazing etc

?? GroceryMartApp-iOS-practice 아래의 내용은 스윗한 SwiftUI 책의 실전 앱 구현하기 을 바탕으로 정리한 내용입니다

Jacob Ko 0 Jan 7, 2022
A cross-platform SwiftUI-like framework built on SwiftGtk.

SwiftGtkUI A SwiftUI-like framework for creating cross-platform apps in Swift. It uses SwiftGtk as its backend. NOTE: SwiftGtkUI does not attempt to r

null 99 Jan 5, 2023
Visualize your dividend growth. DivRise tracks dividend prices of your stocks, gives you in-depth information about dividend paying stocks like the next dividend date and allows you to log your monthly dividend income.

DivRise DivRise is an iOS app written in Pure SwiftUI that tracks dividend prices of your stocks, gives you in-depth information about dividend paying

Kevin Li 78 Oct 17, 2022
A fluent Collapsing header view like iOS Contacts detail and Weather App

FluentCollapsingHeaderView A Collapse Header View like iOS Weather App Credits FluentCollapsingHeaderView is owned and maintained by the Seyed Samad G

Seyed Samad Gholamzadeh 2 May 26, 2022
The ToDo-like app using swift

ToDo-List The ToDo-like app. The data model uses classes. The table view is created depending on the structure of the model classes. The user has the

NIKOLAY NIKITIN 2 Aug 8, 2022
ProgrammingCalculator - a simple programmer's calculator with operators like AND, OR

Programmer's Calculator This is a simple calculator program which implements operators commonly used in discrete logic such as AND, OR, Bit Shifting,

Austin Wright 0 Jan 5, 2022
Fast Multi-store Redux-like architecture for iOS/OSX applications

Highway Highway is implementation of Redux-like architecture pattern using Swift. If you were looking for a something like this: TEA (The Elm Architec

Dmitrii Cooler 14 Dec 9, 2022