我需要在禁用按钮时更改按钮的文本颜色,我已经为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更改此状态更改,这将是应用的默认样式。
这两种方式都没有解决
答案 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没有改变颜色,我也通过样式创建了触发器,但也没有解决。
有一些可能导致问题的可能性:
很可能,您使用错误的Button
类型定义渲染器,Droid项目中有Android.widget.Button
和Xamarin.Forms.Button
,定义渲染器所需的是{{ 1}}:
Xamarin.Forms.Button
您不需要设置[assembly:ExportRenderer(typeof(Xamarin.Forms.Button),
typeof(MyButtonRenderer))]
namespace xxxxxxxxx.Droid
{
...
}
。实际上当时e.OldElement.TextColor = Color.White;
可能是null,因为它代表旧元素。所以只需删除此行。并且代码可以正常工作。