更改禁用按钮中的按钮文本颜色(Xamarin.Forms)

时间:2017-10-27 18:06:29

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

我需要在禁用按钮时更改按钮的文本颜色,我已经为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更改此状态更改,这将是应用的默认样式。

这两种方式都没有解决

6 个答案:

答案 0 :(得分:7)

我使用 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

答案 1 :(得分:4)

对于Androir:

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

答案 2 :(得分: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;
        }
    }

    ...

}

答案 3 :(得分:1)

另一种不干扰自定义渲染器的方法是使按钮InputTransparent透明,并在输入透明时阻止按下。当InputTransparent设置为true时,用户将无法单击按钮,但将保留其所有样式。唯一的问题是,如果在填写最后一个输入字段时激活了按钮,则仍然可以单击该按钮。解决此问题的方法是在按钮click方法中添加一个简单的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   
}

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

  

因为android没有改变颜色,我也通过样式创建了触发器,但也没有解决。

有一些可能导致问题的可能性:

  1. 很可能,您使用错误的Button类型定义渲染器,Droid项目中有Android.widget.ButtonXamarin.Forms.Button,定义渲染器所需的是{{ 1}}:

    Xamarin.Forms.Button
  2. 您不需要设置[assembly:ExportRenderer(typeof(Xamarin.Forms.Button), typeof(MyButtonRenderer))] namespace xxxxxxxxx.Droid { ... } 。实际上当时e.OldElement.TextColor = Color.White;可能是null,因为它代表旧元素。所以只需删除此行。并且代码可以正常工作。