предисловие
Некоторое время назад я изучил Flutter анимацию, и я волновался о написании проекта для практики и закрепления, и вдруг в один прекрасный день продукт прислал ссылку в группу [вкладка Анимация в ios] (ниже есть пример изображения), и я сказал в моем сердце: «Хороший парень». Если продукт должен быть сделан таким, менеджер по продукту и программист должны сражаться снова и снова!
Адрес гитхаба:GitHub.com/longer96/law…
Каждый день мы видим нижние навигационные меню, которые направляют пользователей в приложении, позволяя им быстро переключаться между тегами. Но кто сказал, что переключение вкладок должно быть скучным? Давайте вместе изучим интересные анимации на панели вкладок. Хотя вы можете не использовать его в своем приложении, просмотр его реализации может дать вам некоторое вдохновение, ссылку на дизайн.
Если так случится, что он сможет помочь вам, это будет здорово~ Проходящий мимо красавчик может помочь вам, заказав звезду.
Давайте начнем с нескольких причудливых нижних меню для справки.
Анализ эффективности
Кхм, некоторые анимации действительно сложные и требуют полной поддержки дизайнера, поэтому пришлось выбирать мягкую хурму.
Сначала заметим, что он состоит из текста и индикаторов. После нажатия индикатор переключается, а текст увеличивается.
- Каждый тег делит ширину экрана поровну
- После нажатия индикатор вытягивается из предыдущего среднего положения тега в среднее положение выбранного тега.
- После того, как индикатор достигает выбранного тега, длина сразу же сокращается до положения выбранного тега.
Немного сложнее анимация индикатора, который имеет 3 переменные: левое поле, правое поле и ширину индикатора. Но чем больше переменных, тем неудобнее контролировать.Поразмыслив хорошенько, мы обнаружили, что нам нужно только контролировать: достаточно левого и правого полей, а ширина индикатора устанавливается адаптивной (или контролируется только левое поле и ширина индикатора)
добиться эффекта
На самом деле многие подобные нижние меню можно сделать таким же образом, индикатор находится за тегом, а положение и размер можно регулировать по разным условиям.
Реализовать нижнее меню
Обычно есть другое меню, которое расширяется аналогично, например, это
Кратко проанализируем
- Он состоит из одной кнопки и нескольких кнопок-тегов.
- После нажатия тег расширяется или сжимается в форме веера.
Вроде всего 2 шага, все равно очень просто.
Шаг 1: Складываем кнопки и теги с макетом рамки
Stack(
children: [
// tag菜单
// 菜单/关闭 按钮
]
)
Шаг 2. Управляйте расположением тегов Краткое введение в Flow Flow во Flutter — очень эффективный элемент управления для настройки размера и положения подкомпонентов.
Flow использует матрицу преобразования для оптимизации настройки положения подкомпонентов: после позиционирования Flow, если изменяется размер или положение подкомпонента, вызовите context.paintChild в методе paintChildren() в FlowDelegate для перерисовки, а context.paintChild использует матрицу преобразования при перерисовке и фактически не регулирует положение компонента.
Он также очень прост в использовании: вам нужно всего лишь реализовать метод paintChildren() класса FlowDelegate, чтобы настроить стратегию компоновки. Итак, нам нужно рассчитать положение траектории каждого тега.
После вашего внимательного наблюдения вы обнаружите, что траектория метки разворачивается в виде полукруга Правильно, правильно, вам нужно вывернуть тригонометрическую функцию.
После очередного внимательного наблюдения вы обнаружили, что тегов 5, а полукруг реально может поставить 7 тегов, но для лучшего эффекта отображения можно разместить теги, которые нужно отображать, в среднее положение (фильтр из первого и последнего тегов)
Итак, мы можем перечислить простые расчеты
final total = context.childCount + 1;
for (int i = 0; i < childCount; i++) {
x = cos(pi * (total - i - 1) / total) * Radius;
y = sin(pi * (total - i - 1) / total) * Radius;
}
Вы обнаружите, что слишком правильный круг на самом деле выглядит не так красиво, оптимизируйте его.
- Установите радиус оси X до половины ширины родительского ограничения
- Установите радиус Y на высоту родительского ограничения
- Добавьте кривую к анимации, чтобы тег имел аналогичный эффект отскока.
- Обратите внимание, что ось Y должна быть преобразована в отрицательное число, потому что наши координаты ниже
Немного доработайте, хорошо, поздравляю! 3 предложения кода, пусть продакт-менеджер закажет для вас 18 чашек чая
class FlowAnimatedCircle extends FlowDelegate {
final Animation<double> animation;
/// icon 尺寸
final double iconSize = 48.0;
/// 菜单左右边距
final paddingHorizontal = 8.0;
FlowAnimatedCircle(this.animation) : super(repaint: animation);
@override
void paintChildren(FlowPaintingContext context) {
// 进度等于0,也就是收起来的时候不绘制
final progress = animation.value;
if (progress == 0) return;
final xRadius = context.size.width / 2 - paddingHorizontal;
final yRadius = context.size.height - iconSize;
// 开始(0,0)在父组件的中心
double x = 0;
double y = 0;
final total = context.childCount + 1;
for (int i = 0; i < context.childCount; i++) {
x = progress * cos(pi * (total - i - 1) / total) * xRadius;
y = progress * sin(pi * (total - i - 1) / total) * yRadius;
// 使用Matrix定位每个子组件
context.paintChild(
i,
transform: Matrix4.translationValues(
x, -y + (context.size.height / 2) - (iconSize / 2), 0),
);
}
}
@override
bool shouldRepaint(FlowAnimatedCircle oldDelegate) => false;
}
Если вы понимаете приведенную выше реализацию, следующие три могут быть легко выполнены.
наконец
Я собрал и реализовал несколько нижних навигаций для справки.Конечно, может быть много мест, которые нужно оптимизировать.Не распыляйтесь на меня.
- Было отличное нижнее меню, хотел бы порекомендовать
- Если вам нужно его использовать, рекомендуется клонировать его, импортировать напрямую и добавить определенные требования (например, непрочитанные сообщения) самостоятельно.
- Добро пожаловать, Fork & pr, чтобы поделиться своим кодом, давайте учиться вместе ❤
- Загрузка опыта Androidd.cc53.cn/sn6c
- Веб-онлайн-опытfooter.eeaarr.cn