#flutter #flutter-layout #flutter-web
Вопрос:
У меня есть макет карты, который выглядит следующим образом:
Код для этого он выглядит следующим образом:
Card(
color: tap ? Colors.green : Colors.white,
margin: EdgeInsets.symmetric(horizontal: 5.0, vertical: 3.0),
child: Container(
child: Row(
children: [
**Container(
height: !widget.menuItem.image.endsWith('/')? 70.0 : 0.0,
width: !widget.menuItem.image.endsWith('/')? 70.0 : 0.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
image: DecorationImage(
image: NetworkImage(widget.menuItem.image),
fit: BoxFit.cover
),
),**
),
SizedBox(
width: 8.0,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Text(
howManyThere() > 0 ? "${howManyThere()} x " : '',
style: addBTNHighlight,
),
Expanded(
child: Text(
widget.menuItem.item_name,
overflow: TextOverflow.ellipsis,
style: tap ? TitleWhite18Bold : Title18bold,
),
),
],
),
Container(
child: Text(
widget.menuItem.description,
//overflow: TextOverflow.ellipsis,
style: tap ? SubTitleWhite13 : SubTitle13,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Text(
"£" num.parse(widget.menuItem.price).toStringAsFixed(2),
style: tap ? priceHighlightSelected : priceHighlight,
),
),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 6.0),
decoration: BoxDecoration(),
child: Text("ADD", style: tap ? priceHighlightWhite : addBTNHighlight)),
],
),
],
),
),
)
Как вы можете видеть, я почти на месте с желаемым макетом, но с одной небольшой проблемой, которую можно увидеть в первом и последнем пункте. Из-за заданной ширины и высоты контейнера изображения он оставляет зазор сверху и снизу.
Я бы хотел, чтобы ширина оставалась прежней, но высота была гибкой и регулировалась в соответствии с высотой самой карты. Возможно ли это?
Когда я удаляю атрибут высоты контейнера с изображением, я получаю пустое пространство изображения
ОБНОВЛЕНИЕ: Я также попробовал LayoutBuilder, но безрезультатно, он выдает исключение «Неправильное использование ParentWidget». Код, который я использовал, выглядит следующим образом:
Row(
children: [
widget.menuItem.image.endsWith('/')
? Container()
: **LayoutBuilder(
builder: (context, constraints){
return Container(
width: 70.0,
height: constraints.minHeight,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
image: DecorationImage(
image: NetworkImage(widget.menuItem.image),
fit: BoxFit.cover
),
),
);
}**
),
Комментарии:
1. Ваш код невозможно воспроизвести. Вы можете попробовать удалить
height:70
и обернуть свойRow
IntrinsicHeight
виджет внутрь.2. используйте BoxFit.fitHeight или заполните
Ответ №1:
Попробуйте это :
Column(
children: [
Expanded(
child: Container(
width: !widget.menuItem.image.endsWith('/')? 70.0 : 0.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
image: DecorationImage(
image: NetworkImage(widget.menuItem.image),
fit: BoxFit.cover
),
),
),
),
],
),
Комментарии:
1. Таким образом, я получаю всевозможные ошибки рендеринга.
Ответ №2:
Проблема здесь в тексте описания, который переполняет желаемую максимальную высоту. Вы можете попытаться ограничить свое Container
свойство с помощью a height: 70.0
или добавить его в свой Text
виджет maxLines: 1
.
Комментарии:
1. Спасибо, но это не проблема, это особенность. Описание не должно быть урезано до одной строки.
2. итак, вы хотите изменить размер фотографии до максимальной высоты ?
3. Да, это желание
4. чем если вы позволите
height
изображениюContainer
помочь вам. С другой стороны, постарайтесь придатьdouble.infinity
ценность5. Хорошо.. хорошо, попробуйте использовать
LayoutBuilder
: api.flutter.dev/flutter/widgets/LayoutBuilder-class.html и пользоватьсяmaxHeight
имуществом
Ответ №3:
LayoutBuilder
только дайте вам ограничения, которые родитель передает ребенку, что-то вроде 100 < width < 200, 300 < height < infinity
. На данный момент высота всех текстов справа еще не определена, поэтому определить высоту основания изображения на этом основании невозможно.
Один из способов сделать это-назначить key
каждому элементу списка, получить высоту элемента после того, как все будет готово, перестроить с фиксированной высотой. Это станет двухпроходным процессом и будет менее эффективным.
Официальное решение этой проблемы заключается IntrinsicHeight
в том , что концептуально они делают то же самое, но более оптимизированным способом.
Вот минимальный пример:
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: App(),
),
);
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
// This is where magic happened
child: IntrinsicHeight(
child: Row(
children: [
Container(
width: 100,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://cataas.com/cat'),
fit: BoxFit.cover,
),
),
),
Expanded(
child: Text(
// just put some random text with dynamic height
'Textn' * (Random().nextInt(4) 4),
),
),
],
),
),
);
},
),
);
}
}
Комментарии:
1. @Damandroid «Извините, что это не сработало» вам не поможет.
2. Извините, но я отказался от этого после стольких дней, и изменение стратегии показалось мне лучшим вариантом на данный момент. Теперь я изменил макет.
Ответ №4:
Удалите ограничения по высоте, затем
попробуйте заменить fit: BoxFit.cover
на BoxFit.fitHeight
или BoxFit.fill
.
Ответ №5:
Для того, чтобы заполнить изображение высотой карты, вы можете указать требуемую высоту контейнера и обернуть Image
виджет в AspectRatio
виджет с ratio
1. Это всегда поможет виджету изображения заполнить высоту родительской карты. Взгляните на приведенный ниже код.
Родительский виджет
Container(
margin: EdgeInsets.only(bottom: 12),
height: 100,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 1,
child: _pictureWidget(widget.menuItem.image),
),
/// Replace `Container` with the needed widget
Expanded(child: Container()),
],
),
)
_pictureWidget
Widget _picture(String url) {
return _pictureWidget(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5.0), topRight: Radius.circular(5.0)),
child: Image.network(
url != null ? url : "",
fit: BoxFit.cover,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,
),
);
},
),
);
}