i have a bug, if i click on button before the animation before the card flip back. i think for me the best it would be to disable the button for 2 sec, but i made some research and didnt find anything!
struct CardBack: View {
var body: some View {
Image("back_card")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 250)
}
}
struct ContentView: View {
#State var flipped = false
#State private var cardsFront = ["bigCard1", "bigCard2", "bigCard3", "bigCard4", "bigCard5" ]
#State private var cardBack = "back_card"
#State private var disablled = true
var body: some View {
VStack {
Spacer()
ZStack {
Image(flipped ? self.cardsFront.randomElement()! : self.cardBack)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 250)
.rotation3DEffect(Angle(degrees: flipped ? 180 : 0 ), axis: (x: 0, y: 1, z: 0))
}
Spacer()
HStack {
Button(action: {
withAnimation(.spring()) {
self.flipped.toggle()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
withAnimation(.spring()) {
self.flipped.toggle()
}
}
}) {
Image("circle")
.renderingMode(.original)
}
Button(action: {
}) {
Image("plus")
.renderingMode(.original)
}
iOS 13, Swift 5
You can set the button as disabled initially and then enable it using the same sort of logic I used here.
import SwiftUI
struct ContentView: View {
#State var changeColor = false
var body: some View {
TextView(changeColor: $changeColor)
}
}
struct TextView: View {
#Binding var changeColor: Bool
var body: some View {
Text("Hello World")
.foregroundColor(changeColor ? Color.black: Color.red)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.changeColor.toggle()
}
}
}
}
You are almost there, you just need to use the .appear tag in your code to do this.
Related
I have a button ("Next Word") that when pressed shows a new view ("PracticeResult"). The idea is that everytime you press it, a new random word appears on the screen. But so far, I have to press the button twice to get it to show the next image because it's triggered with a boolean state.
I've tried changing the State back to false with an ".onAppear" toggle but it doesn't work. I've also tried using an origin State to toggle the variable back to false but it hasn't worked either. I'm quite new to SwiftUI so any tips would be appreciated! Thanks in advance.
struct PracticeView: View {
#State var isTapped: Bool = false
var body: some View {
NavigationView {
ZStack {
Color.white
VStack() {
Image("lightlogolong")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 300.0, height: 100.0)
.cornerRadius(100)
.animation(.easeIn, value: 10)
NavigationLink(destination:
ContentView().navigationBarBackButtonHidden(true) {
HomeButton()
}
Group {
if (isTapped == true){
PracticeResult()
}
}.onAppear{
isTapped.toggle()
}
Button("Next Word", action:{
self.isTapped.toggle()
})
.padding()
.frame(width: 150.0, height: 40.0)
.font(.title2)
.accentColor(.black)
.background(Color("appblue"))
.clipShape(Capsule())
}
}
}
}
}
You could try this simple approach, using a UUID or something like it,
to trigger your PracticeResult view every time you tap the button. Note in particular the PracticeResult().id(isTapped)
struct PracticeView: View {
#State var isTapped: UUID? // <--- here
var body: some View {
NavigationView {
ZStack {
Color.white
VStack() {
Image("lightlogolong")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 300.0, height: 100.0)
.cornerRadius(100)
.animation(.easeIn, value: 10)
NavigationLink(destination:
ContentView().navigationBarBackButtonHidden(true) {
HomeButton()
}
if isTapped != nil {
PracticeResult().id(isTapped) // <--- here
}
Button("Next Word", action:{
isTapped = UUID() // <--- here
})
.padding()
.frame(width: 150.0, height: 40.0)
.font(.title2)
.accentColor(.black)
.background(Color.blue)
.clipShape(Capsule())
}
}
}
}
}
// for testing
struct PracticeResult: View {
#State var randomWord: String = UUID().uuidString
var body: some View {
Text(randomWord)
}
}
if you want your button trigger a new random word appears on the screen, you should use button to change that random word
for example (you can try it on Preview):
struct PracticeView: View {
let words = ["one","two","three"]
#State var wordToDisplay: String?
var body: some View {
VStack {
if let wordToDisplay = wordToDisplay {
Text(wordToDisplay)
}
Spacer()
Button("Next Word") {
wordToDisplay = words.filter { $0 != wordToDisplay }.randomElement()
}
}.frame(height: 50)
}
}
There is a button in the TabBar, this button should open the camera
"Button(action: {...}, label: { ..."
The camera code is written in "CameraView" and "CameraModel" :
struct CameraView: View {
#StateObject var camera = CameraModel()
var body: some View {
ZStack{
// Camera preview...
CameraPreview(camera: camera)
.ignoresSafeArea(.all, edges: .all)
VStack{
if camera.isTaken{
HStack {
Spacer()
Button(action: {}, label: {
Image(systemName: "arrow.triangle.2.circlepath.camera")
.foregroundColor(.black)
.padding()
.background(Color.white)
.clipShape(Circle())
})
.padding(.trailing,10)
}
}
Spacer()
HStack{
if camera.isTaken{
Button(action: {}, label: {
Text("Save")
.foregroundColor(.black)
.fontWeight(.semibold)
.padding(.vertical,10)
.padding(.horizontal,20)
.background(Color.white)
.clipShape(Capsule())
})
.padding(.leading)
Spacer()
}
else{
Button(action: {camera.isTaken.toggle()}, label: {
ZStack{
Circle()
.fill(Color.white)
.frame(width: 65, height: 65)
Circle()
.stroke(Color.white,lineWidth: 2)
.frame(width: 75, height: 75)
}
})
}
}
.frame(height: 75)
}
}
.onAppear(perform: {
camera.Check()
})
}
}
class CameraModel: ObservableObject{
#Published var isTaken = false
#Published var session = AVCaptureSession()
#Published var alert = false
// since were going to read pic data....
#Published var output = AVCapturePhotoOutput()
// preview....
#Published var preview : AVCaptureVideoPreviewLayer!
func Check(){
// first checking camerahas got permission...
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
setUp()
return
// Setting Up Session
case .notDetermined:
// retusting for permission....
AVCaptureDevice.requestAccess(for: .video) { (status) in
if status{
self.setUp()
}
}
case .denied:
self.alert.toggle()
return
default:
return
}
}
func setUp(){
// setting up camera...
do{
// setting configs...
self.session.beginConfiguration()
// change for your own...
let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
let input = try AVCaptureDeviceInput(device: device!)
// checking and adding to session...
if self.session.canAddInput(input){
self.session.addInput(input)
}
// same for output....
if self.session.canAddOutput(self.output){
self.session.addOutput(self.output)
}
self.session.commitConfiguration()
}
catch{
print(error.localizedDescription)
}
}
}
// setting view for preview...
struct CameraPreview: UIViewRepresentable {
#ObservedObject var camera : CameraModel
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: UIScreen.main.bounds)
camera.preview = AVCaptureVideoPreviewLayer(session: camera.session)
camera.preview.frame = view.frame
// Your Own Properties...
camera.preview.videoGravity = .resizeAspectFill
view.layer.addSublayer(camera.preview)
// starting session
camera.session.startRunning()
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
}
}
How to call the camera on click Button in TabBar "Button(action: {}, label: {
)"?
This is just an example of how I did it in the past (after all permissions etc... have been done).
Use your code to do the same.
struct ContentView: View {
#State var image: UIImage?
#State private var showCamera = false
var body: some View {
VStack {
Button(action: { self.showCamera.toggle() }) {
Image(systemName: "camera.circle").resizable().frame(width: 100, height: 100)
}
if image != nil {
Image(uiImage: image!).resizable().frame(width: 200, height: 200)
}
} // this is where it happens
.sheet(isPresented: $showCamera, onDismiss: {self.showCamera = false}) {
CameraViewController(photo: $image)
}
}
}
struct CameraViewController: UIViewControllerRepresentable {
#Environment(\.presentationMode) var presentationMode
#Binding var photo: UIImage?
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
}
func makeUIViewController(context: UIViewControllerRepresentableContext<CameraViewController>) -> UIImagePickerController {
let vc = UIImagePickerController()
vc.sourceType = .camera
vc.delegate = context.coordinator
return vc
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate, AVCapturePhotoCaptureDelegate {
var parent: CameraViewController
var captureSession: AVCaptureSession!
var capturePhotoOutput: AVCapturePhotoOutput!
var theCamera: AVCaptureDevice!
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
let photoQualityPrioritizationMode = AVCapturePhotoOutput.QualityPrioritization.speed
init(_ imagePickerController: CameraViewController) {
self.parent = imagePickerController
}
// called when a picture has been taken
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:[UIImagePickerController.InfoKey : Any]) {
guard let image = info[.originalImage] as? UIImage else {
print("No image found")
return
}
parent.photo = image // <--- the photo image
parent.presentationMode.wrappedValue.dismiss()
}
}
}
I want to be able to use my custom button in multiple places. Right now it can only Navigate to StartWithPhoneView when tapped. When I use somewhere else I want to Navigate to another view too. I can do it by creating two custom buttons but it is code repetition.
struct CustomButtonView: View {
#State var isTapped: Bool = false
var text = ""
var body: some View {
Button(action: {
print("Create account tapped")
self.isTapped.toggle()
}, label: {
RoundedRectangle(cornerRadius: 5)
.frame(width: UIScreen.main.bounds.width / 1.205, height: 44)
.foregroundColor(.blue)
.overlay(Text(text))
.foregroundColor(.white)
})
.padding(.top,15)
NavigationLink("", destination: StartWithPhoneView(), isActive: $isTapped)
}
}
I am using Custom Button in this SignUpView
struct SignupView: View {
var body: some View {
NavigationView {
VStack {
CustomButtonView(text: "Create an account" )
}
NavigationLink("", destination: StartWithPhoneView(), isActive: CustomButtonView.$isTapped) // I want to reach inside CustomButtonView to fetch isTapped
}
}
}
You can use Generic type which is a View
struct CustomButtonView<Destination: View>: View { //<-here
#State var isTapped: Bool = false
var destination: Destination //<- here
var text = ""
var body: some View {
Button(action: {
print("Create account tapped")
self.isTapped.toggle()
}, label: {
RoundedRectangle(cornerRadius: 5)
.frame(width: UIScreen.main.bounds.width / 1.205, height: 44)
.foregroundColor(.blue)
.overlay(Text(text))
.foregroundColor(.white)
})
.padding(.top,15)
NavigationLink("bbbbb", destination: destination, isActive: $isTapped) //<- here
}
}
I am trying to call a navigation view from another view using a navigation bar. However, when I try to call it it just comes up blank. I think something goes wrong if I call a view that has a navigation view on it. The view I'm trying to call is TeamList(). I tried calling other views and it works, but only TeamList() doesn't work since it has navigation view on it. Any ideas?
Here is the View I am trying to call
import SwiftUI
struct TeamList: View {
init() {
UITableView.appearance().backgroundColor = UIColor(.pink)
UITableViewCell.appearance().backgroundColor = UIColor(.pink)
UITableView.appearance().tableFooterView = UIView()
}
var body: some View {
NavigationView {
List(teamData) { team in
NavigationLink(destination: TeamDetail(team: team)) {
TeamRow(team: team)
}
}
.navigationBarTitle(Text("Club List"))
}
}
}
struct TeamList_Previews: PreviewProvider {
static var previews: some View {
TeamList()
}
}
And here is the view I am calling it from
import SwiftUI
struct ContentView: View {
var body: some View {
CustomNaviagtionBar()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Home : View {
var body: some View {
VStack {
HStack {
Image("epl")
VStack(alignment: .leading) {
Text("Premier League")
Text("See the latest matches")
}
.padding(.top, 40)
Spacer()
}
Spacer()
}.background(Color.pink).edgesIgnoringSafeArea(.all).foregroundColor(.white)
}
}
var tabs = ["Home","Ranking","Clubs"]
struct BarButton : View {
var image : String
#Binding var Tab : String
var body: some View {
Button(action: {Tab = image}) {
Image(image)
.renderingMode(.template)
.foregroundColor(Tab == image ? Color(.blue) : Color.black.opacity(0.4))
.padding()
}
}
}
struct CustomNaviagtionBar : View {
#State var Tab = "Home"
#State var edge = UIApplication.shared.windows.first?.safeAreaInsets
var body: some View {
ZStack(alignment: Alignment(horizontal: .center, vertical: .bottom)){
TabView(selection: $Tab) {
Home()
.tag("Home")
Ranking()
.tag("Ranking")
Clubs()
.tag("Clubs")
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.ignoresSafeArea(.all, edges: .bottom)
HStack(spacing: 0){
ForEach(tabs, id: \.self){image in
BarButton(image: image, Tab: $Tab)
if image != tabs.last{
Spacer(minLength: 0)
}
}
}
}
}
}
struct Ranking : View {
var body: some View{
VStack{
Text("Ranking")
}
}
}
struct Clubs : View {
var body: some View{
TeamList() // This is the view that I am trying to call but come up blank
}
}
Trying to init CustomButton(title: "Add", icon: .add, status: .enable)
My code is below. I do get the title but enums are not working.
Plus recieving error
Cannot convert value of type 'Image' to expected argument type 'String'
at Image(icon)
import SwiftUI
struct CustomButton: View {
var title: String
var icon: String
var status: Color
var body: some View {
Button(action: {
}) {
Text(title)
.foregroundColor(.white)
.background(Color(.green))
.font(Font.custom("SFCompactDisplay", size: 14))
Image(icon)
.renderingMode(.original)
.foregroundColor(.white)
}
}
enum Icon {
case add
case edit
var image: Image {
switch self {
case .add:
return Image("Add")
case .edit:
return Image("Edit")
}
}
}
enum Status {
case enable
case disable
var color : Color {
switch self {
case .enable:
return Color(.green)
case .disable:
return Color(.gray)
}
}
}
init(title: String, icon: Icon, status: Status) {
self.title = title
self.icon = icon.image
self.status = status.color
}
}
I assume you wanted this
struct CustomButton: View {
var title: String
var icon: Icon
var status: Color
var body: some View {
Button(action: {
}) {
Text(title)
.foregroundColor(.white)
.background(Color(.green))
.font(Font.custom("SFCompactDisplay", size: 14))
icon.image
.renderingMode(.original)
.foregroundColor(.white)
}
}
enum Icon {
case add
case edit
var image: Image {
switch self {
case .add:
return Image("Add")
case .edit:
return Image("Edit")
}
}
}
enum Status {
case enable
case disable
var color : Color {
switch self {
case .enable:
return Color(.green)
case .disable:
return Color(.gray)
}
}
}
init(title: String, icon: Icon, status: Status) {
self.title = title
self.icon = icon
self.status = status.color
}
}
I figured it out. It works now.
struct CustomButton: View {
let title: String
let icon : String
let status: Color
#State private var buttonDisabled = true
var body: some View {
Button(action: {
}) {
ZStack(alignment:.bottom) {
HStack {
Text(title)
.foregroundColor(.white)
.font(Font.custom("SFCompactDisplay-Bold", size: 20))
.bold()
.fontWeight(.bold)
.background(status)
Image(icon)
.renderingMode(.original)
.foregroundColor(.white)
.background(Color(.white))
}
.frame(width: 335, height: 20, alignment: .center)
.padding()
.background(status)
}
.cornerRadius(10)
}
}
enum Icon {
case add
case edit
case none
var image: String {
switch self {
case .add:
return "Add"
case .edit:
return "Edit"
case .none:
return "empty"
}
}
}
enum Status {
case enable
case disable
}
init(title: String, icon: Icon, status: Status) {
self.title = title
self.icon = icon.image
if status == .enable {
self.status = Color(#colorLiteral(red: 0, green: 0.6588235294, blue: 0.5254901961, alpha: 1))
} else {
self.status = Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1))
}
}
}
struct CustomButton_Previews: PreviewProvider {
static var previews: some View {
CustomButton(title: "Odeme Yontemi Ekle", icon: .none, status: .enable)
}
}