我正试图用Xamarin为自己编写一款游戏。问题是,在按下开始按钮后,我无法使颜色动态变化。起初,我试图通过BackgroundColor属性来实现,但由于它不起作用,我决定使用动态资源,但这也不起作用。请帮我找出代码或算法中的错误
P.s
游戏是这样的:从记忆中再现一系列颜色,难度逐渐增加:起初只有一个按钮高亮显示,然后已经有两个按钮了,以此类推。如果你准确地到达第20阶段(再现20种颜色的序列(并完成它,胜利就实现了。
P.P.s
我在手机上运行了应用程序-小米Poco X3 NFC,我的操作系统是MIUI 12(Android 10(。
主页.xaml.cs
using System;
using System.Threading;
using Xamarin.Forms;
namespace JustRepeat
{
public partial class MainPage : ContentPage
{
public readonly MethodsCollection methodsCollection;
public readonly Button[] buttonsMas;
public MainPage()
{
InitializeComponent();
methodsCollection = new MethodsCollection(this);
buttonsMas = new Button[] { one, two, three, four, five, six, seven, eight, nine };
}
private void Button_Clicked(object sender, EventArgs e)
{
methodsCollection.PlaySequence();
startstop.IsEnabled = false;
}
private void Buttons_Clicked(object sender, EventArgs e)
{
bool result = methodsCollection.CheckSequence((Button)sender, out int currStg);
if (!result)
{
DisplayAlert("Notification", $"You lose.nThe last passed stage: {currStg}.", "OK");
startstop.IsEnabled = true;
return;
}
else if (result & currStg == 20)
{
DisplayAlert("Notification", "You won!", "OK");
startstop.IsEnabled = true;
}
}
}
public class MethodsCollection
{
private readonly MainPage mainPage;
private Color[] colors;
private int[] sequence;
private int currentStage = 1;
private int currentMember = 0;
public MethodsCollection(MainPage mP)
{
mainPage = mP;
}
private int[] GenerateSequence(int currentNumber)
{
Random random = new Random();
int[] posMas = new int[currentNumber];
for (int i = 0; i < posMas.Length; i++)
{
posMas[i] = random.Next(1, 10);
}
return posMas;
}
public void PlaySequence()
{
Random random = new Random();
sequence = GenerateSequence(currentStage);
colors = new Color[currentStage];
for (int i = 0; i < sequence.Length; i++)
{
colors[i] = Color.FromRgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256));
mainPage.Resources[string.Format("{0}", sequence[i])] = colors[i];
Thread.Sleep(1000);
mainPage.Resources[string.Format("{0}", sequence[i])] = Color.LightGray;
}
}
public bool CheckSequence(Button btn, out int stage)
{
int pos = 0;
for (int i = 0; i < mainPage.buttonsMas.Length; i++)
{
if (btn == mainPage.buttonsMas[i])
{
pos = i;
}
}
if (currentStage == 20)
{
if (pos == sequence[currentMember])
{
SetColor();
ClearVariables();
stage = currentStage;
currentStage = 1;
return true;
}
ClearVariables();
stage = currentStage - 1;
currentStage = 1;
return false;
}
if (currentStage - currentMember == 1)
{
if (pos == sequence[currentMember])
{
SetColor();
ClearVariables();
stage = currentStage++;
return true;
}
ClearVariables();
stage = currentStage - 1;
currentStage = 1;
return false;
}
if (pos == sequence[currentMember])
{
currentMember++;
stage = currentStage;
return true;
}
else
{
ClearVariables();
stage = currentStage - 1;
currentStage = 1;
return false;
}
}
private void SetColor()
{
mainPage.Resources[string.Format("{0}", sequence[currentMember])] = colors[currentMember];
Thread.Sleep(1000);
mainPage.Resources[string.Format("{0}", sequence[currentMember])] = Color.LightGray;
}
private void ClearVariables()
{
currentMember = 0;
sequence = null;
colors = null;
}
}
}
主页.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="JustRepeat.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="1">LightGray</Color>
<Color x:Key="2">LightGray</Color>
<Color x:Key="3">LightGray</Color>
<Color x:Key="4">LightGray</Color>
<Color x:Key="5">LightGray</Color>
<Color x:Key="6">LightGray</Color>
<Color x:Key="7">LightGray</Color>
<Color x:Key="8">LightGray</Color>
<Color x:Key="9">LightGray</Color>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Grid VerticalOptions="FillAndExpand" >
<Button BackgroundColor="{DynamicResource Key=1}" Clicked="Buttons_Clicked" Grid.Column="0" Grid.Row="0" x:Name="one"/>
<Button BackgroundColor="{DynamicResource Key=2}" Clicked="Buttons_Clicked" Grid.Column="1" Grid.Row="0" x:Name="two"/>
<Button BackgroundColor="{DynamicResource Key=3}" Clicked="Buttons_Clicked" Grid.Column="2" Grid.Row="0" x:Name="three"/>
<Button BackgroundColor="{DynamicResource Key=4}" Clicked="Buttons_Clicked" Grid.Column="0" Grid.Row="1" x:Name="four"/>
<Button BackgroundColor="{DynamicResource Key=5}" Clicked="Buttons_Clicked" Grid.Column="1" Grid.Row="1" x:Name="five"/>
<Button BackgroundColor="{DynamicResource Key=6}" Clicked="Buttons_Clicked" Grid.Column="2" Grid.Row="1" x:Name="six"/>
<Button BackgroundColor="{DynamicResource Key=7}" Clicked="Buttons_Clicked" Grid.Column="0" Grid.Row="2" x:Name="seven"/>
<Button BackgroundColor="{DynamicResource Key=8}" Clicked="Buttons_Clicked" Grid.Column="1" Grid.Row="2" x:Name="eight"/>
<Button BackgroundColor="{DynamicResource Key=9}" Clicked="Buttons_Clicked" Grid.Column="2" Grid.Row="2" x:Name="nine"/>
</Grid>
<Button BackgroundColor="DarkGray" Text="Старт" Clicked="Button_Clicked" VerticalOptions="Fill" x:Name="startstop"/>
</StackLayout>
</ContentPage>
尝试做"任何东西";就像在xamarin中设置按钮的颜色以显示错误一样,需要以正确的方式在正确的地方完成。在代码设置中,按钮的颜色与应用程序无关,因为您不调用更改。
使用设置颜色
Device.BeginInvokeOnMainThread(() =>
{
// Your method to change the color.
button.BackgroundColor = Color.Black; // Or whatever.
});
例如,如果您需要DisplayAlert,您也可以执行此异步操作。
Device.BeginInvokeOnMainThread(async () => // <-----
{
// You await the message
await DisplayAlert("Attention", "Color changed!", "OK);
});
把这个问题解决在评论中,但我发布了一个答案供将来参考。
加载页面后更改资源的值不会影响按钮颜色-它已经从资源中读取。
相反,给按钮一个x:Name
,这样您就可以直接设置其背景颜色。
xaml:
<Button x:Name="button1" ... />
cs:
button1.BackgroundColor = ...;
OR可能是Device.BeginInvokeOnMainThread
,如stersym
的答案所示。
(我添加了一个新答案,因为该答案没有显示x:Name
。(
重要信息:Intellisense在构建之后才会知道button1
我所做的是将x:Name
添加到XAML
,构建项目,然后添加使用该名称的cs
代码。
对于那些对此也有问题的人,特别是在新版本中,如果您的AppTheme
设置为任何类型的材料设计,则Button
将表现为MaterialButton
,因此您无法更改其背景。
要解决此问题,请不要像<Button/>
那样创建按钮,而是创建为<androidx.appcompat.widget.AppCompatButton />
。
现在它应该起作用了。