I am making drag & drop lazyVGrid.
i did reference this answer
SwiftUI | Using onDrag and onDrop to reorder Items within one single LazyGrid?
when drag move another item position it working well
but when I long press and not move and drop itself
self.dragging not set to nil
how can I fix it??
I would try to do like this.
.gesture(DragGesture()
.onChanged({ value in
if value.x == 0 && value.y == 0 {
self.dragging = nil
}
})
)
Related
Implement the proposed solution to do drag and drop in this thread:
SwiftUI | Using onDrag and onDrop to reorder Items within one single LazyGrid?
The problem I have is that I want to play a vibration when the drag starts and I don't get it.
I did the following:
.onDrag(){
let impact = UIImpactFeedbackGenerator(style: .light)
impact.impactOccurred()
self.dragging = module
return NSItemProvider(object: String(module.id) as NSString)
}
But if I drop the item on itself (to cancel or by accident). The next time I try to drag it, the onDrag() method is not executed.
How could I fix it?
I have this scenario:
The first user that joins a lobby will have an active button on his screen. After some actions, if the player hit the button, it will disable, and then the next player in the room will have this button active, and so on.
Based on a property 'Turn' I want to change this button state like this.
In this function PassTurn I first set for the LocalPlayer the Turn property to false and then I determine the next player using some logic, and set for that player the Turn property to true.
private PassTurn()
{
PunHashtable _myCustomProperties_forCurrentPlayer = new PunHashtable();
_myCustomProperties_forCurrentPlayer["Turn"] = false;
PhotonNetwork.LocalPlayer.SetCustomProperties(_myCustomProperties_forCurrentPlayer);
foreach (Player player in PhotonNetwork.PlayerList)
{
// ... some logic to determine the next player to set the 'Turn' property to true
if (someCondition for player) {
PunHashtable _myCustomProperties_forNextPlayer = new PunHashtable();
_myCustomProperties_forNextPlayer["Turn"] = true;
player.SetCustomProperties(_myCustomProperties_forNextPlayer);
}
}
}
In OnPlayerPropertiesUpdate function, if Turn property ever change, activate or deactivate the button based on Turn property value (if true - show the button, if false don't display the button).
public override void OnPlayerPropertiesUpdate(Player targetPlayer, ExitGames.Client.Photon.Hashtable changedProps)
{
base.OnPlayerPropertiesUpdate(targetPlayer, changedProps);
if (targetPlayer != null) {
if (changedProps.ContainsKey("Turn"))
{
{
foreach (Player player in PhotonNetwork.PlayerList)
{
// this print will display (1, false) and (2, false) which is not correct, because the second player doesn't have de property changed
print(player.ActorNumber + player.CustomProperties["Turn"];
if ((bool)player.CustomProperties["Turn"] == true)
{
print("HEY HEY HEY 1");
endTurnBtn.SetActive(true);
}
if ((bool)player.CustomProperties["Turn"] == false)
{
print("HEY HEY HEY 2");
endTurnBtn.SetActive(false);
}
}
}
}
}
}
This is not working properly since it will always enter on HEY HEY HEY 2., the button for the current play will disappear, but it will never appear on the next player.
Which is the right approach for this situation? How can I change ui components on other players screen? Thank you for your time!
LaterEdit based on accepted comment:
public override void OnPlayerPropertiesUpdate(Player targetPlayer, ExitGames.Client.Photon.Hashtable changedProps)
{
base.OnPlayerPropertiesUpdate(targetPlayer, changedProps);
if (targetPlayer != null) {
if (changedProps.ContainsKey("Turn"))
{
{
if ((bool)PhotonNetwork.LocalPlayer.CustomProperties["Turn"] == true)
{
print("HEY HEY HEY 1");
endTurnBtn.SetActive(true);
}
if ((bool)PhotonNetwork.LocalPlayer.CustomProperties["Turn"] == false)
{
print("HEY HEY HEY 2");
endTurnBtn.SetActive(false);
}
}
}
}
}
you iterate over every player and check the variable, so as soon as the last player in your list has the turn property false every player will disable the button, while when the last players turn property is true every player will activate the button.
Either way it makes no sense to iterate over every player in the room, since you only want to change the locally shown button. Therefore you should only check the local player/players and change the button accordingly.
Imagine some standard Unity UI ScrollView. You grab it with your mouse and start dragging it so it is scrolling with your mouse. How do I programmatically make it stop scrolling while mouse button is still down? Is there any way to make ScrollRect think that user is released mouse button?
Quite old question, but I found exactly this same problem and no clean solution. My problem was to have scrollRect with items which I can scroll left/right but when user select one item and drag it up then scrollRect should cancel scrolling and allow user to drag item up. I achieved this by temporary setting ScrollRect.enable to false, and after few ms set it back to true.
Here is part of mu code which do this. Maybe somebody find this useful.
void Update()
{
if (state == DragState.Started) {
dragStart = Input.mousePosition;
state = DragState.Continued;
}
if (state == DragState.Continued) {
Vector3 pos = Input.mousePosition;
if (pos.y - dragStart.y > 80) {
scrollRect.enabled = false;
state = DragState.None;
Invoke("ReenableScroll", 0.01f);
}
}
}
private void ReenableScroll() {
scrollRect.enabled = true;
}
Its not easy to make the EventSystem think something has happend while it hasn't. I believe its much easier to implement your own ScrollRect logic and parse the mouse input yourself
You can call ScrollRect's OnEndDrag() method with artificial PointerEventData.
var forceEndDragData = new PointerEventData(EventSystem.current)
{
button = PointerEventData.InputButton.Left
};
_scrollRect.OnEndDrag(forceEndDragData);
Context
I am making a mobile game in which the player is required to touch objects in a specified order. The correct order is determined in a List called clickOrder. To determine the current object the player is supposed to click, currClickIndex is used.
Problem
When touching a correct object, the debug text will display "Correct" for a split second, and will then immediately change to "Wrong." What I am unsure about is why both the if and else blocks are executed when only touching a single object.
Code
void Update()
{
if (Input.touchCount == 1)
{
if (this.enabled)
{
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero);
if (hit != null && hit.collider != null)
{
// check if the touched object is the correct one
if (hit.collider.gameObject == clickOrder[MyData.currClickIndex])
{
debug.text = "Correct";
MyData.currClickIndex++;
}
else
{
debug.text = "Wrong";
}
}
}
}
}
As soon as the correct object is being touched, you do this:
MyData.currClickIndex++;
which moves you forward in the ordered sequence, and from then on, the previously correct object is not correct anymore. But you're still touching it.
If you want to avoid this, you need to move forward in the sequence after you've touched the correct object.
if (there are touches and the correct object is being touched)
{
set a flag;
}
else if (a flag has been set)
{
MyData.currClickIndex++;
reset the flag;
}
I'm tired to handle and solve issues related to multitouch. I'm using maximum 5 touches simultaneously but when two touches are down on two objects and I moved my fingers then that both touches fired TouchPhase.Ended event but not TouchedPhase.Canceled.
I want to fire TouchPhase.Canceled when my fingers are out of those objects.
if (touch.phase == TouchPhase.Began) {
hitObject.GetComponent ().TouchDown (hitObject);
}
if (touch.phase == TouchPhase.Ended) {
hitObject.GetComponent ().TouchExit (hitObject);
}
if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary) {
hitObject.GetComponent ().TouchStay (hitObject);
}
if (touch.phase == TouchPhase.Canceled) {
print ("Touched canceled....");
hitObject.GetComponent ().TouchExit (hitObject);
}
If i understand your comment correctly
Look,I have one object on my screen.I use raycast for detecting that object.in hitObject i m stored that hittedObject and when my fingure touchdown on that object then it works. if i touchup my fingure from that hitted object that is also worked.when my fingure is stayed on that object or i m move my fingure on that hitted object that is also worked. but when during moving my fingure if it is move outside that object at that time TouchPhase.Canceled event should be fired. but that can not worked . That is my issue. How can i solved it ?
and
I want to stop dragging/swapping finger (not moving) on that hitted object how can i do?
you are going to have to restrict the swiping based on the touch position.
var realWorldPos = Camera.main.ScreenToWorldPoint(touch.position);
if(realWorldPos.x < maximumXSwipePosition && realWorldPos.x > minimumXSwipePosition)
{
//do the stuff you want to do
}
//otherwise, don't do it.