#xamarin.forms
#xamarin.forms
Вопрос:
Проблема
- Визуальный диспетчер состояний не запускается
- Как мне изменить фон выбранного фрейма?
Любые предложения о том, что я делаю неправильно?
Мне нужно создать горизонтальный список с набором фреймов, которые при выборе меняют цвет фона.
Очевидной реализацией будет CollectionView, у которого есть SelectedItem, который будет просто работать, так в чем проблема с этим?
Ну, если у вас есть pancakeView / frame с закругленными углами в iOS, вы можете увидеть серый фон и сообщение об ошибке в формах xamarin.
Итак, я решил реализовать bindableLayout, это работает нормально, однако я перепробовал все виды, но я не могу изменить цвет фона блина / фрейма и метки при выборе, ниже то, что я сделал
Главная страница
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Grid">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="LightSkyBlue" />
<Setter TargetName="LabelA" Property="Label.TextColor" Value="Red"/>
<Setter TargetName="Labelb" Property="Label.TextColor" Value="Red"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<FlexLayout x:Name="Flex"
Direction="Row"
BindableLayout.ItemsSource="{Binding Cities}"
Position="Relative"
AlignItems="Start"
FlowDirection="LeftToRight"
JustifyContent="SpaceEvenly">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid x:Name="myGrid" Padding="8,0" FlexLayout.AlignSelf="Start" >
<pancakeView:PancakeView x:Name="myPancake"
Padding="20"
Margin="5"
CornerRadius="5"
WidthRequest="60"
HeightRequest="60"
BackgroundColor="White" >
<pancakeView:PancakeView.Border>
<pancakeView:Border Thickness="1" Color="Blue" />
</pancakeView:PancakeView.Border>
<StackLayout >
<Label x:Name="LabelA" Margin="0,0,0,0"
Text="{Binding Name }"
TextColor="Gray"
HorizontalOptions="Center" VerticalOptions="Center">
</Label>
<Label x:Name="Labelb" VerticalOptions="EndAndExpand"
HorizontalTextAlignment="Center"
TextColor="Gray"
FontSize="12"
Text="SomeText Here" />
</StackLayout>
<pancakeView:PancakeView.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped">
</TapGestureRecognizer>
</pancakeView:PancakeView.GestureRecognizers>
</pancakeView:PancakeView>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</FlexLayout>
</ContentPage>
КОД ГЛАВНОЙ СТРАНИЦЫ ПОЗАДИ
using System;
using Xamarin.Forms;
namespace BlankApp2.Views
{
public partial class MainPage
{
string currentColorState = "Normal";
public MainPage()
{
InitializeComponent();
}
private void TapGestureRecognizer_OnTapped(object sender, EventArgs e)
{
currentColorState = currentColorState == "Normal" ? "Focused" : "Normal";
//below has errors since "myPancake, LabelA Labelb are not recognized WHY????
// VisualStateManager.GoToState(myPancake,_currentColorState);
// VisualStateManager.GoToState(LabelA, _currentColorState);
// VisualStateManager.GoToState(Labelb, _currentColorState);
}
}
}
VIEWMODEL
using Prism.Navigation;
using System.Collections.ObjectModel;
namespace BlankApp2.ViewModels
{
public class MainPageViewModel : ViewModelBase
{
public MainPageViewModel(INavigationService navigationService)
: base(navigationService)
{
Title = "Main Page";
Cities = GetCities();
}
private ObservableCollection<City> cities;
public ObservableCollection<City> Cities
{
get => cities;
set => SetProperty(ref cities, value);
}
private ObservableCollection<City> GetCities()
{
var list = new ObservableCollection<City>
{
new City {Name = "London"},
new City {Name = "Rome"},
new City {Name = "New York"}
};
return list;
}
}
public class City
{
public string Name { get; set; }
}
}
Ответ №1:
Попробуйте добавить VisualStateManager.VisualStateGroups
свой фрейм / pancakeviw (здесь я тестирую с помощью frame).
создайте пользовательский фрейм:
class MyFrame :Frame
{
public bool IsFoucs { get; set; }
}
страница.xaml:
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="local:MyFrame">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" >
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="White" />
<Setter TargetName="LabelA" Property="Label.TextColor" Value="Gray"/>
<Setter TargetName="Labelb" Property="Label.TextColor" Value="Gray"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="LightSkyBlue" />
<Setter TargetName="LabelA" Property="Label.TextColor" Value="Red"/>
<Setter TargetName="Labelb" Property="Label.TextColor" Value="Red"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<FlexLayout x:Name="Flex"
Direction="Row"
BindableLayout.ItemsSource="{Binding Cities}"
Position="Relative"
AlignItems="Start"
FlowDirection="LeftToRight"
JustifyContent="SpaceEvenly">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid x:Name="myGrid" Padding="8,0" FlexLayout.AlignSelf="Start" >
<local:MyFrame x:Name="myPancake"
Padding="20"
Margin="5"
CornerRadius="5"
WidthRequest="60"
HeightRequest="60"
BorderColor="Blue"
BackgroundColor="White" >
<StackLayout >
<Label x:Name="LabelA" Margin="0,0,0,0"
Text="{Binding .}"
TextColor="Gray"
HorizontalOptions="Center" VerticalOptions="Center">
</Label>
<Label x:Name="Labelb" VerticalOptions="EndAndExpand"
HorizontalTextAlignment="Center"
TextColor="Gray"
FontSize="12"
Text="SomeText Here" />
</StackLayout>
<local:MyFrame.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped">
</TapGestureRecognizer>
</local:MyFrame.GestureRecognizers>
</local:MyFrame>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</FlexLayout>
затем в page.cs:
private void TapGestureRecognizer_OnTapped(object sender, EventArgs e)
{
foreach (var item in Flex.Children)
{
MyFrame frame = (MyFrame)item.FindByName("myPancake");
frame.IsFoucs = false;
VisualStateManager.GoToState(frame, "Normal");
}
MyFrame myFrame = sender as MyFrame;
myFrame.IsFoucs = !myFrame.IsFoucs;
VisualStateManager.GoToState(myFrame, myFrame.IsFoucs ? "Focused" : "Normal");
}
эффект выглядит следующим образом:
Комментарии:
1. Привет, большое спасибо за ваше время, скопировал код и частично работает. По некоторым причинам выбирается все, что вы нажимаете, и не отменяет выбор предыдущего выбранного фрейма. Что происходит, так это то, что вы нажимаете на первый, это нормально, 2-е нажатие требует двойного нажатия, прежде чем оно будет выбрано, но предыдущий выбор не отменяется. Очевидно, вы не понимаете такого поведения, не так ли?
2. Я даже пробовал с DataTriggers и не смог заставить его работать.
3. @developer9969 Это моя ошибка, так как я использую одно и то же
currentColorState
для каждого фрейма. Вы можете проверить обновление выше, я создаю пользовательский фрейм и добавляю к нему свойство bool.4. Привет, теперь двойное нажатие не требуется, если оставить все остальные выбранные фреймы. есть ли способ зациклить и отменить выбор всего фрейма перед его установкой. Работает ли это в вашем примере? еще раз спасибо за ваше время
5. @developer9969 Вы имеете в виду единый выбор?