предисловие
Я правда давно не вел блог, потому что был слишком занят работой в последнее время😅, но занятость имеет и то преимущество, что она занята. Я обогащаюсь, пока занят, и узнаю новые знания. потому что чистыйFlutter
конецIM
Функция (слишком сложная ТМ! 🤣) Во всем процессе реализации напишите часть своего понимания пользовательского интерфейса какblog
. сегодня! Я хотел бы представить вам мою семью пузырей🔮, которая представляет собой чат-пузырь balbla~ в WeChat, который вы видите.
Show Time
Непретенциозный - текстовый пузырь 📒
Первый – сравнитьnormal
, 🐳 Но самое главное, текстовый пузырь, этот пузырь не требует слишком много функций. Он практичен, лаконичен и точен, и он может захватить сердца людей. Проще говоря, он заставляет пользователей чувствовать себя очень комфортно. Давайте посмотрим на наш готовый продукт:
Не спрашивайте меня, почему у меня закруглены углы, потому что наша команда художников разработала это таким образом, некоторые люди думают, что это выглядит хорошо, а некоторые считают, что это некрасиво, но я думаю, что это нормально. Позвольте познакомить вас с ключевыми моментами.Самым важным моментом является то, как мы можем контролировать ширину и высоту пузырьков, чтобы текст автоматически переносился, когда он достигает определенной длины 🤔? Появляется главный герой-ConstrainedBox
,ConstrainedBox
какойWidget
Шерстяная ткань? Как подсказывает названиеConstrainedBox
могу дать тебеWidget
Добавьте некоторые ограничения, это здорово, мы хотим ограничить максимальную ширину пузыря, но мы не ограничиваем высоту, правильно. Вот и родился наш текстовый пузырь 🚀
Widget textBubble(String content,Color colors,Color txtColor,double bottomleft,double bottomRight){
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 500.w
),
child: Container(
margin: EdgeInsets.only(top: 10.h),
padding: EdgeInsets.symmetric(
horizontal: 34.w,
vertical: 18.h,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(bottomleft), bottomRight: Radius.circular(bottomRight),topRight: Radius.circular(0.0),topLeft: Radius.circular(5.0)),
color: colors,
),
child: Text(content,style: TextStyle(color:txtColor,fontSize: 28.sp),),
),
);
}
Игнорируйте некоторые бизнес-ценности 📈, глядя на эту структуру, мы фактически использовалиConstrainedBox
Указана максимальная ширина и определены радианы четырех углов.Эти два места являются ключом к реализации 👀.
Подробности - речевой пузырь 🔊
Голос – неотъемлемая часть общения в чате. Некоторым пользователям очень нравится отправлять голосовые сообщения. Если вы просто хотите сделать всплывающую подсказку, это очень просто. Просто замените текст в текстовой подсказке выше изображением голоса, но вы обнаружите, что пользовательский опыт очень плохой, и вы не хотите использовать его сами 😑. Я лично не могу принять такой продукт, поэтому вы можете работать со мной над улучшением наших пузырей:
играть в анимацию
Поскольку речь идет о пользовательском опыте, воспроизведение анимации имеет важное значение. Пользователь нажимает на речевой пузырь и просто воспроизводит звук. Пользователь не знает, какой пузырь нажат, и пользователь чувствует себя очень плохо 🤨. Эта анимация часто ставила в тупик многих студентов. На самом деле это не так уж и сложно, у нас есть художники! Пожалуйста, обратитесь к WeChat или изображению готового продукта ниже и подумайте, нужно ли нам рисовать анимацию самостоятельно? На самом деле в этом нет нужды, наши колонки на самом деле просто постоянная замена трех картинок 💡.
Такая голосовая картинка заставляет двигаться ⛓, нам на самом деле нужно только ~ картинка белой точки, картинка белой точки и дуги
Смотрите, три картинки по очереди – это анимация! Схема реализации - наш таймер ⏰, используйте таймер для переключения картинок каждые полсекунды, эффект теста очень приятный 👍
_timer = new Timer.periodic(new Duration(milliseconds: 500), (timer) {
if(i == 3)
{
i = 1;
}
else
{
i ++;
}
setState(() {
if(i == 1)
{
_voiceImage = "assets/images/voice_point_right.png";
}
if(i == 2)
{
_voiceImage = "assets/images/voice_step_left.png";
}
if(i == 3)
{
_voiceImage = "assets/images/voice_left.png";
}
});
});
длина пузырька
На самом деле, во взаимодействии с пользователем есть очень важная маленькая деталь, а именно длина речевого пузыря📐, мы можем сами написать небольшой алгоритм, чтобы позволить разной продолжительности речи контролировать длину облачка, это небольшое изменение будет отличным Чтобы улучшить красоту страницы, позвольте мне дать вам одну идею. Ширина пузырьков, которыми вы хотите управлять, должна контролироваться самой длинной и самой короткой длиной. Голос 1s и голос 100 могут легко сделать вашу длину слишком длинной🕹
double width = 0.0;
width = timeLength * 2 * 20.w;
if(width < 150.w)
{
width = 150.w;
}
if(width > 400.w)
{
width = 400.w;
}
Конечный эффект нашего речевого пузыря выглядит так, плюс анимация щелчка, мне это очень нравится:
исходный код
Widget voiceBubble(int timeLength,Color colors,double bottomleft,double bottomRight, String voiceImage){
double width = 0.0;
width = timeLength * 2 * 10.w;
if(width < 150.w)
{
width = 150.w;
}
if(width > 400.w)
{
width = 400.w;
}
return Container(
margin: EdgeInsets.only(top: 10.h),
width: width,
padding: EdgeInsets.symmetric(
horizontal: 34.w,
vertical: 18.h,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(bottomleft), bottomRight: Radius.circular(bottomRight),topRight: Radius.circular(0.0),topLeft: Radius.circular(5.0)),
color: colors,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text((timeLength).toString() + "''",style: TextStyle(color: Colors.white),),
SizedBox(width: 20.w,),
Image.asset(voiceImage,color: Colors.white,width: 24.w),
],
),
);
}
Честный и честный - пузыри с картинками 🖼
Пузыри с картинками также являются неотъемлемой частью нашего ежедневного чата. Как сделать так, чтобы картинки показывались пользователям? Далее я покажу вам, как их сделатьfantastic
мыльные пузыри! Пузыри с картинками, вы также можете тщательно продумать, на какие моменты вам нужно обратить внимание.Как пользователь, вы получаете графическое сообщение, что вас больше всего волнует? что это такое?
Размер
Откройте свой фотоальбом и пролистайте несколько фотографий.Нетрудно обнаружить, что помимо фотографий, сделанных камерой вашего мобильного телефона, вы также скачаете их со сторонних платформ и обрежете сами. Тогда ваши пузыри не могут быть фиксированными по длине и ширине и должны иметь сильную динамику. Для создания этого пункта я и команда художников обращаемся к некоторым планам WeChat 🍭. Мы указали максимальную ширину и максимальную высоту для картинки, в пределах этого диапазона мы будем отображать ее в соответствии с размером самой картинки, но если она превышает эту длину и ширину, мы будем выполнять операции, аналогичные сжатию и обрезке ✂️ сделать картинку как можно более аккуратной. Портретно-ориентированное изображение по-прежнему сохраняет вертикальную композицию, а горизонтальное изображение аналогично.
Отображение изображений
Картинка обязательно должна быть дополнительно отображена пользователю, чтобы пользователь мог просмотреть большую картинку 🚠, верно, как посмотреть большую картинку, обратитесь к большинству маркетовapp
практика - новая страница! В то же время, чтобы максимизировать пользовательский опыт, нам также нужно прыгать по интерфейсу и добавлять анимацию прыжка, котораяFlutter
При условии, очень подходит для нашего бизнес-сценарияHero
Анимация, для отображения больших картинок 🎱.
увеличение изображения
Теперь, когда мы добрались до отображения изображений, мы должны добиваться более экстремального пользовательского опыта, и мы также позволяем ему масштабировать! Функцию можно реализовать напрямую через плагин, ознакомьтесь с нимAPI
Вот и все, но обратите внимание на ограничения коэффициента масштабирования, я буду ссылаться на него напрямую 🍎Apple
Ограничение масштабирования, больше ничего,Apple
беспрецедентный пользовательский опыт.
окончательный эффект:
Исходный код:
Widget imageBubble(BuildContext context,String url){
final String imgUrl = "";
return GestureDetector(
onTap: (){
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => HeroPhotoViewRouteWrapper(
url: url,
minScale: 0.1,
maxScale: 1.5,
imageProvider: NetworkImage(
url
)
),
),
);
},
child: Hero(
tag: "${url}",
child: Container(
margin: EdgeInsets.only(top: 10.h),
padding: EdgeInsets.symmetric(
vertical: 10.h,
),
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 300.h,maxWidth: 400.w),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Theme.of(context).brightness == Brightness.light ? Color.fromRGBO(237, 237, 237, 1) : Color.fromRGBO(17, 17, 17, 1),
),
child: ClipRRect(![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e4fa8e3341974cf688fb2238394bda77~tplv-k3u1fbpfcp-watermark.image)
borderRadius: BorderRadius.circular(10.0),
child: CachedNetworkImage(
imageUrl: url,
placeholder: (context, url) => SizedBox(
width: 100.w,
height: 100.h,
child: Center(
child: LoadingIndicator(indicatorType: Indicator.ballClipRotateMultiple, color: Theme.of(context).brightness == Brightness.light ? Color.fromRGBO(61, 93, 237, 1) : Color.fromRGBO(54, 83, 193, 1),),
),
),
errorWidget: (context, url, error) => new Icon(Icons.error),
),
),
),
),
),
),
);
}
конец
Выше приведены некоторые из моих пузырей, которые я представил вам🧽. Если вам интересно, в будущем я поделюсь с вами более красивыми и сложными пузырями. В течение всего процесса разработки вы должны обращать внимание на пользовательский опыт и думать с с точки зрения пользователя🔫 Некоторые очень простые функции также могут значительно улучшить взаимодействие с пользователем.
🐳 Добро пожаловать в мой 🔗github