I am using Skiasharp on Xamarin Forms app. With SKTouchAction I was trying to capture the time duration of SKTouchAction.Pressed and SKTouchAction.Released and find if the gesture is Long pressed or not. But the issue is SKTouchAction.Released is not triggered on Android.
protected override void OnTouch(SKTouchEventArgs e)
{
switch (e.ActionType)
{
case SKTouchAction.Moved:
break;
case SKTouchAction.Pressed:
//save current time here
break;
case SKTouchAction.Released:
//Compare time here to check long press
break;
}
}
There is a similar issue on the github. It seems you need to let the OS know that you wanted to continue receiving touch events. Such as:
protected override void OnTouch(SKTouchEventArgs e)
{
e.Handled = true;
switch (e.ActionType)
{
case SKTouchAction.Moved:
break;
case SKTouchAction.Pressed:
//save current time here
break;
case SKTouchAction.Released:
//Compare time here to check long press
break;
}
}
In addition, you can also refer to this case.
Related
For a project, I need to do a processing code able to switch between two completely different states. There is a default state and it switches to the special state when the mouse is pressed. The special state have an initialization phase. It also have an end and when it reaches it, the program switches back to the normal state. The way I would implement this is the following :
boolean isNormal;
void setup(){
//setup things...
isNormal = true;
}
void draw(){
if(isNormal){
normal();
}
else{
special();
if (endReached){
isNormal = true;
}
}
}
void mousePressed(){
specialSetup();
isNormal = false;
}
void normal(){
//normal routine...
}
void special(){
//special routine...
}
Is there a better way to do it (more efficient, cleaner, ...) ?
I'm using this well documented solution to add a back button to our app. I'm setting things up like this when the App is initialized:
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested += CreateNewKeyView_BackRequested;
private void CreateNewKeyView_BackRequested(object sender, BackRequestedEventArgs e)
{
NavigationService.Instance.GoBack();
}
The back button is shown on the desktop app and works as expected, navigating our Frame back to previous pages.
However, on Windows Phone, the hardware button just exits the app. The various places that I found code like this all state that this should work for the mobile hardware button, but it simply isn't working for us.
You should set e.Handled = true in your CreateNewKeyView_BackRequested method.
Don't know how you code for your NavigationService, I just tested the following code, it works by my side:
private void CreateNewKeyView_BackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame != null)
{
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
}
Or, for a phone, we use also special API for Hardware Buttons.
You can judge if the current using a phone Api is or not in the OnLaunched method:
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
Windows.Phone.UI.Input.HardwareButtons.BackPressed += OnBackPressed;
}
then complete the OnBackPressed method:
public void OnBackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame != null)
{
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
}
To do this, you need at first add the Windows Mobile Extensions for the UWP references in your project.
Here is
private void CreateNewKeyView_BackRequested(object sender, BackRequestedEventArgs e) //event handle nya untuk backbutton
{
var frame = ((Frame)Window.Current.Content);
if (frame.CanGoBack)
{
frame.GoBack();
e.Handled = true;
}
}
My scenario is , When I navigate to a new page It takes some time to load the content. And for that duration of time, If I press back key it throws exception for some reason. So I want to stop the back key behaviour for that much duration and when content is fully loaded, user can press the back key and then navigate to previous page. I just want to be clear, Is it permitted in application certification requirement from microsoft so that my app could not get rejected. so please give answer.
You could do something like this:
bool flag = false;
// Assuming this is where you can handle executions during loading
loading()
{
flag = true;
}
// After loading is completed
loadComplete()
{
flag = false;
}
// Handle back button
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (flag)
{
e.Cancel = true;
}
}
As long as you don't lock the user to never allow him to go back, it should pass the certification.
In xaml
<phone:PhoneApplicationPage
.....
BackKeyPress="PhoneApplicationPage_BackKeyPress">
In code
private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = CouldStepBack();
}
private bool CouldStepBack()
{
// todo return true, when load comleted
// else return false
}
And if you need you also can clean stack of pages (optional)
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationService.CanGoBack)
{
while (NavigationService.RemoveBackEntry() != null)
{
NavigationService.RemoveBackEntry();
}
}
base.OnNavigatedTo(e);
}
Hope its help
Declare a GeoCoordinateWatcher tracker. This tracker will start on PageOnload event as below.
I dont know how to create a condition such that it will show this :case GeoPositionStatus.NoData, So I need some advise. My objective is it will re-start until it gets the current Latitude and longitude.
Q1) for case GeoPositionStatus.NoData, what will be the best practice to re-start the GeoCoordinateWatcher?
Do this in case GeoPositionStatus.NoData
tracker.Stop();
tracker.Start();
void tracker_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
switch (e.Status)
{
case GeoPositionStatus.Disabled:
if (tracker.Permission == GeoPositionPermission.Denied)
{
MessageBox.Show("The location Service on this device is off.Please read privacy.");
}
else
{
MessageBox.Show("Location service is working but it can not get location data.");
}
break;
case GeoPositionStatus.Initializing:
// Code which needs to be initialized goes here
break;
case GeoPositionStatus.NoData:
//MessageBox.Show("Location data is not available.");
break;
case GeoPositionStatus.Ready:
// Code which needs to be executed when location data is available goes here
break;
}
}
Is there a way I can detect this? I want to keep performing an action as long as the user is holding on an icon.
Instead of using the GestureListener for this you could instead use the mouse manipulation events to detect how long to perform your action. For instance:
Listen for MouseLeftButtonDown to know when the user has touched the icon
Keep performing the action until either MouseLeftButtonUp or MouseLeave fire indicating that the user is no longer touching that icon
You may also have to play with MouseEnter for initiating the action
Today only i did the same thing in my project.I'll tell you the basic logic what i implemented(assuming it has to be done on button).Step 1: On the button _ManipulationStarted_ event start a timer with the interval after which you want to fire the repeat action.
Step 2: On the button _ManipulationCompleted_ event stop the timer.
Step 3: If the timer is fired,stop the timer and start another timer with interval = the repeat interval for your action.And inside the second timer fire handler perform your operation only if the control has focus. In this case, where the control is a button, you can check if the button.IsPressed is true then perform action.
The code will look something like:
Button forward=new Button();
DispatcherTimer forwardHoldTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(2) };
forward.ManipulationStarted += (a, b) => { forwardHoldTimer.Start(); };
forward.ManipulationCompleted += (c, d) => { forwardHoldTimer.Stop(); };
forwardHoldTimer.Tick+=(s1,e1)=>
{
forwardHoldTimer.Stop();
DispatcherTimer t = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(100) };
t.Tick += (x, y) =>
{
if (forward.IsPressed)
{
//Your action logic will go here
}
else
t.Stop();
};
t.Start();
};
Hope this helps.
NOTE: Amresh Kumar was correct in suggesting using the manipulation events. Also, I was given the same advice on the Windows Phone App Hubs forums so I've edited this post to reflect the code changes.
Before, the UX was flaky because lifting my finger off the screen didn't always trigger a cancellation. Not surprisingly, the GestureCompleted code in the toolkit appears to be better geared towards touchscreens than are mouse button events.
XAML:
<iconControls:iconUpDownArrow>
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener Tap="RangeUpTap" Hold="RangeUpHold" GestureCompleted="RangeUpCancel" />
</toolkit:GestureService.GestureListener>
</iconControls:iconUpDownArrow>
code:
private void RangeUpTap(object sender, GestureEventArgs e)
{
RangeIncrementUp(sender, e);
}
private readonly TimeSpan _rangeIncrementTimeSpan = new TimeSpan(1500000);
private readonly DispatcherTimer _rangeIncrementTimer = new DispatcherTimer();
private void RangeUpHold(object sender, GestureEventArgs e)
{
_rangeIncrementTimer.Interval = _rangeIncrementTimeSpan;
_rangeIncrementTimer.Tick += RangeIncrementUp;
_rangeIncrementTimer.Start();
}
private void RangeUpCancel(object sender, GestureEventArgs e)
{
_rangeIncrementTimer.Stop();
_rangeIncrementTimer.Tick -= RangeIncrementUp;
}
private void RangeIncrementUp(object sender, EventArgs e)
{
int range = Convert.ToInt32(tBoxRange.Text);
if (range < 1000)
{
range += 10;
}
tBoxRange.Text = range.ToString();
}