Skip to content

feat: Use DependencyPropertyGenerator #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -395,4 +395,5 @@ FodyWeavers.xsd
*.msp

# JetBrains Rider
*.sln.iml
*.sln.iml
.idea
8 changes: 8 additions & 0 deletions BarcodeScanning.Native.Maui.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BarcodeScanning.Native.Maui
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BarcodeScanning.Test", "BarcodeScanning.Test\BarcodeScanning.Test.csproj", "{E858DBA6-F917-4145-A741-92E53E79EFD2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5882D658-28FD-4470-BF7A-D148EBCD26B7}"
ProjectSection(SolutionItems) = preProject
.gitattributes = .gitattributes
.gitignore = .gitignore
LICENCE = LICENCE
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<Description>Barcode scanning library for .NET MAUI</Description>
<PackageProjectUrl>https://github.com/afriscic/BarcodeScanning.Native.Maui</PackageProjectUrl>
<PackageTags>.NET MAUI android ios barcode-scanner</PackageTags>
<RootNamespace>BarcodeScanning</RootNamespace>

<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.1</SupportedOSPlatformVersion>
Expand All @@ -25,6 +26,10 @@
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
<PackageReference Include="DependencyPropertyGenerator" Version="1.5.0-beta.1">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this project should consume beta (pre-release) versions of nuget packages. Maybe wait, until it's released?

<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
Expand Down
255 changes: 49 additions & 206 deletions BarcodeScanning.Native.Maui/CameraView.cs
Original file line number Diff line number Diff line change
@@ -1,222 +1,61 @@
using System.Windows.Input;
using DependencyPropertyGenerator;
using Timer = System.Timers.Timer;

namespace BarcodeScanning;

[DependencyProperty<ICommand>("OnDetectionFinishedCommand",
Description = "Command that will be executed when barcode is detected.")]
[DependencyProperty<bool>("VibrationOnDetected", DefaultValue = true,
Description = "Disables or enables vibration on barcode detection. " +
"On Android make sure that the android.permission.VIBRATE permission " +
"is declared in the AndroidManifest.xml file.")]
[DependencyProperty<bool>("CameraEnabled",
Description = "Disables or enables camera.")]
[DependencyProperty<bool>("PauseScanning",
Description = "Pauses barcode scanning.")]
[DependencyProperty<bool>("ForceInverted",
Description = "Forces scanning of inverted barcodes. Reduces performance significantly. Android only.")]
[DependencyProperty<int>("PoolingInterval",
Description = "Enables pooling of detections for better detection of multiple barcodes at once. " +
"Value in milliseconds. " +
"Default 0 (disabled).")]
[DependencyProperty<bool>("TorchOn",
Description = "Disables or enables torch.")]
[DependencyProperty<bool>("TapToFocusEnabled",
Description = "Disables or enables tap-to-focus.")]
[DependencyProperty<CameraFacing>("CameraFacing",
Description = "Select Back or Front camera." +
"Default value is Back Camera.")]
[DependencyProperty<CaptureQuality>("CaptureQuality", DefaultValue = CaptureQuality.Medium,
Description = "Set the capture quality for the image analysis." +
"Recommended and default value is Medium." +
"Use highest values for more precision or lower for fast scanning.")]
[DependencyProperty<BarcodeFormats>("BarcodeSymbologies",
DefaultValue = BarcodeFormats.All,
Description = "Set the enabled symbologies." +
"Default value All.")]
[DependencyProperty<bool>("AimMode",
Description = "Disables or enables aim mode. " +
"When enabled only barcode that is in the center of the preview will be detected.")]
[DependencyProperty<bool>("ViewfinderMode",
Description = "Disables or enables viewfinder mode. " +
"When enabled only barcode that is visible in the preview will be detected.")]
[WeakEvent<OnDetectionFinishedEventArg>("OnDetectionFinished",
Description = "Event that will be triggered when barcode is detected.")]
public partial class CameraView : View
{
public static readonly BindableProperty OnDetectionFinishedCommandProperty = BindableProperty.Create(nameof(OnDetectionFinishedCommand)
, typeof(ICommand)
, typeof(CameraView)
, null
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).OnDetectionFinishedCommand = (ICommand)newValue);
public ICommand OnDetectionFinishedCommand
private readonly HashSet<BarcodeResult> _pooledResults = new();
private readonly Timer _poolingTimer = new()
{
get => (ICommand)GetValue(OnDetectionFinishedCommandProperty);
set => SetValue(OnDetectionFinishedCommandProperty, value);
}

public static readonly BindableProperty VibrationOnDetectedProperty = BindableProperty.Create(nameof(VibrationOnDetected)
, typeof(bool)
, typeof(CameraView)
, true
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).VibrationOnDetected = (bool)newValue);
/// <summary>
/// Disables or enables vibration on barcode detection.
/// </summary>
public bool VibrationOnDetected
{
get => (bool)GetValue(VibrationOnDetectedProperty);
set => SetValue(VibrationOnDetectedProperty, value);
}

public static readonly BindableProperty CameraEnabledProperty = BindableProperty.Create(nameof(CameraEnabled)
, typeof(bool)
, typeof(CameraView)
, false
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).CameraEnabled = (bool)newValue);
/// <summary>
/// Disables or enables camera.
/// </summary>
public bool CameraEnabled
{
get => (bool)GetValue(CameraEnabledProperty);
set => SetValue(CameraEnabledProperty, value);
}

public static readonly BindableProperty PauseScanningProperty = BindableProperty.Create(nameof(PauseScanning)
, typeof(bool)
, typeof(CameraView)
, false
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).PauseScanning = (bool)newValue);
/// <summary>
/// Pauses barcode scanning.
/// </summary>
public bool PauseScanning
{
get => (bool)GetValue(PauseScanningProperty);
set => SetValue(PauseScanningProperty, value);
}

public static readonly BindableProperty ForceInvertedProperty = BindableProperty.Create(nameof(ForceInverted)
, typeof(bool)
, typeof(CameraView)
, false
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).ForceInverted = (bool)newValue);
/// <summary>
/// Forces scanning of inverted barcodes. Reduces performance significantly. Android only.
/// </summary>
public bool ForceInverted
{
get => (bool)GetValue(ForceInvertedProperty);
set => SetValue(ForceInvertedProperty, value);
}

public static readonly BindableProperty PoolingIntervalProperty = BindableProperty.Create(nameof(PoolingInterval)
, typeof(int)
, typeof(CameraView)
, 0
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).PoolingInterval = (int)newValue);
/// <summary>
/// Enables pooling of detections for better detection of multiple barcodes at once.
/// Value in milliseconds. Default 0 (disabled).
/// </summary>
public int PoolingInterval
{
get => (int)GetValue(PoolingIntervalProperty);
set => SetValue(PoolingIntervalProperty, value);
}

public static readonly BindableProperty TorchOnProperty = BindableProperty.Create(nameof(TorchOn)
, typeof(bool)
, typeof(CameraView)
, false
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).TorchOn = (bool)newValue);
/// <summary>
/// Disables or enables torch.
/// </summary>
public bool TorchOn
{
get => (bool)GetValue(TorchOnProperty);
set => SetValue(TorchOnProperty, value);
}

public static readonly BindableProperty TapToFocusEnabledProperty = BindableProperty.Create(nameof(TapToFocusEnabled)
, typeof(bool)
, typeof(CameraView)
, false
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).TapToFocusEnabled = (bool)newValue);
/// <summary>
/// Disables or enables tap-to-focus.
/// </summary>
public bool TapToFocusEnabled
{
get => (bool)GetValue(TapToFocusEnabledProperty);
set => SetValue(TapToFocusEnabledProperty, value);
}

public static readonly BindableProperty CameraFacingProperty = BindableProperty.Create(nameof(CameraFacing)
, typeof(CameraFacing)
, typeof(CameraView)
, CameraFacing.Back
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).CameraFacing = (CameraFacing)newValue);
/// <summary>
/// Select Back or Front camera.
/// Default value is Back Camera.
/// </summary>
public CameraFacing CameraFacing
{
get => (CameraFacing)GetValue(CameraFacingProperty);
set => SetValue(CameraFacingProperty, value);
}

public static readonly BindableProperty CaptureQualityProperty = BindableProperty.Create(nameof(CaptureQuality)
, typeof(CaptureQuality)
, typeof(CameraView)
, CaptureQuality.Medium
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).CaptureQuality = (CaptureQuality)newValue);
/// <summary>
/// Set the capture quality for the image analysys.
/// Reccomended and default value is Medium.
/// Use highest values for more precision or lower for fast scanning.
/// </summary>
public CaptureQuality CaptureQuality
{
get => (CaptureQuality)GetValue(CaptureQualityProperty);
set => SetValue(CaptureQualityProperty, value);
}

public static readonly BindableProperty BarcodeSymbologiesProperty = BindableProperty.Create(nameof(BarcodeSymbologies)
, typeof(BarcodeFormats)
, typeof(CameraView)
, BarcodeFormats.All
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).BarcodeSymbologies = (BarcodeFormats)newValue);
/// <summary>
/// Set the enabled symbologies.
/// Default value All.
/// </summary>
public BarcodeFormats BarcodeSymbologies
{
get => (BarcodeFormats)GetValue(BarcodeSymbologiesProperty);
set => SetValue(BarcodeSymbologiesProperty, value);
}

public static readonly BindableProperty AimModeProperty = BindableProperty.Create(nameof(AimMode)
, typeof(bool)
, typeof(CameraView)
, false
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).AimMode = (bool)newValue);
/// <summary>
/// Disables or enables aim mode. When enabled only barcode that is in the center of the preview will be detected.
/// </summary>
public bool AimMode
{
get => (bool)GetValue(AimModeProperty);
set => SetValue(AimModeProperty, value);
}

public static readonly BindableProperty ViewfinderModeProperty = BindableProperty.Create(nameof(ViewfinderMode)
, typeof(bool)
, typeof(CameraView)
, false
, defaultBindingMode: BindingMode.TwoWay
, propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).ViewfinderMode = (bool)newValue);
/// <summary>
/// Disables or enables viewfinder mode. When enabled only barcode that is visible in the preview will be detected.
/// </summary>
public bool ViewfinderMode
{
get => (bool)GetValue(ViewfinderModeProperty);
set => SetValue(ViewfinderModeProperty, value);
}

public event EventHandler<OnDetectionFinishedEventArg> OnDetectionFinished;

private readonly HashSet<BarcodeResult> _pooledResults;
private readonly Timer _poolingTimer;
AutoReset = false,
};

public CameraView()
{
this.Loaded += CameraView_Loaded;
this.Unloaded += CameraView_Unloaded;

_pooledResults = new();
_poolingTimer = new()
{
AutoReset = false
};
_poolingTimer.Elapsed += PoolingTimer_Elapsed;
}

Expand Down Expand Up @@ -281,7 +120,11 @@ private void TriggerOnDetectionFinished(HashSet<BarcodeResult> barCodeResults)
var results = barCodeResults.ToHashSet();
MainThread.BeginInvokeOnMainThread(() =>
{
OnDetectionFinished?.Invoke(this, new OnDetectionFinishedEventArg { BarcodeResults = results });
RaiseOnDetectionFinishedEvent(this, new OnDetectionFinishedEventArg
{
BarcodeResults = results,
});

if (OnDetectionFinishedCommand?.CanExecute(results) ?? false)
OnDetectionFinishedCommand?.Execute(results);
});
Expand Down
23 changes: 9 additions & 14 deletions BarcodeScanning.Native.Maui/CameraViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,20 @@

namespace BarcodeScanning;

public partial class CameraViewHandler : ViewHandler<CameraView, BarcodeView>
public partial class CameraViewHandler()
: ViewHandler<CameraView, BarcodeView>(CameraViewMapper, CameraCommandMapper)
{
public static readonly PropertyMapper<CameraView, CameraViewHandler> CameraViewMapper = new()
{
[nameof(CameraView.CameraFacing)] = (handler, virtualView) => handler.UpdateCamera(),
[nameof(CameraView.CaptureQuality)] = (handler, virtualView) => handler.UpdateResolution(),
[nameof(CameraView.BarcodeSymbologies)] = (handler, virtualView) => handler.UpdateAnalyzer(),
[nameof(CameraView.TorchOn)] = (handler, virtualView) => handler.UpdateTorch(),
[nameof(CameraView.CameraEnabled)] = (handler, virtualView) => handler.HandleCameraEnabled(),
[nameof(CameraView.AimMode)] = (handler, virtualView) => handler.HandleAimModeEnabled()
[nameof(CameraView.CameraFacing)] = (handler, _) => handler.UpdateCamera(),
[nameof(CameraView.CaptureQuality)] = (handler, _) => handler.UpdateResolution(),
[nameof(CameraView.BarcodeSymbologies)] = (handler, _) => handler.UpdateAnalyzer(),
[nameof(CameraView.TorchOn)] = (handler, _) => handler.UpdateTorch(),
[nameof(CameraView.CameraEnabled)] = (handler, _) => handler.HandleCameraEnabled(),
[nameof(CameraView.AimMode)] = (handler, _) => handler.HandleAimModeEnabled()
};

public static readonly CommandMapper<CameraView, CameraViewHandler> CameraCommandMapper = new()
{
};

public CameraViewHandler() : base(CameraViewMapper, CameraCommandMapper)
{
}
public static readonly CommandMapper<CameraView, CameraViewHandler> CameraCommandMapper = new();

protected override void DisconnectHandler(BarcodeView barcodeView)
{
Expand Down
14 changes: 7 additions & 7 deletions BarcodeScanning.Native.Maui/Shared/Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ public static async Task<bool> AskForRequiredPermissionAsync()
try
{
var status = await Permissions.CheckStatusAsync<Permissions.Camera>();
if (status != PermissionStatus.Granted)
{
await Permissions.RequestAsync<Permissions.Camera>();
}
status = await Permissions.CheckStatusAsync<Permissions.Camera>();
if (status == PermissionStatus.Granted)
{
return true;
}

status = await Permissions.RequestAsync<Permissions.Camera>();

return status == PermissionStatus.Granted;
}
catch (Exception)
{

return false;
}
return false;
}
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ This library was inspired by existing MAUI barcode scanning libraries: [BarcodeS
Edit `AndroidManifest.xml` file (under the Platforms\Android folder) and add the following permissions inside of the `manifest` node:
```xml
<uses-permission android:name="android.permission.CAMERA" />
<!-- If you don't disable VibrationOnDetected(true by default) -->
<uses-permission android:name="android.permission.VIBRATE" />
```
#### iOS
Edit `info.plist` file (under the Platforms\iOS folder) and add the following permissions inside of the `dict` node:
Expand Down