我尝试创建一个带有拖动手势的按钮,就像 android 的气泡信使
I try to create a Button with Drag Gesture like the bubble messenger of android
我用拖动手势创建了一个图像,但是当我把它转换成一个按钮时,全屏变成了按钮,所以当我点击到屏幕上的任何地方时,按钮就会动作
struct OwlFly: View {
private var bround = UIScreen.main.bounds
@State var isShow = false
@State private var location = CGPoint(x: 60, y: 60)
@GestureState private var startLocation: CGPoint? = nil
var simpleDrag: some Gesture {
DragGesture()
.onChanged { value in
var newLocation = startLocation ?? location
newLocation.x += value.translation.width
newLocation.y += value.translation.height
self.location = newLocation
self.location = value.location
}
.onEnded{ value in
if(value.translation.width > bround.size.width/2) {
self.location.x = bround.size.width - 30
}
else {
self.location.x = 30
}
}
.updating($startLocation) { (value, startLocation, transaction) in
startLocation = startLocation ?? location
}
}
var body: some View {
Button(action: {
self.isShow.toggle()
if(isFly) {
self.location.x = bround.width/2
}
else {
self.location.x = 30
}
}) { // I convert the Image to a label of button
Image("simpleDrag")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50)
.animation(.easeInOut)
.position(location)
.gesture(simpleDrag)
}
}
}
这是我的代码
这很好!
.position
将视图(和按钮)扩展到最大尺寸,这就是您可以在任何地方单击的原因。
最简单的解决方法是不使用按钮,而是使图像本身可点击 – 请参见下面的代码。
PS:如果您使用 onChanged
和 onEnded
自己管理拖动,则不必使用 @GestureState
– 您做了双重工作。我注释掉了你不需要的一切 ;)
struct ContentView: View {
private var bround = UIScreen.main.bounds
@State var isShow = false
@State private var location = CGPoint(x: 60, y: 60)
// @GestureState private var startLocation: CGPoint? = nil
var simpleDrag: some Gesture {
DragGesture()
.onChanged { value in
// var newLocation = location
// newLocation.x += value.translation.width
// newLocation.y += value.translation.height
// self.location = newLocation
self.location = value.location
}
.onEnded{ value in
if(value.translation.width > bround.size.width/2) {
self.location.x = bround.size.width - 30
}
else {
self.location.x = 30
}
}
// .updating($startLocation) { (value, startLocation, transaction) in
// startLocation = startLocation ?? location
// }
}
var body: some View {
Image(systemName: "bubble.right.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50)
.animation(.easeInOut, value: location)
.position(location)
.gesture(simpleDrag)
.onTapGesture {
self.isShow.toggle()
if(isShow) {
self.location.x = bround.width/2
}
else {
self.location.x = 30
}
}
}
}
我用拖动手势创建了一个图像,但是当我把它转换成一个按钮时,全屏变成了按钮,所以当我点击到屏幕上的任何地方时,按钮就会动作
struct OwlFly: View {
private var bround = UIScreen.main.bounds
@State var isShow = false
@State private var location = CGPoint(x: 60, y: 60)
@GestureState private var startLocation: CGPoint? = nil
var simpleDrag: some Gesture {
DragGesture()
.onChanged { value in
var newLocation = startLocation ?? location
newLocation.x += value.translation.width
newLocation.y += value.translation.height
self.location = newLocation
self.location = value.location
}
.onEnded{ value in
if(value.translation.width > bround.size.width/2) {
self.location.x = bround.size.width - 30
}
else {
self.location.x = 30
}
}
.updating($startLocation) { (value, startLocation, transaction) in
startLocation = startLocation ?? location
}
}
var body: some View {
Button(action: {
self.isShow.toggle()
if(isFly) {
self.location.x = bround.width/2
}
else {
self.location.x = 30
}
}) { // I convert the Image to a label of button
Image("simpleDrag")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50)
.animation(.easeInOut)
.position(location)
.gesture(simpleDrag)
}
}
}
这是我的代码
这很好!
.position
将视图(和按钮)扩展到最大尺寸,这就是您可以在任何地方单击的原因。
最简单的解决方法是不使用按钮,而是使图像本身可点击 – 请参见下面的代码。
PS:如果您使用 onChanged
和 onEnded
自己管理拖动,则不必使用 @GestureState
– 您做了双重工作。我注释掉了你不需要的一切 ;)
struct ContentView: View {
private var bround = UIScreen.main.bounds
@State var isShow = false
@State private var location = CGPoint(x: 60, y: 60)
// @GestureState private var startLocation: CGPoint? = nil
var simpleDrag: some Gesture {
DragGesture()
.onChanged { value in
// var newLocation = location
// newLocation.x += value.translation.width
// newLocation.y += value.translation.height
// self.location = newLocation
self.location = value.location
}
.onEnded{ value in
if(value.translation.width > bround.size.width/2) {
self.location.x = bround.size.width - 30
}
else {
self.location.x = 30
}
}
// .updating($startLocation) { (value, startLocation, transaction) in
// startLocation = startLocation ?? location
// }
}
var body: some View {
Image(systemName: "bubble.right.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50)
.animation(.easeInOut, value: location)
.position(location)
.gesture(simpleDrag)
.onTapGesture {
self.isShow.toggle()
if(isShow) {
self.location.x = bround.width/2
}
else {
self.location.x = 30
}
}
}
}