#flutter #button #stack #overlap
Вопрос:
У меня есть кнопка, для которой требуется, чтобы значок располагался немного за пределами прямоугольника.
Я могу сделать это нормально со стеком, однако граница кнопки перекрывает значок, как вы можете видеть здесь:
вот мой код:
OutlinedButton(
style: scansButtonStyle,
onPressed: () {}, // TODO: add later
child: Stack(clipBehavior: Clip.none, children: [
Padding(
padding: const EdgeInsets.only(left: 50.0),
child: Text('CONNECT'),
),
Positioned(
bottom: 0,
left: -20,
child: CircleAvatar(
radius: 30,
backgroundColor: Colors.black,
child: CircleAvatar(
radius: 27,
backgroundColor: Colors.white,
child: Icon(
Icons.bluetooth_connected,
color: Colors.black,
size: 48,
),
),
),
),
]),
),
и укладка:
final ButtonStyle scansButtonStyle = OutlinedButton.styleFrom(
alignment: Alignment.centerLeft,
primary: Colors.black,
backgroundColor: Color(0xfffcd722),
minimumSize: Size(242, 48),
padding: EdgeInsets.fromLTRB(20, 3, 20, 3),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.zero,
bottomRight: Radius.circular(16),
bottomLeft: Radius.zero),
),
textStyle: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600,
fontSize: 34,
fontFamily: 'HP',
),
side: BorderSide(
color: Colors.black,
width: 3.0,
style: BorderStyle.solid,
));
Комментарии:
1. можете поделиться своей ожидаемой картинкой?
2. Я отредактировал его, чтобы включить ожидаемое изображение
Ответ №1:
Я немного исправил код.
Основными изменениями являются:
- Поместите описанную кнопку в стопку
- Изменил CircleAvatar на простой контейнер с украшением (вам действительно нужен CircleAvatar для этого? Будете ли вы каким-либо образом анимировать иконку? Если нет, то простой контейнер может быть лучше)
- Добавьте IgnorePointer к значку, чтобы он игнорировал событие нажатия и передавал его ниже самой кнопке (это для эффекта пульсации даже при нажатии на значок).
- Оберните значок виджетом FittedBox и добавьте дополнения во внешний контейнер. Это позволит нашей иконке динамически изменять свой размер в зависимости от размера внешнего круга.
- Добавлены некоторые параметры в текстовый виджет, чтобы он не нарушал дизайн, если текст длиннее ширины. Вы можете проверить это с помощью текста(«ПОДКЛЮЧИТЬСЯ» * 10)
Stack(
clipBehavior: Clip.none,
children: [
OutlinedButton(
onPressed: () {},
style: scansButtonStyle,
child: Padding(
padding: const EdgeInsets.only(left: 50.0),
child: Text(
'CONNECT',
maxLines: 1,
overflow: TextOverflow.ellipsis,
textScaleFactor: 1.0, // We do not want OS preferences (text scale option) to break our button's design
),
),
),
Positioned(
bottom: 0,
child: IgnorePointer(
//ignore touch events, so that the Outlined button triggers touch animation when pressed on the icon
child: SizedBox(
width: 60.0,
child: AspectRatio(
aspectRatio: 1.0,
child: Container(
padding: EdgeInsets.all(6.0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.black,
width: 3.0,
),
shape: BoxShape.circle,
),
child: FittedBox(
child: Icon(
Icons.bluetooth_connected,
color: Colors.black,
),
),
),
),
),
),
),
],
)
Код может потребовать некоторых дополнительных корректировок, но вы поймете идею.
Пожалуйста, также обратите внимание, что верхний вырез значка не занимает места (из-за Clip.none и его положения в стеке). Вы можете проверить это, завернув кнопку в цветной контейнер.
Если вам не нравится идея aspectRatio внутри SizedBox — измените его обратно на ширину/высоту в контейнере.
Комментарии:
1. Потрясающе — просто крошечная настройка положения значка, и он выглядит И делает именно то, что я хочу — я могу нажать кнопку, независимо от того, нажимаю ли я на значок или на кнопку (по крайней мере, перекрывающуюся часть — это все, что мне нужно. Спасибо!
Ответ №2:
Я добился желаемого визуального эффекта, поместив кнопку и значок в стопку (вместо стопки внутри кнопки).
Недостатком здесь является то, что если я сейчас нажму на значок, он больше не будет вызывать кнопку.
Так что этот ответ не совсем правильный….
Stack(
clipBehavior: Clip.none,
children: [
OutlinedButton(
style: scansButtonStyle,
onPressed: () {}, // TODO: add later
child: Padding(
padding: const EdgeInsets.only(left: 50.0),
child: Text('CONNECT'),
),
),
Positioned(
bottom: 6,
left: 0,
child: CircleAvatar(
radius: 30,
backgroundColor: Colors.black,
child: CircleAvatar(
radius: 27,
backgroundColor: Colors.white,
child: Icon(
Icons.bluetooth_connected,
color: Colors.black,
size: 48,
),
),
),
),
]),
Комментарии:
1. Я думаю, что один из способов обойти это — сделать значок также кнопкой, которая ссылается на ту же функцию-не уверен, что это самое элегантное решение? Честно говоря, значок в вопросе запускается только частью, перекрывающей кнопку, но она была достаточно близка, чтобы ее было недостаточно заметно, чтобы вызвать проблему, в то время как это решение создает отверстие в кнопке, где оно не может сработать 🙁