1

Now I am using a Container to placeholder an image before render. But now I face a problem to make the CircularProgressIndicator center vertically and herizonally. This is what I am doing now:

  Widget loadingWidget(){
    return Container(
      height: 400.0,
      width: 120.0,
      child: Center(
          child: ConstrainedBox(
            constraints: BoxConstraints(
              maxHeight: 50.0, maxWidth: 50.0
            ),
              child:CircularProgressIndicator()
          )
      ),
    );
  }

in a fixed size container I am put a CircularProgressIndicator, now the CircularProgressIndicator is vertically center, but herizonally not be center. I searching from internet and found all ways to do is very complex. is there any simple way to do that,sorry I am a newbie about flutter. I tried this way follow the answer:

  Widget loadingWidget(){
    return Container(
      height: 400.0,
      width: 120.0,
      child: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children:<Widget> [
              SizedBox(
                child: CircularProgressIndicator(),
                height: 50.0,
                width: 50.0,
              )
            ],
          )
      ),
    );
  }

but the CircularProgressIndicator in the left top corner, why did not in the center of container? This is my full code of the component:

import 'package:cruise/src/common/article_action.dart';
import 'package:cruise/src/common/helpers.dart';
import 'package:cruise/src/common/net/rest/http_result.dart';
import 'package:cruise/src/common/repo.dart';
import 'package:cruise/src/common/utils/common_utils.dart';
import 'package:cruise/src/models/Channel.dart';
import 'package:cruise/src/models/Item.dart';
import 'package:cruise/src/models/api/fav_status.dart';
import 'package:cruise/src/models/api/upvote_status.dart';
import 'package:cruise/src/page/channel/channelpg_component/page.dart';
import 'package:cruise/src/page/home/components/articledetail_component/action.dart';
import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html/style.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:html/parser.dart' as htmlparser;
import 'package:html/dom.dart' as dom;
import 'state.dart';

Widget buildView(ArticleDetailState state, Dispatch dispatch, ViewService viewService) {
  Item item = state.article;
  BuildContext context = viewService.context;
  Offset? _initialSwipeOffset;
  Offset? _finalSwipeOffset;

  void _onHorizontalDragStart(DragStartDetails details) {
    _initialSwipeOffset = details.globalPosition;
  }

  void _onHorizontalDragUpdate(DragUpdateDetails details) {
    _finalSwipeOffset = details.globalPosition;
  }

  void _onHorizontalDragEnd(DragEndDetails details) {
    if (_initialSwipeOffset != null) {
      final offsetDifference = _initialSwipeOffset!.dx - _finalSwipeOffset!.dx;
      if (offsetDifference < 0) {

        Navigator.pop(context);
      }
    }
  }

  void touchUpvote(String action, UpvoteStatus upvoteStatus) async {
    HttpResult result = (await ArticleAction.upvote(articleId: item.id.toString(), action: action))!;

    if (result.result == Result.error) {
      Fluttertoast.showToast(
          msg: "点赞失败",
          toastLength: Toast.LENGTH_SHORT,
          gravity: ToastGravity.CENTER,
          timeInSecForIosWeb: 1,
          backgroundColor: Colors.red,
          textColor: Colors.white,
          fontSize: 16.0);
    } else {
      if (upvoteStatus.statusCode == "upvote") {
        dispatch(ArticleDetailActionCreator.onVote(UpvoteStatus.UPVOTE));
      }
      if (upvoteStatus.statusCode == "unupvote" && item.upvoteCount > 0) {
        dispatch(ArticleDetailActionCreator.onVote(UpvoteStatus.UNUPVOTE));
      }
     Fluttertoast.showToast(
          msg: upvoteStatus.statusCode == "upvote" ? "点赞成功" : "取消点赞成功",
          toastLength: Toast.LENGTH_SHORT,
          gravity: ToastGravity.CENTER,
          timeInSecForIosWeb: 1,
          backgroundColor: Colors.red,
          textColor: Colors.white,
          fontSize: 16.0);
    }
  }

  void touchFav(String action, FavStatus favStatus) async {
    HttpResult result = (await ArticleAction.fav(articleId: item.id.toString(), action: action))!;

    if (result.result == Result.error) {
      Fluttertoast.showToast(
          msg: favStatus.statusCode == "fav" ? "添加收藏失败" : "取消收藏失败",
          toastLength: Toast.LENGTH_SHORT,
          gravity: ToastGravity.CENTER,
          timeInSecForIosWeb: 1,
          backgroundColor: Colors.red,
          textColor: Colors.white,
          fontSize: 16.0);
    } else {
      if (favStatus.statusCode == "fav") {
        dispatch(ArticleDetailActionCreator.onFav(FavStatus.FAV));
      }
      if (favStatus.statusCode == "unfav" && item.favCount > 0) {
        dispatch(ArticleDetailActionCreator.onFav(FavStatus.UNFAV));
      }
      Fluttertoast.showToast(
          msg: favStatus.statusCode == "fav" ? "添加收藏成功" : "取消收藏成功",
          toastLength: Toast.LENGTH_SHORT,
          gravity: ToastGravity.CENTER,
          timeInSecForIosWeb: 1,
          backgroundColor: Colors.red,
          textColor: Colors.white,
          fontSize: 16.0);
    }
  }

  void navToChannelDetail() async {
    Channel channel = (await Repo.fetchChannelItem(int.parse(item.subSourceId)))!;
    var data = {'name': "originalstories", "channel": channel};
    Widget page = ChannelpgPage().buildPage(data);
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => page),
    );
  }

  /// 是否是编辑选择频道链接显示不同的颜色
  TextStyle getDomainStyle(Item article){
    if(article.editorPick == 1) {
      return new TextStyle(
          color: Color(0xFFFFA826),
          fontSize: 15
      );
    }else{
      return new TextStyle(
          color: Color(0xFF0A0A0A),
          fontSize: 15
      );
    }
  }

  ImageSourceMatcher base64UriMatcher() => (attributes, element) =>
  attributes["src"] != null &&
      attributes["src"]!.startsWith("data:image") &&
      attributes["src"]!.contains("base64,");

  Widget loadingWidget(){
    return Container(
      height: 400.0,
      width: 120.0,
      child: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children:<Widget> [
              SizedBox(
                child: CircularProgressIndicator(),
                height: 50.0,
                width: 50.0,
              )
            ],
          )
      ),
    );
  }


  final Map<ImageSourceMatcher, ImageRender> defaultImageRenders = {
    base64UriMatcher(): base64ImageRender(),
    assetUriMatcher(): assetImageRender(),
    networkSourceMatcher(extension: "svg"): svgNetworkImageRender(),
    networkSourceMatcher(): networkImageRender(
        height: 400,
        loadingWidget: loadingWidget
    ),
  };

  SingleChildScrollView buildListView(Item item, BuildContext context) {
    return SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            InkWell(
              onTap: () => CommonUtils.launchUrl(item.link),
              child: Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: Container(
                  child: Text(
                    item.title,
                    style: Theme.of(context).textTheme.headline5!.copyWith(
                          fontWeight: FontWeight.w600,
                        ),
                  ),
                ),
              ),
            ),
            if (item.domain != "")
              Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: InkWell(
                    onTap: () async {
                      navToChannelDetail();
                    },
                    child: Text(
                      item.domain,
                      style: getDomainStyle(item),
                    )),
              ),
            InkWell(
              onTap: () {},
              child: RichText(
                text: TextSpan(
                  children: <TextSpan>[
                    TextSpan(
                      text: item.author,
                      style: Theme.of(context).textTheme.caption,
                    ),
                    TextSpan(
                      text: " ${String.fromCharCode(8226)} ",
                      style: Theme.of(context).textTheme.caption,
                    ),
                    TextSpan(
                      text: item.ago,
                      style: Theme.of(context).textTheme.caption,
                    ),
                  ],
                ),
              ),
            ),
            if (item.content != "")
              Html(
                data: item.content,
                style: {
                  "body": Style(
                    fontSize: FontSize(19.0),
                  ),
                },
                  customImageRenders: defaultImageRenders,
                onLinkTap: (String? url, RenderContext context, Map<String, String> attributes,  dom.Element? element){
                  CommonUtils.launchUrl(url);
              }),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.only(right: 16.0),
                      child: Row(
                        children: [
                          if (item.isFav == 1)
                            IconButton(
                              icon: Icon(Icons.bookmark, color: Theme.of(context).primaryColor),
                              onPressed: () => touchFav("unfav", FavStatus.UNFAV),
                            ),
                          if (item.isFav != 1)
                            IconButton(
                              icon: Icon(Icons.bookmark),
                              onPressed: () => touchFav("fav", FavStatus.FAV),
                            ),
                          Padding(
                            padding: const EdgeInsets.only(left: 0.0),
                            child: Text(
                              "${item.favCount}",
                              textAlign: TextAlign.center,
                              style: Theme.of(context).textTheme.caption!.copyWith(
                                    color: Theme.of(context).primaryColor,
                                  ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(bottom: 0.0),
                      child: Row(
                        children: [
                          if (item.isUpvote == 1)
                            IconButton(
                              icon: Icon(Icons.thumb_up, color: Theme.of(context).primaryColor),
                              onPressed: () => touchUpvote("unupvote", UpvoteStatus.UNUPVOTE),
                            ),
                          if (item.isUpvote != 1)
                            IconButton(
                              icon: Icon(Icons.thumb_up),
                              onPressed: () => touchUpvote("upvote", UpvoteStatus.UPVOTE),
                            ),
                          Padding(
                            padding: const EdgeInsets.only(left: 8.0),
                            child: Text(
                              "${item.upvoteCount}",
                              textAlign: TextAlign.center,
                              style: Theme.of(context).textTheme.caption!.copyWith(
                                    color: Theme.of(context).primaryColor,
                                  ),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
                IconButton(
                  icon: Icon(
                    Feather.share_2,
                  ),
                  onPressed: () => handleShare(id: item.id, title: item.title, postUrl: item.link),
                ),
              ],
            ),
          ],
        ));
  }

  return GestureDetector(
      onHorizontalDragStart: _onHorizontalDragStart,
      onHorizontalDragUpdate: _onHorizontalDragUpdate,
      onHorizontalDragEnd: _onHorizontalDragEnd,
      child: Container(
        constraints: BoxConstraints(
          minHeight: MediaQuery.of(context).size.height * 0.9,
        ),
        color: Theme.of(context).scaffoldBackgroundColor,
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: buildListView(item, context),
        ),
      ));
}

I am using flutter html to render a html text, before render I want a component to takeplace the image postion, this question may explain more detail.

Dolphin
  • 29,069
  • 61
  • 260
  • 539
  • Does this answer your question? [How to set size to CircularProgressIndicator?](https://stackoverflow.com/questions/51901379/how-to-set-size-to-circularprogressindicator) – enzo May 22 '21 at 02:19
  • Can you share a screenshot of how it looks and the code where `loadingWidget` is being used? – JediBurrell May 22 '21 at 02:20
  • I tried what you said but it seems not work.@enzo – Dolphin May 22 '21 at 02:26
  • the full code may be a little longer, I have pasted it and help to understand, the code also could see in github: https://github.com/jiangxiaoqiang/cruise-open.@JediBurrell – Dolphin May 22 '21 at 02:27
  • it´s really hard to help you without all the code or a picture about what are you trying to do, but maybe you could center your CircularProgressIndicator using the widget Positioned – matt020java May 22 '21 at 03:06

1 Answers1

1

The CircularProgressIndicator in the left top corner because the Container is set up right there by default when you call it, so the CircularProgressIndicator is in the center of the Container which is now on the top left.

So everything you need to do is just wrap the Container which is containing the CircularProgressIndicator with the Center() Widget

  • herizonal centered but vertical not centered. This is my code: `Widget loadingWidget(){ return Center( child:Container( height: 400.0, width: 120.0, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( child: CircularProgressIndicator(), height: 50.0, width: 50.0, ) ], ) ), ); }` – Dolphin May 22 '21 at 05:12
  • 1
    so how about add this line right below the crossAxisAlignment : mainAxisAlignment: MainAxisAlignment.center – Trần Trung Hiếu May 22 '21 at 05:18