6
votes

Mettez en surbrillance la valeur sélectionnée dans DropdownButton (comme PopupMenuButton)

Lorsqu'un PopupMenuButton est enfoncé, la valeur actuellement sélectionnée est mise en surbrillance, entrez la description de l'image ici

mais quand un DropdownButton est enfoncé , la valeur actuellement sélectionnée n'est pas mise en surbrillance. entrez la description de l'image ici

Existe-t-il un moyen de mettre en évidence la valeur sélectionnée d'un DropdownButton?

Pour référence, voici quelques exemple de code:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: MyHomePage());
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String letter = 'A';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Popup Menu Button')),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          SizedBox(height: 16.0),
          Text('PopupMenuButton'),
          buildPopupMenuButton(),
          SizedBox(height: 16.0),
          Text('DropdownButton'),
          buildDropdownButton(),
        ],
      ),
    );
  }

  Widget buildPopupMenuButton() {
    return PopupMenuButton<String>(
      padding: EdgeInsets.zero,
      initialValue: letter,
      onSelected: (val) => setState(() => letter = val),
      child: ListTile(
        title: Text('The letter $letter'),
      ),
      itemBuilder: (BuildContext context) {
        return <PopupMenuItem<String>>[
          PopupMenuItem<String>(
            value: 'A',
            child: Text('The letter A'),
          ),
          PopupMenuItem<String>(
            value: 'B',
            child: Text('The letter B'),
          ),
        ];
      },
    );
  }

  Widget buildDropdownButton() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16.0),
      child: DropdownButton<String>(
        value: letter,
        onChanged: (val) => setState(() => letter = val),
        items: [
          DropdownMenuItem<String>(
            value: 'A',
            child: Text('The letter A'),
          ),
          DropdownMenuItem<String>(
            value: 'B',
            child: Text('The letter B'),
          ),
        ],
      ),
    );
  }
}

Voici une vidéo qui montre le problème:

 entrez la description de l'image ici

p>


0 commentaires

4 Réponses :


0
votes

Eh bien, pour autant que je sache, cette superposition grise est un soi-disant «effet d'ondulation» dans la bibliothèque de conception de matériaux. Il semble que Flutter n'adapte pas encore le design complet dans tous les widgets.

Cependant, vous pouvez essayer d'utiliser le widget InkWell pour ajouter ce type d'animations / couleurs aux widgets actuels:

https://flutter.io/docs/cookbook/gestures/ripples

Eg:

PopupMenuItem<String>(
    value: 'B',
    child: InkWell(child: Text('The letter B'))
),

Je ne sais pas si la largeur sera correcte, mais au moins elle devrait afficher la superposition grise lorsque vous appuyez sur l'entrée .

Vous pouvez également vérifier la source Flutter: https: // com / flutter / flutter / blob / 237fc2fb45639312001e947bf7465ef9f23bb699 / packages / flutter / lib / src / material / popup_menu.dart # L933

Ici, vous pouvez voir que Inkwell est la norme utilisée pour le PopupMenuButton.


4 commentaires

Merci pour les commentaires, mais je ne suis pas intéressé par l'effet InkWell lorsque le bouton est enfoncé. Je suis intéressé par l'arrière-plan plus sombre de la valeur actuellement sélectionnée lorsque toutes les valeurs sont affichées.


J'ai également fourni le code source dans ma réponse, vous pourriez essayer de l'imiter un peu car je ne comprends pas vraiment ce que vous voulez vraiment réaliser.


Les éléments de menu déroulant et contextuel sont déjà fournis avec un InkWell, apparemment.


Je recherche également une solution pour changer le focus en fonction de la valeur actuellement sélectionnée. Si vous définissez la valeur initiale, elle reste en surbrillance même après avoir appuyé sur d'autres options. Il ne semble pas y avoir de réponse à cela ici.



1
votes

Le DropdownMenuItem ne prend pas en charge de nombreuses modifications personnalisées sur l'élément enfant, car il n'y a pas de style, d'arrière-plan, quoi que ce soit dans les attributs DropdownMenuItem pour vous aider. En regardant le code, il n'a vraiment pas été construit pour ça,

Pourtant, il y a quelque chose que vous pourriez ajouter, une simple vérification de l'attribut child de DropdownMenuItem , et enveloppez l'élément enfant Text dans quelque chose d'autre ou stylisez l'élément Text lui-même s'il est coché.

Un exemple:

DropdownMenuItem<String>(
  value: 'A',
  child: Text('The letter A',
    style: TextStyle(
      color: letter == 'A' ? Colors.red : Colors.black87,
    ),
  ),
)

Notez que dans un scénario réel, vous auriez une méthode avec un paramètre pour construire chaque élément de liste déroulante, donc la vérification n'aurait pas à être codée en dur comme letter == 'A '.

Ce serait le résultat:

 exemple de sortie sélectionné

Cette approche vous permet de styliser un peu, mais cela a un résultat moche dans certains cas. Bien qu'il soit personnalisable, il y aura toujours une marge blanche autour de l'élément, et il affiche également les mêmes styles lorsque la liste déroulante est fermée, donc cela devient un peu moche sur la page principale.

Au lieu de changer l'arrière-plan, vous pouvez également changer les couleurs du texte, le soulignement, les icônes sur le côté, quelque chose comme ça le rend beaucoup mieux, comme:

Widget buildDropdownButton() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16.0),
      child: DropdownButton<String>(
        value: letter,
        onChanged: (val) => setState(() => letter = val),
        items: [
          DropdownMenuItem<String>(
            value: 'A',
            child: Container(
              color: letter == 'A' ? Colors.black12 : null,
              child: Text('The letter A'),
            ),
          ),
          DropdownMenuItem<String>(
            value: 'B',
            child: Container(
              color: letter == 'B' ? Colors.black12 : null,
              child: Text('The letter B'),
            ),
          ),
        ],
      ),
    );
}


0 commentaires

0
votes

En réponse à votre problème initial qui était: " Je suis intéressé par l'arrière-plan plus sombre de la valeur actuellement sélectionnée lorsque toutes les valeurs sont affichées. "

Votre PopupMenuButton examinera son paramètre initialValue: à chaque fois qu'il est ouvert - l'élément correspondant à cette valeur sera mis en évidence. Vous devrez mettre à jour le paramètre initialValue à chaque fois en utilisant la fonction onSelected .

Assurez-vous que le widget parent est un widget StatefulWidget et créez une référence à quelle que soit votre valeur initiale . Le PopupMenuButton a un paramètre onSelected qui prend une fonction avec le paramètre String .

Chaque fois que vous sélectionnez une option dans le PopupMenuButton , appelez

Class YourClass extends StatefulWidget {
  @override
  createState() => _YourClassState();
}

class _YourClassState extends State<YourClass> {
  ...
  String initialValue = 'foo';

  @override
  Widget build(BuildContext context) {
    final items = [
      PopupMenuItem(
        value: 'foo',
        child: Text('foo'),
      ),
      PopupMenuItem(
        value: 'nice',
        child: Text('nice'),
      ),
    }
    return Scaffold(
      appBar: ...,
      drawer: ...,
      body: PopupMenuButton(
        icon: ...,
        itemBuilder: (_) => items,
        initialValue: this.initialValue,
        onSelected: (value) => bar(value),
      ),
    );
  }

  void bar(String value) {
    setState(() {
      ...
      this.initialValue = value;
    });
  }
}

La classe complète ressemblera à quelque chose comme ça. p>

setState(() {
        ...
        this.initialValue = value;
});


1 commentaires

Le PopupMenuButton fonctionne comme vous le souhaitez. Le problème vient du DropdownButton. La valeur actuelle n'est pas mise en surbrillance lors de l'utilisation d'un DropdownButton.



0
votes

Vous pouvez envelopper le widget avec Thème pour définir une couleur de surbrillance.

return Theme(
    data: ThemeData(highlightColor: Colors.grey[300]),
    child: DropdownButton()


0 commentaires