I would like to ask if there is a way to make a Xamarin.Forms.Label tell that it should use the "AdjustsFontSizeToFitWidth" when the app is run on iOS.
Is this possible, or is Xamarin.Forms.Label something completely different than the UILabel?
I was thinking that Xamarin.Form.Label "falls back" on the UILabel when it's built for iOS, is that the case?
Edit:
According to how I understood the comments I tried this, but it wouldn't work:
switch (Device.RuntimePlatform)
{
case Device.iOS:
{
_label1.AdjustsFontSizeToFitWidth = true;
break;
}
default:
{
break;
}
}
The error I'm getting is that "AdjustsFontSizeToFitWidth" isn't a property of Xamarin.Forms.Label.
Edit 2:
According to another comment I tried the following:
public class clsGridCell : ContentView
{
private Xamarin.Forms.Label _label1;
//problem is that it's not longer a Xamarin.Forms.Label, but UILabel on iOS, but I can't declare it as "var" when I want to reuse it for binding.
//declaring it as "object" would break the bindings.
public clsGridCell()
{
switch (Device.RuntimePlatform)
{
case Device.iOS:
{
_label1 = new UILabel
_label1.AdjustsFontSizeToFitWidth = true;
break;
}
default:
{
_label1 = new Xamarin.Forms.Label()
{
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
};
break;
}
}
this._label1.SetBinding(Label.BackgroundColorProperty, new Binding() { Path = "BackgroundColor", Source = this });
this._label1.SetBinding(Label.TextProperty, new Binding() { Path = "Text", Source = this });
this._label1.SetBinding(Label.TextColorProperty, new Binding() { Path = "TextColor", Source = this });
The error is in line "_label1.AdjustsFontSizeToFitWidth = true;".
The error thrown is "Label doesn't contain "AdjustsFontSizeToFitWidth"".
That is because I declared it as "Label".
I did that because "var" wasn't possible in this case.
What would be an alternative way to declare it without breaking the bindings?
Declaring it as "object" would break the bindings.
Thank you!
As SushiHangover mentioned above,there are several ways to achieve your requirement.
Use Effects
In PCL
label.Effects.Add (Effect.Resolve ("MyCompany.AdjustsFontSizeEffect"));
Create class named AdjustsFontSizeEffect In iOS Project
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(AdjustsFontSizeEffect), "AdjustsFontSizeEffect")]
namespace EffectsDemo.iOS
{
public class AdjustsFontSizeEffect : PlatformEffect
{
protected override void OnAttached ()
{
(Control as UILabel).AdjustsFontSizeToFitWidth = true;
}
protected override void OnDetached ()
{
}
}
}
Use Custom Renderers
Create class named AdjustsFontSizeEffectRenderer In iOS Project
[assembly: ExportRenderer(typeof(Label), typeof(AdjustsFontSizeEffectRenderer))]
namespace EffectsDemo.iOS
{
public class AdjustsFontSizeEffectRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.AdjustsFontSizeToFitWidth = true;
}
}
}
}
I recommend you to use Effectsin this scenario.
Refer to Why Use an Effect over a Custom Renderer?
Related
i'm relative new to this, so i want to implement dependency injection using typescript (is the first time I use this pattern), I'm more that using language programming like java or c# for OOP, so there is more easy to apply this pattern,
I found an example on internet and I can use it without problems on eclipse and visual studio, but when i use it on typescript the IDE raise an error like this:
Supplied parameters do not match any signature of call target
and is just at the end of implement it when this error appears
my base class:
class Motor {
Acelerar(): void {
}
GetRevoluciones(): number {
let currentRPM: number = 0;
return currentRPM;
}
}
export {Motor};
my class that uses motor
import { Motor } from "./1";
class Vehiculo {
private m: Motor;
public Vehiculo(motorVehiculo: Motor) {
this.m = motorVehiculo;
}
public GetRevolucionesMotor(): number {
if (this.m != null) {
return this.m.GetRevoluciones();
}
else {
return -1;
}
}
}
export { Vehiculo };
my interface and the type of motor
interface IMotor {
Acelerar(): void;
GetRevoluciones(): number;
}
class MotorGasoline implements IMotor {
private DoAdmission() { }
private DoCompression() { }
private DoExplosion() { }
private DoEscape() { }
Acelerar() {
this.DoAdmission();
this.DoCompression();
this.DoExplosion();
this.DoEscape();
}
GetRevoluciones() {
let currentRPM: number = 0;
return currentRPM;
}
}
class MotorDiesel implements IMotor {
Acelerar() {
this.DoAdmission();
this.DoCompression();
this.DoCombustion();
this.DoEscape();
}
GetRevoluciones() {
let currentRPM: number = 0;
return currentRPM;
}
DoAdmission() { }
DoCompression() { }
DoCombustion() { }
DoEscape() { }
}
and here is where the error appears:
import { Vehiculo } from "./2";
enum TypeMotor {
MOTOR_GASOLINE = 0,
MOTOR_DIESEL = 1
}
class VehiculoFactory {
public static VehiculoCreate(tipo: TypeMotor) {
let v: Vehiculo = null;
switch (tipo) {
case TypeMotor.MOTOR_DIESEL:
v = new Vehiculo(new MotorDiesel()); break;
case TypeMotor.MOTOR_GASOLINE:
v = new Vehiculo(new MotorGasoline()); break;
default: break;
}
return v;
}
}
I don't wanna use any library or module like SIMPLE-DIJS or D4js or any other for the moment, I just wanna know how to implement without them
You have this error because you don't specify a constructor on the Vehiculo type.
To declare a constructor you should use use the constructor keyword and not the name of the class.
class Vehiculo {
private m: Motor;
constructor(motorVehiculo: Motor) {
this.m = motorVehiculo;
}
public GetRevolucionesMotor(): number {
if (this.m != null) {
return this.m.GetRevoluciones();
}
else {
return -1;
}
}
}
I wanted to hide 'cancel' button in my iOS search bar. I have implemented the following custom renderer code but it seems not to to work. If anyone knows solution , please share.
public class iOSSearchBar : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> args)
{
base.OnElementChanged(args);
UISearchBar bar = (UISearchBar)this.Control;
bar.AutocapitalizationType = UITextAutocapitalizationType.None;
bar.AutocorrectionType = UITextAutocorrectionType.No;
//bar.BarStyle = UIBarStyle.Default;
//bar.BarTintColor = UIColor.LightGray;
//bar.KeyboardType = UIKeyboardType.ASCIICapable;
bar.SearchBarStyle = UISearchBarStyle.Minimal;
bar.SetShowsCancelButton(false, false);
bar.ShowsCancelButton = false;
}
}
Thanks in advance
This worked for me.
https://gist.github.com/xleon/9f94a8482162460ceaf9
using System;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using UIKit;
using System.Diagnostics;
[assembly: ExportRenderer(typeof(SearchBar), typeof(Namespace.iOS.Renderers.ExtendedSearchBarRenderer))]
namespace Namespace.iOS.Renderers
{
public class ExtendedSearchBarRenderer : SearchBarRenderer
{
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Text")
{
Control.ShowsCancelButton = false;
}
}
}
}
Write code to hide cancel button in layoutsubviews method.
public override void LayoutSubviews()
{
base.LayoutSubviews();
UISearchBar bar = (UISearchBar)this.Control;
bar.ShowsCancelButton = false;
}
Following is also working or me, no need to subclass searcher:
SearchBar.TextChanged += delegate
{
SearchBar.ShowsCancelButton = false;
};
I think i managed to remove it manually with:
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Subviews[0].Subviews[0].RemoveFromSuperview();
}
}
I spend some more time searching for this, so adding here in case someone else wants to do both.
In case you also need to remove the X button as well, I found the solution in this comment
I have the following code:
CancellationPolicyService
using MyApp.Model.Models;
using Repository.Pattern.Repositories;
using Service.Pattern;
namespace MyApp.Service
{
public interface ICancellationPolicyService : IService<CancellationPolicy>
{
}
public class CancellationPolicyService : Service<CancellationPolicy>, ICancellationPolicyService
{
public CancellationPolicyService(IRepositoryAsync<CancellationPolicy> repository)
: base(repository)
{
}
}
}
Inside UnityConfig.cs:
.RegisterType<ICancellationPolicyService, CancellationPolicyService>()
In DataCacheService:
namespace MyApp.Service
{
public class DataCacheService
{
private ICancellationPolicyService CancellationPolicyService
{
get { return _container.Resolve<ICancellationPolicyService>(); }
}
public DataCacheService(IUnityContainer container)
{
_container = container;
MainCache = new MemoryCache("MainCache");
GetCachedItem(CacheKeys.CancellationPolicies);
}
public object GetCachedItem(CacheKeys CacheKeyName)
{
lock (_lock)
{
if (!MainCache.Contains(CacheKeyName.ToString()))
{
switch (CacheKeyName)
{
case CacheKeys.CancellationPolicies:
var cancellationpolicies = CancellationPolicyService.Queryable().ToList();
UpdateCache(CacheKeys.CancellationPolicies, cancellationpolicies);
break;
}
};
return MainCache[CacheKeyName.ToString()] as Object;
}
}
}
}
And when I call DataCacheService I get an error saying the following:
InvalidOperationException - The current type, Repository.Pattern.Repositories.IRepositoryAsync`1[MyApp.Model.Models.CancellationPolicy], is an interface and cannot be constructed. Are you missing a type mapping?
Do you have an idea, why that is? I would be thankful for any kind of hint.
It sounds like you haven't registered IRepositoryAsync<CancellationPolicy>. Add that registration to your unity registration as well.
Assuming that the implementation of IRepositoryAsync<CancellationPolicy> is CancellationPolicyRepository:
.RegisterType<IRepositoryAsync<CancellationPolicy>, CancellationPolicyRepository>()
Or someting like this if you have a generic repository.
.RegisterType<IRepositoryAsync<CancellationPolicy>, MyGenericRepository<CancellationPolicyRepository>>()
use this one:
RegisterType<yourInterface>().As<yourClass>().AsSelf();
it might work.
The card.io component (http://components.xamarin.com/view/cardioios) has a fallback screen that has a Cancel and a Done button on them.
Neither of which actually do anything. I assume it is up to me to subscribe to and event, however, there is no event to subscribe to.
Here is the code:
var paymentDelegate = new PaymentViewControllerDelegate();
var paymentViewController = new Card.IO.PaymentViewController(paymentDelegate);
paymentDelegate.OnScanCompleted += (viewController, cardInfo) =>
{
viewController.DismissViewController(true, null);
if (cardInfo == null)
{
}
else
{
new UIAlertView("Card Scanned!", cardInfo.CardNumber, null, "OK", null).Show();
}
};
paymentViewController.AppToken = "app-token";
// Display the card.io interface
base.PresentViewController(paymentViewController, true, () => { });
There is a method on the PaymentViewControllerDelegate, but I can't figure out what to do with it:
public override void UserDidCancel(PaymentViewController paymentViewController);
public override void UserDidProvideCreditCardInfo(CreditCardInfo cardInfo, PaymentViewController paymentViewController);
I guess the problem is that the Component doesn't expose any events for the Fallback View.
You need to subclass PaymentViewControllerDelegate:
public class MyPaymentDelegate : PaymentViewControllerDelegate
{
public MyPaymentDelegate ()
{
}
public override void UserDidCancel (PaymentViewController paymentViewController)
{
// Implement on-cancel logic here...
base.UserDidCancel (paymentViewController);
}
public override void UserDidProvideCreditCardInfo (CreditCardInfo cardInfo, PaymentViewController paymentViewController)
{
// Implement logic for credit card info provided here...
base.UserDidProvideCreditCardInfo (cardInfo, paymentViewController);
}
}
And then provide an instance of this class into the constructor for Card.IO.PaymentViewController:
var paymentDelegate = new MyPaymentDelegate();
var paymentViewController = new Card.IO.PaymentViewController(paymentDelegate);
So, I figured this out by looking at the working sample application and comparing it to what I had done.
All I had to do was widen the scope of the paymentDelegate and paymentViewController variables.
If you look at the sample, you really just need to subscribe to the OnScanCompleted event which is called in both cases of UserDidCancel (where cardInfo will be null), and UserDidProvideCreditCardInfo (where it will not be null).
In fact, this is the code for the binding, so you can see the Event was made as a 'helper' to make it so you didn't have to make your own delegate implementation:
namespace Card.IO
{
public partial class PaymentViewControllerDelegate : BasePaymentViewControllerDelegate
{
public delegate void ScanCompleted(PaymentViewController viewController, CreditCardInfo cardInfo);
public event ScanCompleted OnScanCompleted;
public override void UserDidCancel (PaymentViewController paymentViewController)
{
var evt = OnScanCompleted;
if (evt != null)
evt(paymentViewController, null);
}
public override void UserDidProvideCreditCardInfo (CreditCardInfo cardInfo, PaymentViewController paymentViewController)
{
var evt = OnScanCompleted;
if (evt != null)
evt(paymentViewController, cardInfo);
}
}
}
If you still really want to implement the delegate yourself, subclass BasePaymentViewController instead, however I don't think you really need to make your own subclass of it...
Hopefully that helps!
I am trying to implement a custom binding on a subclass of UITextField so that the bound value is set when the user is done editing instead of with each keystroke because some interim values are invalid in the viewmodel (for example, while setting 'Age' to '26', a value of '2' is invalid so I'd like to wait to set the value until both digits are there). Something similar to setting UpdateSourceTrigger in xaml. I looked at several examples here:
MvvmCross UITextField custom binding is similar, as is MvvmCross: change update source trigger property of binding on MonoDroid (but for Android). I've also watch N=28 custom binding and looked at the source for MvxUITextFieldTextTargetBinding.
I think I'm close, but my custom binding never gets created and the UITextFields in my app still FireValueChanged with every keystroke.
I created the following Custom Binding:
public class UITextFieldFocusChangedBinding : MvxTargetBinding
{
private bool _subscribed;
private UITextField _view;
public UITextFieldFocusChangedBinding(UITextField target) : base(target)
{
_view = target;
}
public override void SetValue(object value)
{
if (_view == null) return;
_view.Text = (string)value;
}
public override void SubscribeToEvents()
{
var view = _view;
if (view == null)
return;
view.Ended += TextFieldOnEnded;
}
private void TextFieldOnEnded(object sender, EventArgs eventArgs)
{
var view = _view;
if (view == null)
return;
if (!view.IsFirstResponder)
FireValueChanged(view.Text);
_subscribed = true;
}
public override Type TargetType
{
get { return typeof(string); }
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
var view = _view;
if (view != null && _subscribed)
{
view.Ended -= TextFieldOnEnded;
_subscribed = false;
}
}
base.Dispose(isDisposing);
}
}
My setup.cs contains the following:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterPropertyInfoBindingFactory(typeof(Bindings.UITextFieldFocusChangedBinding),typeof(UITextField), "Text");
}
and in my MvxViewController I have:
var set = this.CreateBindingSet<LifeNeedsView, LifeNeedsViewModel>();
set.Bind(_txtFinMedExpenses).To(vm => vm.FinalMedicalExpenses);
set.Apply();
The bindings work (values are passing correctly) but with every keystroke. Any suggestions on what I might be missing?