Using Xamarin Forms, I'm trying to understand at which offset during swiping will my SwipeView trigger the Invoked event when using mode Execute and if it's possible to programmatically get this value. So far what I've seen is it seems to be around 60% of Threshold (at least for Android) but I'm curious to know if this value is available somewhere in the component. I originally thought it wouldn't be triggered until it hit Threshold but I found that it fires before it meets that value. Below is my XAML:
<SwipeView
SwipeChanging="SwipeView_SwipeChanging"
SwipeEnded="SwipeView_SwipeEnded"
SwipeStarted="SwipeView_SwipeStarted"
Threshold="80">
<SwipeView.TopItems>
<SwipeItems Mode="Execute" SwipeBehaviorOnInvoked="Close">
<SwipeItemView BackgroundColor="Transparent" Invoked="SwipeItemView_Invoked">
<Label Text="Create New Task" />
</SwipeItemView>
</SwipeItems>
</SwipeView.TopItems>
<SwipeView.Content>
...
</SwipeView.Content>
</SwipeView>
With the above example with Threshold at 80 it seems to trigger around 49/50.
Related
I'm trying to test touchscreen of a tablet (Surface) and therefore I'm developing an app that is able to detect tap event and tell its coordinates.
I made a tap event handler to main Grid in MainPage and wrote this to MainPage.xaml.cs:
outputText.Text = e.GetPosition(this).X.ToString() + "\t";
outputText.Text += e.GetPosition(this).Y.ToString();
outputText is just a TextBlock to output coordinates.
This code should give its coordinates based on Grid, but it only gives coordinates if I touch it within TextBlock area.
How does this Tapped event handler work in a way that it only detects tap events inside TextBlock and not from entire screen (app runs in fullscreen mode)?
My MainPage.xaml looks like this:
<Grid Tapped="Grid_Tapped" PointerPressed="Grid_PointerPressed">
<TextBlock x:Name="outputText" HorizontalAlignment="Left" Height="62" Margin="806,374,0,0" Text="TextBlock" TextWrapping="Wrap" VerticalAlignment="Top" Width="182"/>
</Grid>
The problem is that the Grid.Background is null, so the tap events pass through it. The only place where the Grid has any actual "surface" is the TextBlock, which is exactly what you are seeing.
You will have to set the background to any other value like Transparent. This way it will handle the events properly.
Context
I am discovering step by step Exrin infrastructure. I explored that there are many ready to use infra element to implement command execution in background. Among those I see IsBusyDelay, VisualState.IsBusy, Timeout message, etc. I also know that Exrin does not depend on Xamarin.Forms, so I suppose, no real visual implementation should be provided by Exrin, that very last step remains on me. (which is cool, let me decide the UI experience)
In my ViewModel I set IsBusyDelay = 1000;. The background task is started by Execution.ViewModelExecute(... my task here ..., currently 5000msec delay )
Question
I suppose now I have to implement somewhere a handler(s) or override(s) which will be called automatically, and implement some visual UX to show and hide the a busy/inprogress UX feedback. I just do not know where and how...
This is something you would implement yourself in the view. For example, if you wanted something that covered the whole screen, with a loading indicator, you would add this to your UI.
<Grid HorizontalOptions="FillAndExpand"
IsVisible="{Binding VisualState.IsBusy}"
BackgroundColor="#E6272C30"
VerticalOptions="FillAndExpand">
<Grid HorizontalOptions="Center" VerticalOptions="CenterAndExpand"
Height="200">
<ActivityIndicator Grid.Row="0"
IsRunning="{Binding VisualState.IsBusy}"
IsVisible="{Binding VisualState.IsBusy}">
<ActivityIndicator.Scale>
<OnPlatform x:TypeArguments="x:Double" Android="1" iOS="1.3" />
</ActivityIndicator.Scale>
</ActivityIndicator>
</Grid>
</Grid>
You would add this at the bottom of the page, inside your existing Grid.
Then when IsBusy is trigger, it shows this as an overlay, with the activity indicator.
Of course that is only one way to do it. You could just have an activityindicator next to, or inside a button that was just clicked, or anything similar. It all depends on your UI design.
In my nativescript app I noticed that sometimes the tap does not trigger right a way. I have to tap several times to trigger the event. This happens on both, android and ios.
How can I increase the tap hot zone? What else could be causing this to happen?
Thank you.
P.S. I tried increasing the padding of the element whose tap event I am capturing, but that did not seem to help.
I often increase the height and width of the view that have the tap event. You can give it a try.
There are a few factors at play here.
First, when you intercept a page-level event in NativeScript it seems to stop events from other widgets from firing. For example, if you tap on a text field but have a page-level listener for tap events, the tap on the TextField will be intercepted by the page-level listener.
Second, Double-tapping seems to exploit a timing issue in events, allowing the tap event to bubble up to the next listening widget.
Finally, when you have padding on the element you're trying to tap, the tap does not register on the padded areas. It will appear that you can only tap in the middle of the widget (inside of the padded area). In my case, the TextField on which I had padding had to be tapped directly in the vertical center (and that was with a padding of 5px).
To test it, try removing the padding from the element and see if the tapping works normally again.
I was able to create a very smooth / natural experience with the software keyboard by doing the following:
Wrap the TextField in a StackLayout and putting padding on the StackLayout instead of the widget
Add the page-level listener that dismisses the software keyboard ONLY when the textfield is tapped, and remove it once that listener is fired.
ex: XML file
<StackLayout id="loginFieldWrapper" padding="5 5 5 5">
<TextView hint="Enter Login ID" id="loginField" keyboardType="number" returnKeyType="done" returnPress="{{hideKeyboard}}" />
</StackLayout>
Backing javascript file
loginField.on(gestures.GestureTypes.tap, function(args) {
page.on(gestures.GestureTypes.tap, function (args) {
loginField.dismissSoftInput();
page.off(gestures.GestureTypes.tap);
});
});
Wrap the item inside some layout to increase the clickable area
<StackLayout (tap)="select(param)">
<Label text="{{description}}" textWrap="true" marginTop="40px" marginBottom="40px">
</Label>
</StackLayout>
I created a simple application with ListBox and 1000 very short strings in it. (no explicit ItemTemplate).
If i scroll it really fast - there are black holes(CPU cant render fast i suppose).
At the same time if i use ItemsControl in ScrollViewer - everything is OKay.
Why ? Can i slow down scrolling speed in ListBox somehow ?
Users can get really confused when they are to see these black holes in the screen.
Update: Reproduces on device(HTC HD7 7.10.7740). I use databinding via ItemSource
Repro project: https://www.dropbox.com/s/lgcod878srnctp0/SLTK_LLS_TEST.zip
Repro video(!): https://www.dropbox.com/s/t25dguq0vaa88o9/WP_20111213_113729Z.mp4
The ListBox has "virtualization" enabled by default (exactly: sort of UI container virtualization), it's not loading the complete list, just fragments. When scrolling, it has to render the items first, and when you scroll quickly, you are noticing this rendering delay. It's achieved by the VirtualizingStackPanel. The advantage is, it saves Memory.
You can disable the virtualization when using a custom ItemsPanel:
<ListBox x:Name="YourListbox">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
...but the solution will take up more resources from the beginning. Might become dangerous with long lists.
The other way round, you can enable virtualization on your ItemsControl, for a testing purpose, you should be able to achieve the rendering delay ("black holes").
How long are your strings? Is it something you can easily and sensibly split into a very brief summary (8 - 10 characters)? If so you might want to take a look at the LazyListBox which tries to address the issue (it was intended for more complex layouts than you are talking about, though, so the benefits may be negligible)
I'm building a custom control in Silverlight and I want one of the fields to animate to the value of a DependencyProperty when that property is changed. More specifically, I have particular item in my Control Template that I want to animate to the color of the Background whenever the background changes color. So, what I have is:
<ControlTemplate TargetType="local:MyType">
<Grid x:Name="PART_RootElement">
<Grid.Resources>
<Storyboard x:Name="PART_FillAnimation">
<ColorAnimationUsingKeyFrames
BeginTime="00:00:00"
Storyboard.TargetName="PART_MainPath"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<EasingColorKeyFrame
x:Name="PATH_FillKeyframe"
KeyTime="00:00:01"
Value="{TemplateBinding Background}"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<!-- the rest of the template -->
I'm triggering the animation in the custom control code, but when the animation starts, it doesn't look like the Value is updating. I was just wondering if I'm missing something or if it is at all possible to apply TemplateBinding to resources in my ControlTemplate.
(I'm currently using a work-around of manually assigning the Background to the EasingColorKeyFrame Value, but the TemplateBinding solution would be so much cleaner.)
Have a look at Expression Blend Samples as a possible solution to your problem. There are a number of Interactivity classes that you could use within your ControlTemplate to create the effect your looking for. The documentation is not great, but descriptions in the Object Browser should give you some more clues :)
For example, I have a ListBox ItemTemplate that contains a ControlStoryboardAction Behaviour. The trigger for this Behaviour is a DataTrigger which fires when a DataContext field contains a specific value. (In my case when Severity=="High") The trigger then Plays a Storyboard within the ItemTemplate.
<i:Interaction.Triggers>
<is:DataTrigger Binding="{Binding Severity, Mode=OneWay}" Value="High">
<im:ControlStoryboardAction Storyboard="{StaticResource flashLight}" IsEnabled="True" />
</is:DataTrigger>
The following namespaces are referenced:
<i: - System.Windows.Interactivity
<is: - Expression.Samples.Interactivity (available from the link above. I am using the July 2009 release for SL3)
<im: - Microsoft.Expression.Interactivity.Media