HomeiOS DevelopmentFlutter UI not matching design: top-right badge not correctly connected to card...

Flutter UI not matching design: top-right badge not correctly connected to card border


Here’s what I’m making an attempt to do:

Flutter UI not matching design: top-right badge not correctly connected to card border

The screenshot is taken from a iPhone 15 Professional:

Image

I’m making an attempt to construct a pricing UI in Flutter, however the structure isn’t matching the design—particularly the top-right badge (“Starter Plan”).

class _PricingScreenState extends State<PricingScreen> {
  closing PageController _controller = PageController();
  int currentPage = 0;

  closing Record<PlanModel> plans = [
    PlanModel(
      title: "Basic Plan",
      price: "$13 USD",
      subtitle: "per user/month",
      tag: "Starter Plan",
      buttonText: "Get Basic - $13/month",
      features: [
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
      ],
      isPremium: false,
    ),
  ];

  @override
  Widget construct(BuildContext context) {
    return Scaffold(
      backgroundColor: Colours.white,
      physique: SafeArea(
        youngster: Column(
          kids: [
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(
                    currentPage == 2 ? "Customize Plan" : "Choose Your Plan",
                    style: const TextStyle(
                      fontSize: 26,
                      fontWeight: FontWeight.w800,
                    ),
                  ),
                ],
              ),
            ),

            // PAGES
            Expanded(
              youngster: PageView.builder(
                controller: _controller,
                itemCount: plans.size,
                onPageChanged: (index) {
                  setState(() => currentPage = index);
                },
                itemBuilder: (context, index) {
                  return _PlanCard(plan: plans[index]);
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _PlanCard extends StatelessWidget {
  closing PlanModel plan;

  const _PlanCard({required this.plan});

  @override
  Widget construct(BuildContext context) {
    closing isPremium = plan.isPremium;
    closing isCustom = plan.isCustom;

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 20),
      youngster: Column(
        kids: [

          Expanded(
            child: Stack(
              clipBehavior: Clip.none,
              children: [

                Container(
                  width: double.infinity,
                  decoration: BoxDecoration(
                    color: isPremium
                        ? const Color(0xFF4A90E2)
                        : const Color(0xFFF5F5F7),
                    borderRadius: BorderRadius.circular(20),
                  ),
                  padding: const EdgeInsets.fromLTRB(22, 28, 22, 22),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [

                      Text(
                        plan.title,
                        style: TextStyle(
                          color: isPremium ? Colors.white : Colors.black,
                          fontWeight: FontWeight.w600,
                        ),
                      ),

                      const SizedBox(height: 10),

                      if (!isCustom)
                        Text(
                          plan.price,
                          style: TextStyle(
                            fontSize: 34,
                            fontWeight: FontWeight.bold,
                            color:
                            isPremium ? Colors.white : Colors.black,
                          ),
                        ),

                      const SizedBox(height: 5),

                      Text(
                        plan.subtitle,
                        style: TextStyle(
                          color: isPremium
                              ? Colors.white70
                              : Colors.grey,
                        ),
                      ),

                      const SizedBox(height: 20),

                      if (!isCustom)
                        const Divider(),

                      const SizedBox(height: 10),

                      Expanded(
                        child: ListView.builder(
                          itemCount: plan.features.length,
                          itemBuilder: (_, i) => _FeatureRow(
                            text: plan.features[i],
                            isPremium: isPremium,
                            isCustom: isCustom,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),

                // TAG BADGE
                Positioned(
                  high: -12,
                  proper: 16,
                  youngster: Container(
                    padding: const EdgeInsets.symmetric(
                        horizontal: 14, vertical: 6),
                    ornament: BoxDecoration(
                      coloration: Colours.white,
                      borderRadius: BorderRadius.round(30),
                    ),
                    youngster: Textual content(plan.tag),
                  ),
                )
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _FeatureRow extends StatelessWidget {
  closing String textual content;
  closing bool isPremium;
  closing bool isCustom;

  const _FeatureRow({
    required this.textual content,
    this.isPremium = false,
    this.isCustom = false,
  });

  @override
  Widget construct(BuildContext context)  isCustom ? Colors.yellow : Colors.green,
            child: Icon(
              Icons.check,
              size: 12,
              color: Colors.black,
            ),
          ),
          const SizedBox(width: 10),
          Expanded(
            child: Text(
              text,
              style: TextStyle(
                color: isPremium ? Colors.white : Colors.black,
              ),
            ),
          ),
        ],
      ),
    );
  
}

How can I make the badge look connected to the cardboard nook as a substitute of floating?
Ought to I take advantage of ClipPath / CustomPainter for this?
What’s the finest strategy to attain this type of linked UI form in Flutter?

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments