Visual State'ler

August 8, 2026 · View on GitHub

Visual State Manager, kontrolün görünümünü durumuna göre değiştirir — Normal, Focused, Disabled, PointerOver, Pressed vb. FmgLib.MauiMarkup bunu güçlü tipli VisualState<T> sınıfıyla sarar; stillere veya doğrudan kontrollere takılır, hatta state'e giriş animasyonlarını destekler.

Visual State Tanımlama

VisualState<T>, state adını ve setter lambda'sını alır — her yerdeki aynı fluent özellik API'si:

new VisualState<Button>(VisualStates.Button.Normal, e => e
    .TextColor(Colors.White)
    .BackgroundColor(AppColors.Primary))

Yerleşik state adları — VisualStates yardımcısı

Sihirli string'ler yerine kütüphaneyle gelen sabitler sınıfını kullanın:

SınıfSabitler
VisualStates.VisualElementNormal, Disabled, Focused, PointerOver
VisualStates.Button+ Pressed
VisualStates.ImageButton+ Pressed
VisualStates.Switch+ On, Off
VisualStates.RadioButton+ Checked, Unchecked
VisualStates.CheckBox+ IsChecked
VisualStates.CollectionView+ Selected
VisualStates.CarouselView+ DefaultItem, CurrentItem, PreviousItem, NextItem

(Her kontrol sınıfı ortak VisualElement state'lerini miras alır; VisualStates.Button.Focused da geçerlidir.)

Stilde Visual State'ler

En yaygın yerleşim — Style<T> koleksiyon başlatıcısında, uygulama genelinde:

new Style<Button>(e => e
    .FontSize(14)
    .CornerRadius(8))
{
    new VisualState<Button>(VisualStates.Button.Normal, e => e
        .TextColor(e => e.OnLight(Colors.White).OnDark(AppColors.Primary))
        .BackgroundColor(e => e.OnLight(AppColors.Primary).OnDark(Colors.White))),

    new VisualState<Button>(VisualStates.Button.PointerOver, e => e
        .BackgroundColor(AppColors.PrimaryDark)),

    new VisualState<Button>(VisualStates.Button.Disabled, e => e
        .TextColor(e => e.OnLight(AppColors.Gray950).OnDark(AppColors.Gray200))
        .BackgroundColor(e => e.OnLight(AppColors.Gray200).OnDark(AppColors.Gray600))),
}

Normal'ı her zaman tanımlayın. VSM yalnızca bir state'in ayarladığı özellikleri geri yükler; Normal'ın açık tanımı diğer state'lerden temiz dönüşü garanti eder.

Doğrudan Kontrolde Visual State'ler

VisualStateGroups attached-property metodunu kullanın:

new Entry()
    .Placeholder("E-posta")
    .VisualStateGroups(
        new VisualStateGroupList
        {
            new VisualState<Entry>(VisualStates.VisualElement.Normal, e => e
                .BackgroundColor(Colors.White)),
            new VisualState<Entry>(VisualStates.VisualElement.Focused, e => e
                .BackgroundColor(Colors.LightYellow)),
        })

VisualStateGroups bir VisualStateGroupList alır; doğrudan içine yazdığınız state'ler CommonStates grubuna girer. Kendi grubunuzu tanımlamanız gerekiyorsa VisualStateGroup'u açıkça ekleyin:

new Grid()
    .VisualStateGroups(
        new VisualStateGroupList
        {
            new VisualStateGroup()
                .Name("SelectionStates")
                .States(
                    new VisualState<Grid>("Unselected", e => e.BackgroundColor(Colors.White)),
                    new VisualState<Grid>("Selected", e => e.BackgroundColor(Colors.LightBlue)))
        })

VisualStateGroup'un kendisi koleksiyon başlatıcı sözdizimini desteklemez: state'lerini States property'sinde tutar, IEnumerable uygulamaz. Yukarıdaki gibi VisualStateGroupList kullanın ya da fluent .States(...) metodunu tercih edin.

Visual State İçinde Animasyonlar

VisualState<T> koleksiyon başlatıcısında Action<T> girdileri kabul eder — state'e girildiğinde çalışırlar; async MAUI animasyonları state geçişine dönüşür:

new Style<Button>(e => e.FontSize(20))
{
    new VisualState<Button>(VisualStates.Button.Normal, e => e
        .FontSize(33)
        .TextColor(AppColors.Gray200))
    {
        async button => {
            await button.RotateTo(0);     // Normal'a girişte animasyon
        }
    },

    new VisualState<Button>(VisualStates.Button.Disabled, e => e
        .FontSize(20)
        .TextColor(AppColors.Gray600))
    {
        async button => {
            await button.RotateTo(180);   // Disabled'a girişte animasyon
        }
    },
}

Özellik düzeyi animasyonlar için kütüphanenin ürettiği Animate…To yardımcılarıyla birleştirin:

new VisualState<Button>(VisualStates.Button.PointerOver)
{
    async b => await b.AnimateBackgroundColorTo(Colors.DarkSlateBlue, length: 150)
}

State Trigger'lar — koşullara bağlı state'ler

Bir VisualState<T>, kontrol etkileşimi yerine state trigger'larla da sürülebilir. Bu, duyarlı/adaptif yerleşimleri mümkün kılar:

new VisualStateGroupList
{
    new VisualState<Grid>("Wide", e => e.BackgroundColor(Colors.White))
    {
        new AdaptiveTrigger().MinWindowWidth(800)
    },
    new VisualState<Grid>("Narrow", e => e.BackgroundColor(Colors.WhiteSmoke))
    {
        new AdaptiveTrigger().MinWindowWidth(0)
    },
}

Fluent destekli state trigger'lar:

TriggerAktifleşme koşulu
AdaptiveTriggerPencere boyutu MinWindowWidth/MinWindowHeight eşiğini geçince
CompareStateTriggerBağlanan Property, Value'ya eşit olunca
DeviceStateTriggerBelirli Device (platform) üzerinde çalışırken
OrientationStateTriggerCihaz yönelimi eşleşince
StateTriggerIsActive ayarlanınca (manuel kontrol)

Örnek — yönelime bağlı yerleşim:

new VisualStateGroupList
{
    new VisualState<StackLayout>("Portrait", e => e.Orientation(StackOrientation.Vertical))
    {
        new OrientationStateTrigger().Orientation(DisplayOrientation.Portrait)
    },
    new VisualState<StackLayout>("Landscape", e => e.Orientation(StackOrientation.Horizontal))
    {
        new OrientationStateTrigger().Orientation(DisplayOrientation.Landscape)
    },
}

Programatik State Değişimi

Standart MAUI geçerlidir:

VisualStateManager.GoToState(myButton, "CustomState");

Özel state adları çalışır — kendi adınızla bir VisualState<T> tanımlayıp koddan tetikleyin.

Visual State mi, Trigger mı?

Visual state'lerTrigger'lar
SürücüAdlandırılmış kontrol durumları (+ state trigger'lar)Özellik değerleri / binding'ler / olaylar
Karşılıklı dışlayıcıEvet, grup içindeHayır
Animasyon desteğiEvet (aksiyon girdileri)EventTrigger aksiyonlarıyla
En uygunEtkileşim geri bildirimi, adaptif yerleşimVeriye bağlı özellik değişimleri

İlgili Konular