web-dev-qa-db-ja.com

無効なボタンのボタンテキストの色を変更する(Xamarin.Forms)

ボタンが無効になっているときにボタンのテキストの色を変更する必要があります。iOS用とAndroid用のカスタムレンダラーを作成しました。 Androidは色を変更しないので、iOSは完全に機能しました。また、スタイルを介してトリガーを作成しましたが、解決しません。

Xamarin.Formsでカラースワップを機能させる方法は?

Androidレンダラー:

[Assembly: ExportRenderer(typeof(Button), typeof(MyButtonRenderer))]
namespace xxxxxx.Droid.Renderers
{
    public class MyButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
                Control.SetTextColor(Color.White.ToAndroid());

            if (e != null)
            {
                e.NewElement.TextColor = Color.White;
                e.OldElement.TextColor = Color.White;
            }
        }
    }
}

この状態の変化は、コマンドのCanExecuteに従って変更されます。これは、適用されるデフォルトのスタイルになります。

これらの方法のどちらも解決しません

5
Luiz Negrini

アンドロイド用:

[Assembly: ExportRenderer(typeof(Button), typeof(MyButtonRenderer))]
namespace Forms.Droid.Renderers
{
    public class MyButtonRenderer : ButtonRenderer
    {
        public MyButtonRenderer(Context context) : base(context) { }

        protected override void OnElementChanged(ElementChangedEventArgs<Button> args)
        {
            base.OnElementChanged(args);
            if (Control != null) SetColors();
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(sender, args);
            if (args.PropertyName == nameof(Button.IsEnabled)) SetColors();
        }

        private void SetColors()
        {
            Control.SetTextColor(Element.IsEnabled ? Element.TextColor.ToAndroid() : Android.Graphics.Color.Gray);
            Control.SetBackgroundColor(Element.IsEnabled ? Element.BackgroundColor.ToAndroid() : Android.Graphics.Color.DarkGray);
        }
    }
}

IOSの場合:

[Assembly: ExportRenderer(typeof(Button), typeof(MyButtonRenderer))]
namespace Forms.iOS.Renderers
{
    public class MyButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> args)
        {
            base.OnElementChanged(args);
            if (Control != null) SetColors();
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(sender, args);
            if (args.PropertyName == nameof(Button.IsEnabled)) SetColors();
        }

        private void SetColors()
        {
            Control.SetTitleColor(Element.IsEnabled ? Element.TextColor.ToUIColor() : UIColor.Gray, Element.IsEnabled ? UIControlState.Normal : UIControlState.Disabled);
            Control.BackgroundColor = Element.IsEnabled ? Element.BackgroundColor.ToUIColor() : UIColor.DarkGray;
        }
    }
}
10
Arvis

カスタムレンダラーをいじらずにこれを行う別の方法は、ボタンInputTransparentを作成し、入力が透明になったときにプレスをブロックすることです。 InputTransparentがtrueに設定されている場合、ユーザーはボタンをクリックできませんが、すべてのスタイルは保持されます。唯一の問題は、最後の入力フィールドに入力したときにボタンをアクティブにした場合でも、ボタンをクリックできることです。これを解決する方法は、ボタンクリックメソッドに単純なInputTransparentチェックを追加することです。

XAML:

<!-- Uses "InputTransparent" instead of "IsEnabled" so we can have control of the text color when the button is "Disabled" -->
<!-- Must add "if (btnLogin.InputTransparent == true) return;" code to the top of the button clicked method of this event to block "LastControl" auto click -->
<Button Text="im back!" x:Name="btnLogin" Style="{StaticResource BaseButtonStyleTransparent}" WidthRequest="225" InputTransparent="True" TextColor="#999999">
    <Button.Triggers>
        <MultiTrigger TargetType="Button">
            <MultiTrigger.Conditions>
                <BindingCondition Binding="{Binding Source={x:Reference txtEmail}, Path=IsValid, Converter={StaticResource dataHasBeenEntered}}" Value="true" />
                <BindingCondition Binding="{Binding Source={x:Reference txtPassword}, Path=IsValid, Converter={StaticResource dataHasBeenEntered}}" Value="true" />
            </MultiTrigger.Conditions>
            <Setter Property="InputTransparent" Value="False" />
            <Setter Property="TextColor" Value="White" />
        </MultiTrigger>
    </Button.Triggers>
</Button>

C#:

private async void LoginClicked(object sender, EventArgs e)
{
    // If the button is psudo disabled dont let the user click the button
    if (btnLogin.InputTransparent == true)
        return;

    // Rest of LoginClicked Code   
}
1

CanExecuteが期待どおりに機能する場合は、それに応じてIsEnabledプロパティを更新する必要があります。このプロパティ値の変更は、OnElementPropertyChangedメソッドを介して聞くことができます。

public class MyButtonRenderer : ButtonRenderer
{

    ....

    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);

        if (e.PropertyName == nameof(Button.IsEnabled))
        {
            Element.TextColor = Element.IsEnabled ? Color.White : Color.Gray;
        }
    }

    ...

}
1
Sharada Gururaj

Androidは色を変更しないので、スタイルを介してトリガーも作成しましたが、解決しません。

問題を引き起こす可能性のあるいくつかの可能性があります。

  1. ほとんどの場合、間違ったButtonタイプを使用してレンダラーを定義しています。DroidプロジェクトにはAndroid.widget.ButtonXamarin.Forms.Buttonがあります。レンダラーを定義するために必要なのはXamarin.Forms.Buttonです。

    [Assembly:ExportRenderer(typeof(Xamarin.Forms.Button),
                             typeof(MyButtonRenderer))]
    namespace xxxxxxxxx.Droid
    {
      ...
    }
    
  2. e.OldElement.TextColor = Color.White;を設定する必要はありません。そして実際には、その時点でe.OldElementはおそらくnullであり、古い要素を表しています。したがって、この行を削除するだけです。コードは正常に機能します。

0