What I have are these different views as shown in picture: the main view is the container
, inside that there is the boxSentence
, inside the boxSentence
there is the subView
, and inside subView
the different text labels with the gray box boxWord
. Then there is this other view boxAnswer
that is a draggable element that i created that can only be dropped inside the boxWord
(I pass the boxWord
to my custom class of the boxAnswer
to check his position (frame)).
In this scenario everything works fine, the boxAnswer
can only be placed
inside the boxWord
Then for adjusting the graphics of the whole view I want to put my subView
with all his actual subviews in the center of boxSentence
. To do that I used subView.center = boxSentence.center
and I obtained what I wanted.
Now, the problem comes when I try to drag and drop boxAnswer
inside the new position of boxWord
, it doesn't work, but if I try to drag and drop it where boxWord
was before moving it to the center it does work.
It seems like that when you do subView.center = boxSentence.center
it only affects the frame of subView
, but it doesn't affect the frames of its subviews. Any suggestions on how to resolve the problem?
CODE:
// creo box dove inserire la frase
let boxSentence = UIView(frame: CGRect(x: 0, y: 0, width: container.frame.width, height: container.frame.height/2))
container.addSubview(boxSentence)
boxSentence.backgroundColor = hexStringToUIColor(hex: "#49eb34")
let subView = UIView(frame: CGRect(x: 0, y: 0, width: container.frame.width, height: 70))
let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
label1.text = esercizio.ctsex![0].first_sentence
label1.backgroundColor = UIColor.yellow
label1.sizeToFit()
let boxWord = UIView(frame: CGRect(x: label1.frame.maxX, y: 0, width: 100, height: 60))
boxWord.backgroundColor = UIColor.gray
let label2 = UILabel(frame: CGRect(x: boxWord.frame.maxX, y: 0, width: 100, height: 100))
label2.text = esercizio.ctsex![0].second_sentence
label2.backgroundColor = UIColor.yellow
label2.sizeToFit()
subView.addSubview(label1)
subView.addSubview(boxWord)
subView.addSubview(label2)
subView.backgroundColor = UIColor.purple
boxSentence.addSubview(sottoView)
subView.frame = CGRect(x: 0, y: 0, width: label2.frame.maxX-label1.frame.minX, height: 80)
subView.center = boxSentence.center
let coordrisposta = CGRect(x: boxFrase.frame.minX, y: boxFrase.frame.maxY, width: 80.0, height: 40.0)
let boxAnswer = DragObject(frame: coordrisposta, vistap: boxWord)
boxAnswer.backgroundColor = UIColor.red
container.addSubview(rispostaBox)
CLASS DragObject OF boxAnser:
import UIKit
// CLASSE CHE CREA UNA VISTA CHE PUO ESSERE SPOSTATA SOLO ALL'INTERNO DI UNA VISTA PASSATA DA PARAMETRO
class DragObject: UIView {
var vista: UIView
var initcoord: CGRect
init(frame: CGRect, vistap: UIView){
self.vista = vistap
self.initcoord = frame
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touch began")
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
var touch : UITouch! = touches.first as UITouch?
self.center = touch.location(in: self.superview)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
var coorv = vista.frame
print(coorv)
let coord1 = (touches.first?.location(in: self.superview))!
let destinazione1 = CGPoint(x: coorv.minX, y: coorv.minY)
let destinazione2 = CGPoint(x: coorv.maxX, y: coorv.maxY)
if coord1.x > destinazione1.x && coord1.y > destinazione1.y && coord1.x < destinazione2.x && coord1.y < destinazione2.y {
print("OK")
self.frame = vista.frame
} else {
print("fuori")
self.frame = initcoord
}
}
}
Frames of UIView is it's coordinate relative to it's parent bounds(internal coordinate system of UIView that is coordinate system for subview of that view). For example we have UIViewController with 2 views:
let redView = UIView()
redView.backgroundColor = .red
redView.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
self.view.addSubview(redView)
let greenView = UIView()
greenView.backgroundColor = .green
greenView.frame = CGRect(x: 25, y:25, width:50, height: 50)
redView.addSubview(greenView)
print(redView.frame)
/*
(20.0, 20.0, 100.0, 100.0)
redView is placed self.view.bounds.origin.x + 20 and self.view.bounds.origin.y + 20
*/
print(greenView.frame)
/*
(25.0, 25.0, 50.0, 50.0)
green is placed redView.bounds.origin.x + 25 and redView.bounds.origin.y + 25
*/
print(redView.convert(greenView.frame, to: self.view))
/*
(45.0, 45.0, 50.0, 50.0)
converted frame of greenView from redViews bounds to of self.view bounds.
*/
So the problem inside DragObject, you pass frame and view coordinates that reflect their place relative to subView view origin.
Meanwhile DragObject is subview of container view and when you receive touch coordinates you get coordinates relative to container view.
You could fix it by converting vista.frame to DragObject superview coordinate system.
Here is fullCode of override func touchesEnded(_ touches: Set, with event: UIEvent?) in DragObject
var coorv = vista.superview!.convert(vista.frame, to: self.superview!)
print(coorv)
let coord1 = (touches.first?.location(in: self.superview))!
let destinazione1 = CGPoint(x: coorv.minX, y: coorv.minY)
let destinazione2 = CGPoint(x: coorv.maxX, y: coorv.maxY)
if coord1.x > destinazione1.x && coord1.y > destinazione1.y && coord1.x < destinazione2.x && coord1.y < destinazione2.y {
print("OK")
self.frame = coorv
} else {
print("fuori")
self.frame = initcoord
}