web-dev-qa-db-fra.com

Comment changer les couleurs de la barre de navigation et de la barre de navigation dans Xamarin Forms?

J'ai une application Xamarin Forms et je travaille actuellement sur du code pour iOS. Dans mes paramètres, j'ai une option pour changer le thème de l'application (Dark and Light). En gros, cela ne fait que changer les couleurs d’arrière-plan et les couleurs du texte des pages. Maintenant, ce que je veux faire, c'est pouvoir changer les SelectedImageTintColor et BarTintColor de TabBar ainsi que les BarTintColor et TintColor de NavigationBar. Pour le moment, j'ai créé un moteur de rendu pour la page à onglets: 

protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
   base.OnElementChanged(e);
   App.theme = (Theme)App.DB.GetIntSetting("ThemeColor");
   switch (App.theme)
   {
      case Theme.Dark:
      {
         TabBar.SelectedImageTintColor = UIColor.FromRGB(255, 165, 0);
         TabBar.BarTintColor = UIColor.Black;
         break;
      }
      case Theme.Light:
      {
         TabBar.SelectedImageTintColor = UIColor.FromRGB(60, 132, 60);
         TabBar.BarTintColor = UIColor.White;
         break;
      }
   }
}

À l'heure actuelle, ces couleurs ne prendraient effet qu'au premier démarrage de l'application. 

 enter image description here

J'ai fait des recherches sur ce problème mais je n'ai trouvé aucune réponse de quiconque sur la façon de le résoudre. 

Je sais que de nombreux changements ont eu lieu chez Xamarin et j'aimerais donc savoir s'il y a eu des développements récents ou de nouveaux moyens de résoudre ce problème. Je suis ouvert à la recherche de suggestions éventuelles dans le cadre de l'exigence relative à l'application qui consiste à pouvoir modifier ces couleurs.

Edits: 

Ma page Tabbed a été créée comme suit: 

public partial class MainPage : TabbedPage
{
   public MainPage()
   {
      InitializeComponent();
      var phrasesPage = new NavigationPage(new PhrasesPage())
      {
         Title = "Play",
         Icon = "play1.png"
      };
      var settingsPage = new NavigationPage(new SettingsPage())
      {
         Title = "Settings",
         Icon = "settings.png"
      };
      // other declarations here

      Children.Add(phrasesPage);
      Children.Add(settingsPage);
      // and more
   }
}

Par exemple, si je choisis un thème sombre, la couleur d'arrière-plan TabBar et NavigationBar sera noire, l'image sélectionnée de TabBar sera orange et le texte de NavigationBar sera blanc. De même, si je choisis le thème Lumière, la couleur d'arrière-plan TabBar et NavigationBar sera blanche, l'image sélectionnée de TabBar sera verte et le texte de NavigationBar sera noir.

14
user6742877

Je pense que le problème est que vous n'écoutez pas et ne gérez pas le changement de thème. Vous définissez les couleurs dans OnElementChanged qui ne seront pas rappelées lorsque vous modifiez le thème. 

Vous pouvez créer une propriété qui déclenchera un événement auquel vous vous êtes abonné dans votre moteur de rendu personnalisé. Par exemple, si vous créez la propriété dans votre classe App, dans votre rendu personnalisé TabbedPage, vous pouvez effectuer les opérations suivantes:

protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
    base.OnElementChanged(e);

    if(e.OldElement != null)
    {
        App.Current.PropertyChanged -= Current_PropertyChanged;
        return;
    }

    App.Current.PropertyChanged += Current_PropertyChanged; //subscribe to the App class' built in property changed event
    UpdateTheme();
}

void Current_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    if(e.PropertyName == "DarkTheme")
    {
        UpdateTheme();
    }
}

Étant donné que la barre de navigation est contrôlée par NavigationPage, vous devrez également écouter le changement de propriété. Heureusement, vous n'avez pas besoin d'un moteur de rendu personnalisé, car vous pouvez modifier les couleurs des barres et du texte avec les propriétés Forms. Vous pouvez donc créer une classe qui hérite de NavigationPage et vous abonner à l'événement:

public class CustomNavigationPage : NavigationPage
{
    public CustomNavigationPage(Page root) : base(root)
    {
        if(Device.OS == TargetPlatform.iOS)
        {
            App.Current.PropertyChanged += Current_PropertyChanged;
        }
    }
}

J'ai créé un exemple de projet qui illustre tout cela pour que vous puissiez le vérifier :) 

8
jimmgarr

Vous pouvez utiliser la propriété de la barre de tabulation pour changer la couleur de l'arrière-plan et des icônes chaque fois que vous en avez besoin. 

 TabBar.TintColor = UIColor.White; // changer as per your need for tab icon's color
TabBar.BarTintColor = UIColor.Black; // changer as per your need for tabbar's backgroungcolor 

idem que pour la navigation

this.NavigationController.NavigationBar.TintColor = UIColor.White;//change as per your need for tab icon color

this.NavigationController.NavigationBar.BarTintColor = UIColor.Black;// changer as per your need for Navbar' backgroungcolor 
1
KKRocks

Connaissez-vous la fonctionnalité "Ressource dynamique" dans Xamarin Forms?

Je vais donner ma façon de le faire. Ce ne sera peut-être pas facile, mais je pense que cela peut marcher.

Étape 1: Dans app.xaml, définissez les clés et les icônes par défaut comme suit

<FileImageSource x:Key="PlayIconKey">playdark.png</FileImageSource>
<FileImageSource x:Key="AboutIconKey">aboutdark.png</FileImageSource>

and

<Image Source="{ DynamicResource PlayIconKey }" />
<Image Source="{ DynamicResource AboutIconKey}" />

etc..

Étape 2: Dans votre ensemble de pages à onglets, comme

var phrasesPage = new NavigationPage(new PhrasesPage())
{
 Title = "Play",
 Icon = Application.Current.Resources["PlayIconKey"]
};

et ainsi de suite pour d'autres pages dans TabbedPage

Étape 3: Maintenant, lorsque vous modifiez les paramètres, définissez simplement

Application.Current.Resources["PlayIconKey"] = "playlight.png" 

et d'autres icônes ici.

Avec cette approche, vous pouvez changer toutes les icônes en un seul endroit ..__ Laissez-moi savoir votre opinion à ce sujet.

0
Avinash Ramireddy