Url shortener app with flutter

In this article, we'll build a simple app for shortening long urls with flutter. I'm making use of android studio but you can do the same with visual studio code

Table of contents

  • Building the app UI.
  • Making the API call.
  • Conclusion.

Building the app UI.

Our UI will look like this.

Screenshot_20221028-134657.png

Create a new flutter project and give the name url shortener.

new_proj.jpg

Create these dart files in your lib folder

lib_folder.jpg

The home_page.dart will look like this

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart';
import 'package:url_shortener/left_bar.dart';
import 'package:url_shortener/right_bar.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  final TextEditingController _linkController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Url Shortener"),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
             Column(
               mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const SizedBox(height: 60,),
                  const Text("Enter your long URL here",
                  style: TextStyle(
                    fontSize: 20,
                    ),
                  ),
                  const SizedBox(height: 20,),
                  Padding(
                    padding: const EdgeInsets.only(left: 18.0, right: 18),
                      child: TextFormField(
                        decoration: InputDecoration(
                            border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(5)
                            ),
                        ),
                         style: const TextStyle(
                           fontSize: 20,
                         ),
                        textAlign: TextAlign.center,
                        controller: _linkController,
                      )
                  ),
                  const SizedBox(height: 20,),
                  GestureDetector(
                    onTap: () async {
                     final shortenedUrl = await shortenUrl(url: _linkController.text);
                      if(shortenedUrl != null){
                        showDialog(
                            context: context,
                            builder: (context) {
                              return  AlertDialog(
                                title: const Text('Your Shortened Bub-URL'),
                                content: SizedBox(
                                  height: 100,
                                  child: Column(
                                    children: [
                                      Row(
                                        children: [
                                          GestureDetector(
                                            onTap: () async {
                                              if(await canLaunchUrl(Uri.parse(shortenedUrl))){
                                                await launchUrl(Uri.parse(shortenedUrl));
                                              }
                                            },
                                            child: Container(
                                              height: 40,
                                              decoration: BoxDecoration(
                                                color: Colors.white,
                                                borderRadius: BorderRadius.circular(5)
                                              ),
                                              width: 150,
                                              child: Text(shortenedUrl),
                                            ),
                                          ),
                                          IconButton(onPressed: (){
                                            Clipboard.setData(ClipboardData(text: shortenedUrl)).then((_) =>
                                                ScaffoldMessenger.of(context).showSnackBar(
                                                    const SnackBar(content: Text('Copied!'))
                                                ));
                                           }, icon: const Icon(Icons.copy))
                                        ],
                                      ),
                                      ElevatedButton.icon(onPressed: (){
                                        _linkController.clear();
                                        Navigator.pop(context);
                                       }, icon: const Icon(Icons.close), label: const Text('Close'))
                                    ],
                                  ),
                                ),
                              );
                            }
                        );
                      }
                    },
                    child: Container(
                        width: 80,
                        height: 50,
                        decoration: BoxDecoration(
                            color: Colors.blue,
                            borderRadius: BorderRadius.circular(20),
                            border: Border.all(color: Colors.blue)
                        ),
                        child: Padding(
                          padding: const EdgeInsets.only(top: 12.0),
                          child: const Text(
                            "Bub It",
                            style: TextStyle(
                              color: Colors.white,
                              fontSize: 20,
                            ),
                            textAlign: TextAlign.center,
                          ),
                        )
                    ),
                  ),
                  const SizedBox(height: 40,),
                  const LeftBar(barWidth: 40,),
                  const SizedBox(height: 20,),
                  const LeftBar(barWidth: 70,),
                  const SizedBox(height: 20,),
                  const RightBar(barWidth: 70,),
                  const SizedBox(height: 20,),
                  const RightBar(barWidth: 40,),
                  const SizedBox(height: 20,),
                  const LeftBar(barWidth: 70,),
                  const SizedBox(height: 20,),
                  const LeftBar(barWidth: 40,),
                  const SizedBox(height: 20,),
                  const SizedBox(height: 20,),
                  const RightBar(barWidth: 40,),
                  const SizedBox(height: 20,),
                  const RightBar(barWidth: 70,),
                ],
              ),
          ],
        ),
      ),
    );
  }

  Future<String?> shortenUrl({required String url}) async {
    try{
      final result = await http.post(
          Uri.parse('https://cleanuri.com/api/v1/shorten'),
          body: {
            'url': url
          }
      );

      if(result.statusCode == 200){
        final jsonResult = jsonDecode(result.body);
        return jsonResult['result_url'];
      }
    }catch (e){
      print('Error ${e.toString()}');
    }
    return null;
  }

}

For the left and right bar.

import 'package:flutter/material.dart';

class LeftBar extends StatelessWidget {
  final double barWidth;
  const LeftBar({Key? key, required this.barWidth}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.end,
      children: [
        Container(
          height: 25,
          width: barWidth,
          decoration: const BoxDecoration(
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(20),
              bottomLeft: Radius.circular(20),
            ),
            color: Colors.blue
          ),
        )
      ],
    );
  }
}

import 'package:flutter/material.dart';

class RightBar extends StatelessWidget {
  final double barWidth;
  const RightBar({Key? key, required this.barWidth}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.start,
      children: [
        Container(
          height: 25,
          width: barWidth,
          decoration: const BoxDecoration(
              borderRadius: BorderRadius.only(
                topRight: Radius.circular(20),
                bottomRight: Radius.circular(20),
              ),
              color: Colors.blue
          ),
        )
      ],
    );
  }
}

You can modify their sizes as you want on the home_page.dart.


                  const SizedBox(height: 20,),
                  const LeftBar(barWidth: 70,),
                  const SizedBox(height: 20,),
                  const RightBar(barWidth: 70,),
                  const SizedBox(height: 20,),
                  const RightBar(barWidth: 40,),
                  const SizedBox(height: 20,),
                  const LeftBar(barWidth: 70,),
                  const SizedBox(height: 20,),
                  const LeftBar(barWidth: 40,),
                  const SizedBox(height: 20,),
                  const SizedBox(height: 20,),
                  const RightBar(barWidth: 40,),
                  const SizedBox(height: 20,),
                  const RightBar(barWidth: 70,),
  • Finally, our main.dart looks like this

import 'package:flutter/material.dart';
import 'package:url_shortener/home_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});


  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      home:  HomePage(),
    );
  }
}

Making the API Call

Our api call was made in our home_page.dart. You can use the one below or any other api created by a backend service.

'https://cleanuri.com/api/v1/shorten'

To make the http request, we need to use the flutter http library and import in our project. For this add this in your terminal.

terminal.jpg

Then import in your home_page.dart

import 'package:http/http.dart' as http;

In the home_page.dart, we have this


Future<String?> shortenUrl({required String url}) async {
    try{
      final result = await http.post(
          Uri.parse('https://cleanuri.com/api/v1/shorten'),
          body: {
            'url': url
          }
      );

      if(result.statusCode == 200){
        final jsonResult = jsonDecode(result.body);
        return jsonResult['result_url'];
      }
    }catch (e){
      print('Error ${e.toString()}');
    }
    return null;
  }

Conclusion We've successfully created our url_shortener app.

After entering the long url, an alert dialog will pop up showing the shortened url.

Screenshot_20221027-162559.png

You can get the complete source code on the Github Link

Thanks for following, please feel free to ask any questions if you have.

0
Subscribe to my newsletter

Read articles from Osalumenese Ighedosa directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Osalumenese Ighedosa
Osalumenese Ighedosa

Flutter developer