inspired by Esat GÖZCÜ CustomTextField 🙇🏻♂️
Cassette is an Custom View library written in SwiftUI.
- Requirements
- iOS 13.0+
- Installation
- features
.package(url: "https://github.com/ios-carki/Cassette.git", from: "v1.1.10")
I will guide you on how to use BtnCassette(Button) in SwiftUI.
- Basic
struct TestView: View {
var body: some View {
VStack(spacing: 20) {
// Normal Button
BtnCassette(buttonMode: .normal(text: "Normal Button"))
// Image Button - Left Positioned Image
BtnCassette(buttonMode: .imageButton(text: "Leading Image Button", imageDirection: .leading, imageType: .system, imageName: "globe"))
// Image Button - Right Positioned Image
BtnCassette(buttonMode: .imageButton(text: "Trailing Image Button", imageDirection: .trailing, imageType: .system, imageName: "person"))
// Binding Text Button
BtnCassette(buttonMode: .bindingText(text: .constant("Binding Text Button")))
}.padding(.horizontal, 16)
}
}
- Customizing
struct TestView: View {
@StateObject private var viewModel = TestViewModel()
var body: some View {
VStack(spacing: 20) {
BtnCassette(buttonMode: .normal(text: "Normal Button"))
.setTitleTextColor(color: .blue)
.setTitleTextFont(font: .title2)
.setCornerRadius(20)
.setBorderWidth(width: 2)
.setBorderColor(color: .blue)
.setButtonHeight(height: 80)
.setBackgroundColor(color: .cyan)
.setDisableBackgroundColor(color: .gray)
.setDisable(disable: $viewModel.buttonDisable)
.click {
viewModel.buttonDisable.toggle()
}
}.padding(.horizontal, 16)
}
}
If you set default value, you don't need to set customizing function every views
- For Storyboard Interface Project
import UIKit
import Cassette
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Here is important!
let shared = BtnCassetteConfig.shared
shared.defaultButtonTextColor = .blue
shared.defaultButtonTextFont = .title2
shared.defaultButtonCornerRadius = 20
shared.defaultBorderWidth = 2
shared.defaultBorderColor = .blue
shared.defaultButtonHeight = 80
shared.defaultButtonBackgroundColor = .cyan
shared.defaultbuttonDisableBackgroundColor = .gray
return true
}
.
.
.
}
- For SwiftUI Interface Project
import SwiftUI
import Cassette
@main
struct MyProjectApp: App {
// Here is important!
init() {
let shared = BtnCassetteConfig.shared
shared.defaultButtonTextColor = .blue
shared.defaultButtonTextFont = .title2
shared.defaultButtonCornerRadius = 20
shared.defaultBorderWidth = 2
shared.defaultBorderColor = .blue
shared.defaultButtonHeight = 80
shared.defaultButtonBackgroundColor = .cyan
shared.defaultbuttonDisableBackgroundColor = .gray
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
- With Using Default Variable
import SwiftUI
import Cassette
struct TestView: View {
@StateObject private var viewModel = TestViewModel()
var body: some View {
VStack(spacing: 20) {
BtnCassette(buttonMode: .normal(text: "Normal Button"))
.setDisable(disable: $viewModel.buttonDisable)
.click {
viewModel.buttonDisable.toggle()
}
}.padding(.horizontal, 16)
}
}
The result is the same as above, but the code is much shorter.
- Basic
//normal
SwitchCassette(switchType: .normal(text: Binding<String>?, isOn: Binding<Bool>, spacing: CGFloat?))
//rectangle
SwitchCassette(switchType: .rectangle(text: Binding<String>?, isOn: Binding<Bool>, spacing: CGFloat?))
- Customizing
import SwiftUI
import Cassette
struct ContentView: View {
@StateObject private var viewModel = ContentViewModeel()
var body: some View {
VStack(alignment: .leading, spacing: 8) {
HStack {
SwitchCassette(text: $viewModel.text, isOn: $viewModel.isOn, spacing: 12)
.setSwitchControllerColor(color: .blue)
.setTitleTextOffColor(color: .blue)
.setTitleTextOnColor(color: .red)
.setSwitchOnBackgroundColor(color: .indigo)
.insertSpacer(true)
}
}
.padding(.horizontal, 16)
}
}
import SwiftUI
import Cassette
struct ContentView: View {
@StateObject private var viewModel = ContentViewModeel()
var body: some View {
VStack(alignment: .leading, spacing: 8) {
HStack {
SwitchCassette(text: $viewModel.text, isOn: $viewModel.isOn, spacing: 12)
.setSwitchControllerColor(color: .blue)
.setTitleTextOffColor(color: .blue)
.setTitleTextOnColor(color: .red)
.setSwitchOnBackgroundColor(color: .indigo)
.insertSpacer(false) // here is changed!
}
}
.padding(.horizontal, 16)
}
}
import SwiftUI
import Cassette
struct ContentView: View {
@StateObject private var viewModel = ContentViewModeel()
var body: some View {
VStack(alignment: .leading, spacing: 8) {
HStack {
SwitchCassette(text: $viewModel.text, isOn: $viewModel.isOn, spacing: 100) // spacing value changed!
.setSwitchControllerColor(color: .blue)
.setTitleTextOffColor(color: .blue)
.setTitleTextOnColor(color: .red)
.setSwitchOnBackgroundColor(color: .indigo)
.insertSpacer(false)
}
}
.padding(.horizontal, 16)
}
}
If you set default value, you don't need to set customizing function every views
- For Storyboard Interface Project
import UIKit
import Cassette
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Here is important!
let shared = SwitchCassetteConfig.shared
shared.defaultSwitchOffTextColor = .blue
shared.defaultSwitchOnTextColor = .red
shared.defaultSwitchTextFont = .callout
shared.defaultSwitchOnBackgroundColor = .indigo
shared.defaultSwitchOffBackgroundColor = .gray
shared.defaultSwitchControllerColor = .blue
return true
}
.
.
.
}
- For SwiftUI Interface Project
import SwiftUI
import Cassette
@main
struct MyProjectApp: App {
// Here is important!
init() {
let shared = SwitchCassetteConfig.shared
shared.defaultSwitchOffTextColor = .blue
shared.defaultSwitchOnTextColor = .red
shared.defaultSwitchTextFont = .callout
shared.defaultSwitchOnBackgroundColor = .indigo
shared.defaultSwitchOffBackgroundColor = .gray
shared.defaultSwitchControllerColor = .blue
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
- With Using Default Variable
import SwiftUI
import Cassette
struct ContentView: View {
@StateObject private var viewModel = ContentViewModeel()
var body: some View {
VStack(alignment: .leading, spacing: 8) {
HStack {
SwitchCassette(text: $viewModel.text, isOn: $viewModel.isOn, spacing: 100)
.insertSpacer(false)
}
}
.padding(.horizontal, 16)
}
}
The result is the same as above, but the code is much shorter.
- Basic
TextFieldCassette(mode: .underLine(placeHolder: "asdfok", text: $viewModel.text, title: "Title", alignment: .leading))
- Customizing
//Customizing
TextFieldCassette(mode: .underLine(placeHolder: "asdfok", text: $viewModel.text, title: "Title", alignment: .leading))
.setReactangleFieldBackgroundColor(.white) // SetBackgroundColor
.setPlaceHolderTextColor(.blue) // SetPlaceHolderTextColor
.setRectangleFieldBorderColor(.black) //SetBorderColor
.setImageButton(imageDirection: .trailing, imageType: .system(color: .black), imageName: "person") {
print("Hello") // SetImageButton
}
- Result
- SetError
struct ContentView: View {
@StateObject private var viewModel = ContentViewModeel()
var body: some View {
VStack(alignment: .leading, spacing: 8) {
VStack {
TextFieldCassette(mode: .underLine(placeHolder: "asdfok", text: $viewModel.text, title: "Title", alignment: .leading))
.setSecureField(isSecure: false)
.setError(isError: $viewModel.isError, errorColor: .red)
}
}
.padding(.horizontal, 16)
}
}
final class ContentViewModeel: ObservableObject {
@Published var isOn: Bool = false
@Published var text: String = "" { didSet { setError()}}
@Published var isError: Bool = false
func setError() {
if text == "abc" {
isError = true
} else {
isError = false
}
}
}
- Error Result
Simulator.Screen.Recording.-.iPhone.14.Pro.Max.-.2023-09-18.at.12.40.08.mp4
If you set default value, you don't need to set customizing function every views
//Title
public var defaultTitleTextFont: Font = .callout
public var defaultTitleTextColor: Color = .black
public var defaultTitleTextSpacing: CGFloat = 8
public var defaultTitleTextAlignment: Alignment = .leading
//Text
public var defaultTextFont: Font = .callout
public var defaultTextColor: Color = .black
public var defaultTextAlignment: Alignment = .leading
//PlaceHolder
public var defaultPlaceHolderTextColor: Color = .gray
public var defaultPlaceHolderTextFont: Font = .callout
public var defaultPlaceHolderTextAlignment: Alignment = .leading
//Design
public var defaultTextFieldHeight: CGFloat = 50
public var defaultRectangleFieldBackgroundColor: Color = .yellow
public var defaultRectangleFieldCornerRadius: CGFloat = 12
public var defaultRectangleFieldBorderColor: Color = .orange
public var defaultRectangleFieldBorderWidth: CGFloat = 2
//Error
public var defaultErrorColor: Color = .red
//SecureField
setSecureField(isSecure: Bool)
//Title
setTitleTextFont(_ font: Font)
setTitleTextColor(_ color: Color)
setTitleTextSpacing(spacing: CGFloat)
setTitleTextAlignment(alignment: Alignment)
//Text
setTextFont(_ font: Font)
setTextColor(_ color: Color)
setTextAlignment(alignment: Alignment)
//PlaceHolder
setPlaceHolderTextColor(_ color: Color)
setPlaceHolderTextFont(_ font: Font)
setPlaceHolderTextAlignment(alignment: Alignment)
//Design
setTextFieldHeight(_ height: CGFloat)
setReactangleFieldBackgroundColor(_ color: Color)
setRectangleFieldCornerRadius(_ radius: CGFloat)
setRectangleFieldBorderColor(_ color: Color)
setRectangleFieldBorderWidth(_ width: CGFloat)
//Error
setError(isError: Binding<Bool>, errorColor: Color)
//Image
setImageButton(imageDirection: ImageDirection, imageType: ImageType, imageName: String, action: (() -> ())?)