CustomRenderer not applying - xamarin

The BackgroundColor property on Xamarin.Forms.Buttons started coloring the entire area assigned to the button instead of just the button, so I started delving into the Custom Renderers in Android to see if I could fix it. The following is the class I created, the .xaml where I use a custom button, and the renderer (it's just supposed to color the button green as a test):
using Xamarin.Forms;
namespace wcsmobile
{
public class wcsButton : Button
{
}
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:wcsmobile;assembly=wcsmobile"
x:Class="wcsmobile.Transfer"
Title="Transfer">
<ContentPage.Content>
<StackLayout HorizontalOptions="FillAndExpand">
<local:wcsButton Text="OK" HorizontalOptions="Center"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
[assembly: ExportRenderer(typeof(wcsButton), typeof(ButtonRenderer))]
namespace wcsmobile.Droid
{
class wcsButtonRenderer : ButtonRenderer
{
public wcsButtonRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.SetBackgroundColor(global::Android.Graphics.Color.LightGreen);
}
}
}
}
There is no error, but the button stays gray, not green. Putting a breakpoint at the "base.OnElementChanged(e)" doesn't do anything; the breakpoint never gets hit. Both projects are using Xamarin.Forms version 3.1.0.583944.
Anyone with a clue as to why the Custom Renderer doesn't seem to be applying would be very helpful. (Or even an idea as to why BackgroundColor seemed to stop working in the first place).

As you mentioned "both projects" the answer seems obvious: the renderer from project A isn't applied to project B. You have the choice to move it to appropriate project OR move it to a shared project https://learn.microsoft.com/en-us/xamarin/cross-platform/app-fundamentals/shared-projects?tabs=vswin

Related

How to add the ripple effect in Xamarin label or image?

I am looking at implementing a ripple effect on label text or in image.So how to add the ripple effect on any label or in image?
You can use the package TouchView from nuget
Add nuget package to your Xamarin.Forms .netStandard/PCL project and to your platform-specific projects (iOS and Android)
iOS: add TouchViewRenderer.Initialize() line to your AppDelegate
(preserve from linker)
using TouchEffect.iOS;
namespace YourApp.iOS
{
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
TouchViewRenderer.Initialize();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
}
}
in xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:YourApp"
xmlns:touch="clr-namespace:TouchEffect;assembly=TouchEffect"
x:Class="App11.MainPage">
<StackLayout>
<touch:TouchView
RegularBackgroundColor="LightGray"
PressedBackgroundColor="Gray"
PressedOpacity="1"
PressedAnimationDuration="100"
RegularAnimationDuration="100"
Padding="10, 5"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
Completed="Handle_TouchCompleted"
>
<Label Text="Click Me"
TextColor="Black"
FontSize="30"/>
</touch:TouchView>
</StackLayout>
</ContentPage>
in code behind
private void Handle_TouchCompleted(TouchEffect.TouchView sender, TouchEffect.EventArgs.TouchCompletedEventArgs args)
{
// do something you want
}
Use XamarinCommunityToolkit Documentation YouTube Resources
In your xaml
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
Use exactly NativeAnimation
<Frame xct:TouchEffect.NativeAnimation="True"> </Frame>
You can provide ripple and other effects using TouchEffect Library from AndreiMisiukevich.For more info: https://github.com/AndreiMisiukevich/TouchEffect
And another library is also available. https://github.com/mrxten/XamEffects
Both are well documented.

Xamarin Form Animation

I have a simple code that uses ScaleTo method to build a simple animation and the code was working fine up to last Friday and all of the sudden it's not working any more.
Here is my XAML file:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="TestAnim.MainPage">
<StackLayout Orientation="Vertical">
<Image Source="discount.png" x:Name="img" Scale="0.1"/>
<Button Text="Do" Clicked="doIt"/>
</StackLayout>
</ContentPage>
And here is my C# code:
using System;
using System.ComponentModel;
using Xamarin.Forms;
namespace TestAnim
{
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
async void doIt (object sender , EventArgs ev)
{
await img.ScaleTo(1, 2000, Easing.BounceOut);
await img.ScaleTo(0.1, 3000, Easing.BounceIn);
}
}
}
When I run the code, I see no effects at all, if I comment the 2nd ScaleTo call I see my image scales to 1 but this happens immediately instead of within 2 seconds! As result when I have the 2nd scale really the end result is no see no animation at all.
This was working fine before as I mentioned but for some reason the duration seems to be ignored and the scaling seems to happen instantly which is the issue here.
Any one else see the same problem?
If you are using Xamarin.Forms version 4.2+ there is currently a bug about Animations, you can track it here.
I've reproduced your code in Xamarin.Forms 4.1.0.581479 and it is working just fine.

Frame goes transparent on tap

I am working on a Xamarin.Forms project with a ListView and each item has a Frame with a white background. My problem is I recently noticed when I tap the Item it makes the Frame's background white. It still shows all the other objects but the frame goes transparent.
The frame is simply
<Frame CornerRadius="10" Padding="0" Margin="10, 10, 10, 5" BackgroundColor="White">...</Frame>
Promoting above comments-answer to real-answer for readability sake:
The behavior you are seeing is specific to iOS. You can solve it by overriding the default behavior using an effect, like so:
[assembly: ResolutionGroupName("MyEffects")]
[assembly: ExportEffect(typeof(ListViewHighlightEffect), nameof(ListViewHighlightEffect))]
namespace MyProject.iOS.Effects
{
public class ListViewHighlightEffect : PlatformEffect
{
protected override void OnAttached()
{
var listView = (UIKit.UITableView)Control;
listView.AllowsSelection = false;
}
protected override void OnDetached()
{
}
}
}
Then, you can apply it in your view code-behind:
MyListView.Effects.Add(Effect.Resolve($"MyEffects.ListViewHighlightEffect"));
I did a short write-up on the full solution here
Alternatively, if you want to maintain the ability to select an item, one possible fix would be to add an ItemTapped handler in your code behind and null out
MyListView.SelectedItem = null;

ZXing view with FreshMVVM not triggering OnScanResult

Resoution TL;DR : https://gist.github.com/rupe120/78f8a57f0ed7ecacbdc13fa2da8d931a
I created my own scan page, converting the built-in ZXingScannerPage code (https://github.com/Redth/ZXing.Net.Mobile/blob/master/Source/ZXing.Net.Mobile.Forms/ZXingScannerPage.cs) to a Page + PageModel/View concept. The page code is below.
The problem is that OnScanResult is never triggered.
I was using ZXingScannerPage directly previously, and the OnScanResult event was successfully triggering but I wanted the page to follow the same format as the rest of the application. So the QR code I'm using should trigger it.
I must be missing a setup piece in the ZXingScannerView, but I can't see it.
Any thoughts?
SearchQrPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Pages.SearchQrPage"
xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms">
<ContentPage.Content>
<Grid>
<zxing:ZXingScannerView x:Name="scannerView" />
<zxing:ZXingDefaultOverlay x:Name="scannerOverlay"
TopText="Hold your phone up to the QR code"
BottomText="Scanning will happen automatically"
ShowFlashButton="True"/>
</Grid>
</ContentPage.Content>
</ContentPage>
SearchQrPage.xaml.cs
using MyApp.PageModels;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace MyApp.Pages
{
public partial class SearchQrPage : ContentPage
{
public SearchQrPage()
{
InitializeComponent();
scannerView.Options = new ZXing.Mobile.MobileBarcodeScanningOptions
{
PossibleFormats =
new List<ZXing.BarcodeFormat>
{
ZXing.BarcodeFormat.QR_CODE
}
};
scannerView.OnScanResult += ScannerView_OnScanResult;
scannerOverlay.FlashButtonClicked += ScannerOverlay_FlashButtonClicked;
}
private void ScannerOverlay_FlashButtonClicked(Button sender, EventArgs e)
{
scannerView.ToggleTorch();
}
private void ScannerView_OnScanResult(ZXing.Result result)
{
var model = this.BindingContext as SearchQrPageModel;
if (model == null)
return;
scannerView.IsScanning = false;
if (model.ScanResultCommand.CanExecute(result))
model.ScanResultCommand.Execute(result);
}
}
}
Just set IsScanning = true at the constructor, for example. On the original ZXing's page, they do it on the OnAppearing event.
You've missed it up.

Wrapping an MPVolumeView inside 2 Stack Layouts (Xamarin.IOS)

I am creating a control based on a generic View that works with a custom renderer based on an iOS MPVolumeView, which is the simple control that allows you to select an alternate output route for audio in your app (i.e. Bluetooth Speaker). The code works just fine if I wrap inside a single stack layout, but not if it's inside two stack layouts. My XAML looks like this... very basic:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="DABApp.DabTestPage" xmlns:local="clr-namespace:DABApp;assembly=DABApp">
<ContentPage.Content>
<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand" BackgroundColor="Red">
<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand" VerticalOptions="FillAndExpand">
<local:AudioOutputView />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
And here's the guts of my custom renderer:
[assembly: ExportRenderer(typeof(AudioOutputView), typeof(iosAudioOutputViewRenderer))]
namespace DABApp.iOS
{
public class iosAudioOutputViewRenderer: ViewRenderer<AudioOutputView, UIView>
{
MPVolumeView view;
protected override void OnElementChanged(ElementChangedEventArgs<AudioOutputView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
view = new MPVolumeView()
{
ShowsRouteButton = true,
ShowsVolumeSlider = false,
};
SetNativeControl(view);
}
}
}
}
With this XAML and code, when I push the page onto the nav stack async, the page won't even show. If I remove one of the StackLayouts, it works fine.
I changed my IOS control in the CustomRenderer to a simple UILabel and this works fine... so it looks like it has something to do with putting the MPVolumeView inside 2 StackLayouts. I need to be able to do this because of the layout requirements of my app, and it doesn't make any sense why 1 StackLayout is fine, but 2 isn't, and only for this native control.
Any ideas?

Resources