【问题标题】:Change button text color in disabled button (Xamarin.Forms)更改禁用按钮中的按钮文本颜色 (Xamarin.Forms)
【发布时间】:2018-04-09 09:56:54
【问题描述】:

当按钮被禁用时,我需要更改按钮的文本颜色,我为 iOS 和 Android 创建了一个自定义渲染器。 iOS完美运行,由于android没有改变颜色,我也通过样式创建了触发器,也没有解决。

如何为 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 进行更改,这将是应用的默认样式。

这两种方法都不能解决

【问题讨论】:

标签: c# xamarin xamarin.forms xamarin.android


【解决方案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;
        }
    }

    ...

}

【讨论】:

  • 不幸的是,这对我不起作用:该方法被调用,但不适用于 Button.IsEnabled 属性,因此它不会得到更新。
【解决方案2】:

由于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 可能为空,因为它代表旧元素。所以只需删除此行。并且代码可以正常工作。

【讨论】:

    【解决方案3】:

    对于安卓:

    [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;
            }
        }
    }
    

    【讨论】:

    • 注意,安卓系统请务必使用FastRenderer,否则可能无法应用某些样式设置器。
    【解决方案4】:

    在不影响自定义渲染器的情况下执行此操作的另一种方法是使按钮 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   
    }
    

    【讨论】:

      【解决方案5】:

      我使用VisualStateManager为每个按钮状态添加不同的样式:正常、聚焦、按下、禁用

      <Style TargetType="Button">
              <Setter Property="VisualStateManager.VisualStateGroups">
                  <VisualStateGroupList>
                      <VisualStateGroup x:Name="CommonStates">
                          <VisualState x:Name="Normal">
                              <VisualState.Setters>
                                  <Setter Property="BackgroundColor" Value="{StaticResource ColorAccent}" />
                                  <Setter Property="TextColor" Value="{StaticResource ColorForegroundIcon}" />
                              </VisualState.Setters>
                          </VisualState>
                          <VisualState x:Name="Pressed">
                              <VisualState.Setters>
                                  <Setter Property="BackgroundColor" Value="{StaticResource ColorAccentTransparent}" />
                              </VisualState.Setters>
                          </VisualState>
                          <VisualState x:Name="Focused">
                              <VisualState.Setters>
                                  <Setter Property="BackgroundColor" Value="{StaticResource ColorAccentTransparent}" />
                              </VisualState.Setters>
                          </VisualState>
                          <VisualState x:Name="Disabled">
                              <VisualState.Setters>
                                  <Setter Property="BackgroundColor" Value="{DynamicResource ColorBackgroundDisabled}" />
                                  <Setter Property="TextColor" Value="{DynamicResource ColorForegroundFaded}" />
                              </VisualState.Setters>
                          </VisualState>
                      </VisualStateGroup>
                  </VisualStateGroupList>
              </Setter>
          </Style>
      
      

      有关更多信息和示例,请查看:Understanding Visual State Manager in Xamarin Forms

      【讨论】:

      • 很高兴它有帮助! :-)
      • 最好的方法!
      • 最干净的答案。渲染器很有用,但可能会导致很多意想不到的副作用(例如,未设置焦点和按下的颜色)。
      【解决方案6】:

      我知道这是一个旧线程,但想分享一个对我有用的简单解决方案。如果这是您正在寻找的,希望这会有所帮助。 为了将 Text Color 或任何在后面的代码中无法访问的属性分配给 Button,请尝试这样做,

      ("YourControl" as Button).TextColor= .... 您将看到该控件的所有属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-13
        • 1970-01-01
        • 1970-01-01
        • 2017-04-10
        相关资源
        最近更新 更多