14 KiB
MarketAlly.TouchEffect.Maui
A comprehensive touch effect library for .NET MAUI applications by MarketAlly, providing rich interaction feedback and animations across all platforms. MarketAlly.TouchEffect.Maui brings advanced touch handling, hover states, long press detection, and smooth animations to any MAUI view.
What's New in v2.0.0
- .NET 10 Support - Updated to target .NET 10 with latest MAUI
- TouchBehavior - New Behavior-based API as modern alternative to Effects
- Thread-Safe Architecture - Complete thread-safety overhaul with proper synchronization
- Enhanced Logging - Integrated logging throughout with
ITouchEffectLoggerinterface - Improved Code Organization - TouchEffect split into partial classes for maintainability
- Bug Fixes - Fixed
ForceUpdateStateWithoutAnimationto actually disable animations - Performance - Replaced LINQ with for-loops in hot paths to reduce allocations
Features
Core Capabilities
- Universal Touch Feedback - Consistent touch interactions across iOS, Android, and Windows
- 50+ Customizable Properties - Fine-grained control over every aspect of the touch experience
- Hardware-Accelerated Animations - Smooth, performant transitions using platform-native acceleration
- Accessibility First - Full keyboard, screen reader, and assistive technology support
- Memory Efficient - WeakEventManager pattern prevents memory leaks
- Thread-Safe - Proper synchronization for animation state management
Visual Effects
- Opacity Animations - Fade effects on touch with customizable values
- Scale Transformations - Grow or shrink elements during interaction
- Color Transitions - Dynamic background color changes for different states
- Translation & Rotation - Move and rotate elements during touch
- Native Platform Effects - Android ripple effects and iOS haptic feedback
Advanced Features
- Long Press Detection - Configurable duration with separate command binding
- Hover Support - Mouse and stylus hover states on supported platforms
- Toggle Behavior - Switch-like functionality with persistent state
- Gesture Threshold - Configurable movement tolerance before cancellation
- Command Pattern - MVVM-friendly with ICommand support
Platform Support
| Platform | Version | Features |
|---|---|---|
| iOS | 13.0+ | Full support with haptic feedback |
| Android | API 24+ | Full support with native ripple effects |
| Windows | 10.0.17763+ | Full support with WinUI 3 animations |
| Mac Catalyst | - | Not currently supported |
| Tizen | - | Not currently supported |
Installation
Package Manager
Install-Package MarketAlly.TouchEffect.Maui -Version 2.0.0
.NET CLI
dotnet add package MarketAlly.TouchEffect.Maui --version 2.0.0
PackageReference
<PackageReference Include="MarketAlly.TouchEffect.Maui" Version="2.0.0" />
Quick Start
1. Configure Your App
In your MauiProgram.cs:
using MarketAlly.TouchEffect.Maui.Hosting;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiTouchEffect() // Add this line
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
return builder.Build();
}
}
2. Add Touch Effects to Your Views
XAML Approach (Attached Properties)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:touch="clr-namespace:MarketAlly.TouchEffect.Maui;assembly=MarketAlly.TouchEffect.Maui"
x:Class="YourApp.MainPage">
<StackLayout Padding="20">
<!-- Simple Button Effect -->
<Frame touch:TouchEffect.PressedScale="0.95"
touch:TouchEffect.PressedOpacity="0.7"
touch:TouchEffect.AnimationDuration="100"
touch:TouchEffect.Command="{Binding TapCommand}">
<Label Text="Tap Me" HorizontalOptions="Center" />
</Frame>
<!-- Card with Hover Effect -->
<Frame touch:TouchEffect.PressedScale="0.98"
touch:TouchEffect.HoveredScale="1.02"
touch:TouchEffect.HoveredBackgroundColor="LightGray"
touch:TouchEffect.AnimationDuration="200"
touch:TouchEffect.AnimationEasing="{x:Static Easing.CubicInOut}">
<Label Text="Hover or Touch Me" />
</Frame>
<!-- Native Ripple Effect (Android) -->
<Frame touch:TouchEffect.NativeAnimation="True"
touch:TouchEffect.NativeAnimationColor="Blue"
touch:TouchEffect.Command="{Binding SelectCommand}">
<Label Text="Native Effect" />
</Frame>
</StackLayout>
</ContentPage>
NEW: TouchBehavior Approach (v2.0.0)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:touch="clr-namespace:MarketAlly.TouchEffect.Maui;assembly=MarketAlly.TouchEffect.Maui"
x:Class="YourApp.MainPage">
<Button Text="Click Me">
<Button.Behaviors>
<touch:TouchBehavior
PressedScale="0.95"
PressedOpacity="0.8"
AnimationDuration="100"
Command="{Binding TapCommand}" />
</Button.Behaviors>
</Button>
</ContentPage>
Fluent Builder Approach
using MarketAlly.TouchEffect.Maui;
// Configure a button with fluent API
var button = new Frame { Content = new Label { Text = "Click Me" } }
.ConfigureTouchEffect()
.AsButton()
.WithCommand(viewModel.TapCommand)
.Build();
// Create a card with hover effect
var card = new Frame { Content = contentView }
.ConfigureTouchEffect()
.AsCard()
.WithCommand(viewModel.SelectCommand)
.Build();
// Apply a preset
var listItem = new StackLayout()
.WithListItemPreset();
Using Presets
// Apply common UI patterns instantly
TouchEffectPresets.Button.ApplyPrimary(myButton);
TouchEffectPresets.Card.ApplyElevated(myCard);
TouchEffectPresets.ListItem.Apply(myListItem);
TouchEffectPresets.IconButton.ApplyFloatingAction(myFab);
// Or use extension methods
myButton.WithButtonPreset();
myCard.WithCardPreset();
myListItem.WithListItemPreset();
Logging Configuration
Configure logging to debug touch effect issues:
// Use the default console logger
TouchEffect.SetLogger(new DefaultTouchEffectLogger());
// Or implement custom logging
public class MyLogger : ITouchEffectLogger
{
public void LogError(Exception ex, string context, string? info = null)
{
// Log to your preferred service (App Center, Sentry, etc.)
}
public void LogWarning(string message, string context)
{
Debug.WriteLine($"[TouchEffect Warning] {context}: {message}");
}
public void LogInfo(string message, string context)
{
// Optional info logging
}
}
// Configure in your app startup
TouchEffect.SetLogger(new MyLogger());
Common Use Cases
Interactive Cards
<Frame CornerRadius="10"
touch:TouchEffect.PressedScale="0.95"
touch:TouchEffect.AnimationDuration="150"
touch:TouchEffect.Command="{Binding OpenDetailCommand}"
touch:TouchEffect.CommandParameter="{Binding .}">
<StackLayout>
<Image Source="{Binding ImageUrl}" />
<Label Text="{Binding Title}" FontAttributes="Bold" />
<Label Text="{Binding Description}" />
</StackLayout>
</Frame>
Toggle Buttons
<Frame touch:TouchEffect.IsToggled="{Binding IsSelected}"
touch:TouchEffect.PressedBackgroundColor="Green"
touch:TouchEffect.NormalBackgroundColor="Gray">
<Label Text="Toggle Me" />
</Frame>
Long Press Actions
<Image Source="photo.jpg"
touch:TouchEffect.Command="{Binding TapCommand}"
touch:TouchEffect.LongPressCommand="{Binding ShowMenuCommand}"
touch:TouchEffect.LongPressDuration="500" />
API Reference
For complete API documentation, see API_Reference.md.
Quick Reference
| Category | Key Properties |
|---|---|
| State | IsAvailable, IsToggled, Status, State |
| Commands | Command, CommandParameter, LongPressCommand, LongPressDuration |
| Visual | PressedOpacity, PressedScale, PressedBackgroundColor |
| Hover | HoveredOpacity, HoveredScale, HoveredBackgroundColor |
| Animation | AnimationDuration, AnimationEasing, PulseCount |
| Native | NativeAnimation, NativeAnimationColor, NativeAnimationRadius |
Performance Tips
- Keep Animations Short - Use durations under 300ms for responsive feel
- Prefer Scale Over Size - Scale transformations are GPU-accelerated
- Use Native Animations - Enable platform-specific effects when possible
- Limit Simultaneous Effects - Too many concurrent animations can impact performance
- Test on Lower-End Devices - Ensure smooth performance across all target devices
Accessibility
TouchEffect.Maui is fully accessible by default:
- Keyboard Navigation - Full support for Tab, Enter, and Space keys
- Screen Readers - Compatible with VoiceOver, TalkBack, and Narrator
- Focus Indicators - Proper focus visualization
- Touch Exploration - Support for accessibility touch modes
<!-- Accessible button with semantic properties -->
<Frame touch:TouchEffect.Command="{Binding SubmitCommand}"
SemanticProperties.Description="Submit form button"
SemanticProperties.Hint="Double tap to submit">
<Label Text="Submit" />
</Frame>
Troubleshooting
Touch Not Working
- Verify
IsAvailableis true - Check parent view
InputTransparentsettings - Ensure view has appropriate size (not 0x0)
- Enable logging to see detailed diagnostics
Animations Stuttering
- Reduce
AnimationDuration - Disable debug mode for testing
- Check for layout cycles during animation
Platform-Specific Issues
iOS: Ensure View.UserInteractionEnabled is true in custom renderers
Android: For API 21+, native ripple requires a bounded view
Windows: Hover only works with mouse/pen, not touch input
Contributing
We welcome contributions! Please see our Contributing Guide for details.
Building from Source
# Clone the repository
git clone https://git.marketally.com/marketally/TouchEffect.Maui.git
# Build the project
dotnet build src/Maui.TouchEffect/TouchEffect.Maui.csproj
# Run tests
dotnet test
# Pack NuGet package
dotnet pack src/Maui.TouchEffect/TouchEffect.Maui.csproj
Changelog
Version 2.0.0 (2025-01)
- .NET 10 Support: Updated to target .NET 10 with latest MAUI packages
- TouchBehavior: New
TouchBehaviorclass as modern Behavior-based alternative to Effects - Thread-Safety: Complete overhaul with proper
locksynchronization inGestureManager - Logging Integration: Full logging throughout codebase via
ITouchEffectLogger - Code Organization:
TouchEffectsplit into partial classes (Core, Properties, Accessors) - Bug Fix:
ForceUpdateStateWithoutAnimationnow correctly passesanimated: false - Performance: Replaced LINQ with for-loops in hot paths (
HasTouchEffect,GetFrom,PickFrom) - CancellationToken Disposal: Proper null-before-dispose pattern to prevent race conditions
Version 1.0.0 (2024-11)
- Fluent Builder Pattern: New intuitive API for configuring touch effects
- Preset Configurations: 20+ pre-built configurations for common UI patterns
- Centralized Constants: Eliminated magic numbers throughout codebase
- Logging Interface: Comprehensive error handling and debugging support
- Windows Support: Full Windows platform implementation with WinUI 3
- Code Quality: Partial classes, improved organization, and documentation
- Bug Fixes: Fixed .NET 9 compatibility issues
- Documentation: Enhanced XML documentation for all public APIs
Version 8.1.0
- Initial release as MarketAlly.TouchEffect.Maui
- Ported from original TouchEffect for .NET MAUI
- Full iOS and Android support
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Based on the original TouchEffect by Andrei (MIT License)
- Original Xamarin Community Toolkit team
- .NET MAUI team
- All contributors
Support
- Report Issues
- Star this repository if you find it helpful!
Made with care by MarketAlly for the .NET MAUI Community
Based on the original TouchEffect by Andrei - Used under MIT License