Я использовал эту логику для анимации. Можно ли упростить эту логику?

SliverAppBar FlexibleSpaceBar

  void _positionListener() {
    final FlexibleSpaceBarSettings settings = context.dependOnInheritedWidgetOfExactType();
    _fontSize = getFontSize(settings.minExtent.toInt(), settings.maxExtent.toInt(), settings.currentExtent.toInt());
setState(() {});
  }

необходимо упростить приведенную ниже логику

 double getFontSize(int minExtent, int maxExtent, int currentExtent){
    double onePaddingExtent = (maxExtent - minExtent) / 31;

    if (currentExtent >= minExtent && currentExtent <= minExtent + (1 * onePaddingExtent))
      return 3.0;
    else if (currentExtent > minExtent + (1 * onePaddingExtent) && currentExtent <= minExtent + (2 * onePaddingExtent))
      return 2.9;
    else if (currentExtent > minExtent + (2 * onePaddingExtent) && currentExtent <= minExtent + (3 * onePaddingExtent))
      return 2.8;
    else if (currentExtent > minExtent + (3 * onePaddingExtent) && currentExtent <= minExtent + (4 * onePaddingExtent))
      return 2.7;
    else if (currentExtent > minExtent + (4 * onePaddingExtent) && currentExtent <= minExtent + (5 * onePaddingExtent))
      return 2.6;
    else if (currentExtent > minExtent + (5 * onePaddingExtent) && currentExtent <= minExtent + (6 * onePaddingExtent))
      return 2.5;
    else if (currentExtent > minExtent + (6 * onePaddingExtent) && currentExtent <= minExtent + (7 * onePaddingExtent))
      return 2.4;
    else if (currentExtent > minExtent + (7 * onePaddingExtent) && currentExtent <= minExtent + (8 * onePaddingExtent))
      return 2.3;
    else if (currentExtent > minExtent + (8 * onePaddingExtent) && currentExtent <= minExtent + (9 * onePaddingExtent))
      return 2.2;
    else if (currentExtent > minExtent + (9 * onePaddingExtent) && currentExtent <= minExtent + (10 * onePaddingExtent))
      return 2.1;
    else if (currentExtent > minExtent + (10 * onePaddingExtent) && currentExtent <= minExtent + (11 * onePaddingExtent))
      return 2.0;
    else if (currentExtent > minExtent + (11 * onePaddingExtent) && currentExtent <= minExtent + (12 * onePaddingExtent))
      return 1.9;
    else if (currentExtent > minExtent + (12 * onePaddingExtent) && currentExtent <= minExtent + (13 * onePaddingExtent))
      return 1.8;
    else if (currentExtent > minExtent + (13 * onePaddingExtent) && currentExtent <= minExtent + (14 * onePaddingExtent))
      return 1.7;
    else if (currentExtent > minExtent + (14 * onePaddingExtent) && currentExtent <= minExtent + (15 * onePaddingExtent))
      return 1.6;
    else if (currentExtent > minExtent + (15 * onePaddingExtent) && currentExtent <= minExtent + (16 * onePaddingExtent))
      return 1.5;
    else if (currentExtent > minExtent + (16 * onePaddingExtent) && currentExtent <= minExtent + (17 * onePaddingExtent))
      return 1.4;
    else if (currentExtent > minExtent + (17 * onePaddingExtent) && currentExtent <= minExtent + (18 * onePaddingExtent))
      return 1.3;
    else if (currentExtent > minExtent + (18 * onePaddingExtent) && currentExtent <= minExtent + (19 * onePaddingExtent))
      return 1.2;
    else if (currentExtent > minExtent + (19 * onePaddingExtent) && currentExtent <= minExtent + (20 * onePaddingExtent))
      return 1.0;
    else if (currentExtent > minExtent + (20 * onePaddingExtent) && currentExtent <= minExtent + (21 * onePaddingExtent))
      return 1;
    else if (currentExtent > minExtent + (21 * onePaddingExtent) && currentExtent <= minExtent + (22 * onePaddingExtent))
      return 0.9;
    else if (currentExtent > minExtent + (22 * onePaddingExtent) && currentExtent <= minExtent + (23 * onePaddingExtent))
      return 0.8;
    else if (currentExtent > minExtent + (23 * onePaddingExtent) && currentExtent <= minExtent + (24 * onePaddingExtent))
      return 0.7;
    else if (currentExtent > minExtent + (24 * onePaddingExtent) && currentExtent <= minExtent + (25 * onePaddingExtent))
      return 0.6;
    else if (currentExtent > minExtent + (25 * onePaddingExtent) && currentExtent <= minExtent + (26 * onePaddingExtent))
      return 0.5;
    else if (currentExtent > minExtent + (26 * onePaddingExtent) && currentExtent <= minExtent + (27 * onePaddingExtent))
      return 0.4;
    else if (currentExtent > minExtent + (27 * onePaddingExtent) && currentExtent <= minExtent + (28 * onePaddingExtent))
      return 0.3;
    else if (currentExtent > minExtent + (28 * onePaddingExtent) && currentExtent <= minExtent + (29 * onePaddingExtent))
      return 0.2;
    else if (currentExtent > minExtent + (29 * onePaddingExtent) && currentExtent <= minExtent + (30 * onePaddingExtent))
      return 0.1;
    else if (currentExtent > minExtent + (30 * onePaddingExtent) && currentExtent <= minExtent + (31 * onePaddingExtent))
      return 0;
    else
      return 0;
  }

Я пробовал этот способ, но не работал

  double getFontSize(int minExtent, int maxExtent, int currentExtent) {
    double onePaddingExtent = (maxExtent - minExtent) / 31;
    
    var baseValue = (currentExtent + minExtent) / onePaddingExtent ;
    var upperBaseValue = baseValue.round();
    var lowerBaseValue = baseValue.floor();


    var result = 30 - Math.min(upperBaseValue, lowerBaseValue);

    return Math.max(result, 0);
  }
0
BloodLoss 20 Янв 2021 в 19:46

2 ответа

Лучший ответ

Сначала мы видим, что в ваших случаях есть шаблон, и упрощаем его с помощью цикла:

 double getFontSize(int minExtent, int maxExtent, int currentExtent) {
    double onePaddingExtent = (maxExtent - minExtent) / 31;

    for (var i = 0; i < 31; i += 1) {
      if (currentExtent >= minExtent + (i * onePaddingExtent) &&
          currentExtent <= minExtent + (i + 1) * onePaddingExtent) {
        return 3.0 - i / 10;
    }  
    return 0;
  }
}

(В исходном коде ваш первый случай немного отличается, поскольку он проверяет закрытый интервал [минимум, максимум], тогда как все последующие случаи проверяют полуоткрытый интервал (минимум, максимум] Однако, поскольку цикл будет проверять случаи по порядку, не имеет значения, используем ли мы закрытый интервал для всех случаев: значение, которое точно соответствует минимуму / максимуму, в любом случае будет удовлетворено только первым применимым случаем.)

Отсюда мы можем алгебраически переставить неравенства и увидеть, что условие if эквивалентно:

if ((currentExtent - minExtent) / onePaddingExtent >= i &&
    (currentExtent - minExtent) / onePaddingExtent <= (i + 1))

Это означает, что (currentExtent - minExtent) / onePaddingExtent лежит в диапазоне [i, i + 1] для некоторого целого i. Другими словами, i - наибольшее целое число, которое меньше или равно (currentExtent - minExtent) / onePaddingExtent. Следовательно, вместо повторения поиска i, мы можем вычислить i напрямую, без цикла:

double getFontSize(int minExtent, int maxExtent, int currentExtent) {
  double onePaddingExtent = (maxExtent - minExtent) / 31;
  var i = ((currentExtent - minExtent) / onePaddingExtent).floor();
  if (i >= 0 && i < 31) {
    return 3.0 - i / 10;
  }
  return 0;
}

Обратите внимание, что приведенные выше упрощения могут возвращать очень незначительно значения, отличные от исходного кода (например, 0.9 vs 0.8999999999999999), но это артефакт выполнения дополнительных операций с плавающей запятой. (Не обманывайте себя; значения с плавающей запятой, даже литералы, не точны.)

1
jamesdlin 20 Янв 2021 в 20:20

Может ты можешь попробовать это

if (currentExtent >= minExtent && currentExtent <= minExtent + (1 * onePaddingExtent)) return 3.0;
else for (int i = 1; i <= 30; ++ i) if ((currentExtent > minExtent + (i * onePaddingExtent)) && (currentExtent <= minExtent + ((i + 1) * onePaddingExtent))) return 3.0 - (i / 10);
2
dm_tr 20 Янв 2021 в 16:56