Skip to content

Commit

Permalink
Improve bindings on tintcolor (#847)
Browse files Browse the repository at this point in the history
* Added PropertyChanged sample

* improved android

* removed Tizen from attribute since it doesn't exist

* improved iOS implementation

* improved sample
  • Loading branch information
pictos authored Jan 11, 2023
1 parent f9fabc0 commit 8517beb
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
xmlns:vm="clr-namespace:CommunityToolkit.Maui.Sample.ViewModels.Behaviors"
Title="IconTintColorBehaviorPage"
x:DataType="vm:IconTintColorBehaviorViewModel"
x:TypeArguments="vm:IconTintColorBehaviorViewModel">
x:TypeArguments="vm:IconTintColorBehaviorViewModel"
x:Name="this">
<ScrollView>
<Grid
Padding="20"
ColumnDefinitions="*,*"
RowDefinitions="Auto, Auto, 60, 60, 60"
RowDefinitions="Auto, Auto, 60, 60, 60, Auto"
RowSpacing="20">

<Label
Expand Down Expand Up @@ -68,11 +69,17 @@
<ImageButton
Grid.Row="4"
Grid.Column="1"
Command="{Binding ChangeCommand}"
Source="shield.png">
<ImageButton.Behaviors>
<mct:IconTintColorBehavior TintColor="Green" />
<mct:IconTintColorBehavior TintColor="{Binding Source={x:Reference this}, Path=BindingContext.ChangedColor}" />
</ImageButton.Behaviors>
</ImageButton>

<Label
Grid.Row="5"
Grid.Column="1"
Text="The ImageButton above uses Binding in order to change the TintColor. Click it!"/>
</Grid>
</ScrollView>
</pages:BasePage>
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
namespace CommunityToolkit.Maui.Sample.ViewModels.Behaviors;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

public class IconTintColorBehaviorViewModel : BaseViewModel
namespace CommunityToolkit.Maui.Sample.ViewModels.Behaviors;

public partial class IconTintColorBehaviorViewModel : BaseViewModel
{
[RelayCommand]
void Change()
{
IsChanged = !IsChanged;
}

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(ChangedColor))]
bool isChanged;

public Color ChangedColor => IsChanged ? Colors.Red : Colors.Green;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,19 @@ namespace CommunityToolkit.Maui.Behaviors;
public partial class IconTintColorBehavior
{
/// <inheritdoc/>
protected override void OnAttachedTo(View bindable, AView platformView) =>
protected override void OnAttachedTo(View bindable, AView platformView)
{
ApplyTintColor(bindable, platformView);

this.PropertyChanged += (s, e) =>
{
if (e.PropertyName == TintColorProperty.PropertyName)
{
ApplyTintColor(bindable, platformView);
}
};
}

/// <inheritdoc/>
protected override void OnDetachedFrom(View bindable, AView platformView) =>
ClearTintColor(bindable, platformView);
Expand Down Expand Up @@ -77,8 +87,7 @@ void OnElementPropertyChanged(object? sender, PropertyChangedEventArgs args)
return;
}

if (!propertyName.Equals(TintColorProperty.PropertyName, StringComparison.Ordinal)
&& !propertyName.Equals(Image.SourceProperty.PropertyName, StringComparison.Ordinal)
if (!propertyName.Equals(Image.SourceProperty.PropertyName, StringComparison.Ordinal)
&& !propertyName.Equals(ImageButton.SourceProperty.PropertyName, StringComparison.Ordinal))
{
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,54 @@ namespace CommunityToolkit.Maui.Behaviors;
public partial class IconTintColorBehavior
{
/// <inheritdoc/>
protected override void OnAttachedTo(View bindable, UIView platformView) =>
protected override void OnAttachedTo(View bindable, UIView platformView)
{
ApplyTintColor(platformView, bindable, TintColor);

bindable.PropertyChanged += OnElementPropertyChanged;
this.PropertyChanged += (s, e) =>
{
if (e.PropertyName == TintColorProperty.PropertyName)
{
ApplyTintColor(platformView, bindable, TintColor);
}
};
}

void OnElementPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != ImageButton.IsLoadingProperty.PropertyName
|| e.PropertyName != Image.SourceProperty.PropertyName
|| e.PropertyName != ImageButton.SourceProperty.PropertyName
|| sender is not IImageElement element
|| (sender as VisualElement)?.Handler?.PlatformView is not UIView platformView)
{
return;
}

if (!element.IsLoading)
{
ApplyTintColor(platformView, (View)element, TintColor);
}
}

/// <inheritdoc/>
protected override void OnDetachedFrom(View bindable, UIView platformView) =>
ClearTintColor(platformView, bindable);

void ClearTintColor(UIView platformView, View element)
{
element.PropertyChanged -= OnElementPropertyChanged;
switch (platformView)
{
case UIImageView imageView:
element.PropertyChanged -= OnImageViewTintColorPropertyChanged;
if (imageView.Image is not null)
{
imageView.Image = imageView.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
}

break;
case UIButton button:
element.PropertyChanged -= OnButtonTintColorPropertyChanged;
if (button.ImageView?.Image is not null)
{
var originalImage = button.CurrentImage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
Expand Down Expand Up @@ -61,65 +88,32 @@ void ApplyTintColor(UIView platformView, View element, Color? color)
}
}

void SetUIButtonTintColor(UIButton button, View element, Color color)
static void SetUIButtonTintColor(UIButton button, View element, Color color)
{
if (button.ImageView.Image is null)
{
element.PropertyChanged += OnButtonTintColorPropertyChanged;
}
else
{
var templatedImage = button.CurrentImage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);

button.SetImage(null, UIControlState.Normal);
var platformColor = color.ToPlatform();
button.TintColor = platformColor;
button.ImageView.TintColor = platformColor;
button.SetImage(templatedImage, UIControlState.Normal);
}
}

void OnButtonTintColorPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != ImageButton.IsLoadingProperty.PropertyName
|| sender is not ImageButton element
|| element.Handler?.PlatformView is not UIView platformView)
{
return;
}

if (!element.IsLoading)
{
ApplyTintColor(platformView, element, TintColor);
}
}
var templatedImage = button.CurrentImage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);

button.SetImage(null, UIControlState.Normal);
var platformColor = color.ToPlatform();
button.TintColor = platformColor;
button.ImageView.TintColor = platformColor;
button.SetImage(templatedImage, UIControlState.Normal);

void SetUIImageViewTintColor(UIImageView imageView, View element, Color color)
{
if (imageView.Image == null)
{
element.PropertyChanged += OnImageViewTintColorPropertyChanged;
}
else
{
imageView.Image = imageView.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);
imageView.TintColor = color.ToPlatform();
}
}

void OnImageViewTintColorPropertyChanged(object? sender, PropertyChangedEventArgs e)
static void SetUIImageViewTintColor(UIImageView imageView, View element, Color color)
{
if (e.PropertyName != Image.IsLoadingProperty.PropertyName
|| sender is not Image element
|| element.Handler?.PlatformView is not UIView platformView)
if (imageView.Image is null)
{
return;
}

if (!element.IsLoading)
{
ApplyTintColor(platformView, element, TintColor);
}
imageView.Image = imageView.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);
imageView.TintColor = color.ToPlatform();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace CommunityToolkit.Maui.Behaviors;
/// <summary>
/// A behavior that allows you to tint an icon with a specified <see cref="Color"/>.
/// </summary>
[UnsupportedOSPlatform("windows"), UnsupportedOSPlatform("Tizen")]
[UnsupportedOSPlatform("windows")]
public partial class IconTintColorBehavior : PlatformBehavior<View>
{
/// <summary>
Expand Down

0 comments on commit 8517beb

Please sign in to comment.