Search code examples
flutteruser-interfaceflexboxfrontendspacing

Flutter: image messing up Flexible/Expanded sizes


Im trying to make something in flutter that looks like a twitter clone. The Tweet, called a wave, can be seen in the following:

import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:timeago/timeago.dart' as timeago;
import '../../../../../../blocs/vote/vote_bloc.dart' as vote;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:like_button/like_button.dart';

import '../../../../../../blocs/profile/profile_bloc.dart';
import '../../../../../../blocs/wave_liking/wave_liking_bloc.dart';
import '../../../../../../models/user_model.dart';
import '../../../../../../models/wave_model.dart';
import '../../../../../../widgets/text_splitter.dart';
import '../../generic_view.dart';
import '../../photo_view/photo_view.dart';

class WaveTile extends StatelessWidget {
  const WaveTile({
    Key? key,
    required this.poster,
    required this.wave,
    this.extendBelow = false,
  }) : super(key: key);

  final User poster;
  final Wave wave;
  final bool extendBelow;

  @override
  Widget build(BuildContext context) {
    User user =
        (BlocProvider.of<ProfileBloc>(context).state as ProfileLoaded).user;
    return IntrinsicHeight(
      child: Row(
        children: [
          waveColumn(context),
          Expanded(
              flex: 5,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  waveHeader(poster, wave, context, user),
                  waveText(wave, context),
                  if (wave.imageUrl != null) waveImage(wave, context),
                  waveButtons(wave),
                ],
              ))
        ],
      ),
    );
  }

  Expanded waveColumn(BuildContext context) {
    return Expanded(
      child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            SizedBox(
              width: 40,
              height: 40,
              child: InkWell(
                child: Hero(
                  tag: 'wave${wave.id}',
                  child: CircleAvatar(
                      backgroundImage:
                          CachedNetworkImageProvider(poster.imageUrls[0])),
                ),
                onTap: () {
                  BlocProvider.of<vote.VoteBloc>(context)
                      .add(vote.LoadUserEvent(user: poster));
                  Navigator.pushNamed(
                    context,
                    '/votes',
                  );
                },
              ),
            ),

            if (extendBelow)
              Expanded(
                child: VerticalDivider(
                  color: Color.fromARGB(255, 207, 207, 207),
                  thickness: 2,
                  width: 10,
                ),
              ),

            //add a grey line
          ]),
    );
  }
}

Widget waveHeader(User poster, Wave wave, BuildContext context, User user) {
  return Row(
    children: [
      Container(
        margin: const EdgeInsets.only(right: 5.0),
        child: Text(poster.name,
            style: Theme.of(context)
                .textTheme
                .headline4!
                .copyWith(fontWeight: FontWeight.bold)),
      ),
      Text(
        '${poster.handle} · ${timeago.format(wave.createdAt)}',
        style: Theme.of(context).textTheme.subtitle1,
      ),
      Spacer(),
      WaveTilePopup(poster: poster, wave: wave, user: user),
    ],
  );
}

Widget waveText(Wave wave, BuildContext context) {
  return Flexible(
      child: TextSplitter(
    wave.message,
    context,
    Theme.of(context).textTheme.subtitle2!,
  ));
}

Widget waveImage(Wave wave, BuildContext context) {
  return Flexible(
    child: ClipRRect(
      borderRadius: BorderRadius.circular(10),
      child: InkWell(
        child: CachedNetworkImage(
          imageUrl: wave.imageUrl!,
          fit: BoxFit.fill,
        ),
        onTap: () {
          Navigator.pushNamed(
            context,
            MyPhotoView.routeName,
            arguments: {
              'imageUrls': [wave.imageUrl!],
              'index': 0
            },
          );
        },
      ),
    ),
  );
}

Widget waveButtons(Wave wave) {
  return BlocBuilder<ProfileBloc, ProfileState>(
    builder: (context, profileState) {
      if (profileState is ProfileLoading) {
        return Container();
      }
      if (profileState is ProfileLoaded) {
        User user = profileState.user;
        return Container(
          margin: const EdgeInsets.only(top: 10.0, right: 20.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Row(
                children: [
                  //font awesome comment icon
                  Icon(
                    FontAwesomeIcons.comment,
                    size: 14.0,
                    color: Colors.grey,
                  ),
                  SizedBox(width: 5),
                  Text(wave.comments.toString()),
                ],
              ),
              BlocBuilder<WaveLikingBloc, WaveLikingState>(
                builder: (context, waveLikingState) {
                  //set waveLikingState to be WaveLikingLoaded
                  waveLikingState = waveLikingState as WaveLikingLoaded;
                  bool inShortTermLikes =
                      waveLikingState.shortTermLikes.contains(wave.id);
                  bool inShortTermDislikes =
                      waveLikingState.shortTermDislikes.contains(wave.id);
                  bool inLikes = waveLikingState.likes.contains(wave.id);
                  bool inDislikes = waveLikingState.dislikes.contains(wave.id);
                  bool likedBy = wave.likedBy.contains(user.id);
                  bool isLiked = ((likedBy || inLikes || inShortTermLikes) &&
                      !(inDislikes || inShortTermDislikes));
                  int likeCount = (inLikes || inShortTermLikes)
                      ? wave.likes + 1
                      : (inDislikes || inShortTermDislikes)
                          ? wave.likes - 1
                          : wave.likes;

                  return LikeButton(
                    isLiked: isLiked,
                    size: 30,
                    circleColor: CircleColor(
                        start: Colors.red[300]!, end: Colors.red[900]!),
                    bubblesColor: BubblesColor(
                      dotPrimaryColor: Colors.red[300]!,
                      dotSecondaryColor: Colors.red[900]!,
                    ),
                    likeBuilder: (bool isLiked) {
                      return Icon(
                        Icons.favorite,
                        color: isLiked ? Colors.red[900] : Colors.grey,
                        size: 20,
                      );
                    },
                    likeCount: likeCount,
                    countBuilder: (int? count, bool isLiked, String text) {
                      var color = isLiked ? Colors.red[900] : Colors.grey;
                      Widget result;

                      result = Text(
                        text,
                        style: TextStyle(color: color),
                      );
                      return result;
                    },
                    onTap: (bool isLiked) async {
                      (isLiked)
                          ? BlocProvider.of<WaveLikingBloc>(context).add(
                              DislikeWave(waveId: wave.id, userId: user.id!))
                          : BlocProvider.of<WaveLikingBloc>(context)
                              .add(LikeWave(waveId: wave.id, userId: user.id!));

                      return !isLiked;
                    },
                  );
                },
              ),
            ],
          ),
        );
      }
      return Container();
    },
  );
}



When creating a wave with just text, it will end up looking like this: enter image description here

This is the ideal situation right now. However, when an image is added, it looks like this:

enter image description here

Going through widget inspector does not seem to help me much, and the only way I can change the size of the wave is by deleting the image, leading me to believe the image is causing some weird interaction with the Flexible/Expanded widgets near it. Anyone got any ideas?

Thanks!


Solution

  • As you have 2 Flexible in a column , it will take up all the space. You can try removing Flexible from Text.