UI News App

  • Screen 1

    UI

    1 . API call with async

    pubspec.yaml

    
    dependencies:
      flutter:
        sdk: flutter
    
    
      # The following adds the Cupertino Icons font to your application.
      # Use with the CupertinoIcons class for iOS style icons.
      cupertino_icons: ^1.0.6
      http: ^1.2.1
      cached_network_image: ^3.3.1
    
    

    main.dart

    
    
    import 'package:flutter/material.dart';
    import 'package:new_app_api/Screen/home_screen.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 const MaterialApp(
          debugShowCheckedModeBanner: false,
          home: NewsHomeScreen(),
        );
      }
    }
    

    model/category_data.dart

    
    import 'new_model.dart';
    
    List<CategoryModel> getCategories() {
      // news category list
      List<CategoryModel> categories = [];
    
      CategoryModel category = CategoryModel();
      category.categoryName = "Science";
    
      categories.add(category);
    
      category = CategoryModel();
      category.categoryName = "Sports";
    
      categories.add(category);
    
      category = CategoryModel();
      category.categoryName = "Business";
    
      categories.add(category);
    
      category = CategoryModel();
      category.categoryName = "General";
    
      categories.add(category);
    
      category = CategoryModel();
      category.categoryName = "Health";
    
      categories.add(category);
    
      category = CategoryModel();
      category.categoryName = "Entertainment";
    
      categories.add(category);
    
      return categories;
    }
    
    

    model/new_model.dart

    
    class CategoryModel {
      String? categoryName;
    
      CategoryModel({
        this.categoryName,
      });
    }
    
    class NewsModel {
      String? title;
      String? description;
    
      String? urlToImage;
      String? author;
      String? content;
    
      NewsModel({
        this.title,
        this.description,
        this.urlToImage,
        this.author,
        this.content,
      });
    }
    

    Services/services.dart

    
    import 'dart:convert';
    
    import 'package:http/http.dart' as http;
    import 'package:new_app_api/model/new_model.dart';
    
    class NewsApi {
      // for news home screen
      List<NewsModel> dataStore = [];
      Future<void> getNews() async {
        Uri url = Uri.parse(
            "https://newsapi.org/v2/top-headlines?country=us&apiKey=313e712139fc486796d895c700aef894");
        var response = await http.get(url);
        var jsonData = jsonDecode(response.body);
        if (jsonData["status"] == 'ok') {
          jsonData["articles"].forEach((element) {
            if (element['urlToImage'] != null &&
                element['description'] != null &&
                element['author'] != null &&
                element['content'] != null) {
              NewsModel newsModel = NewsModel(
                title: element['title'], // name must be same fron api
                urlToImage: element['urlToImage'],
                description: element['description'],
                author: element['author'],
                content: element['content'],
              );
              dataStore.add(newsModel);
            }
          });
        }
      }
    }
    
    class CategoryNews {
      // for news home screen
      List<NewsModel> dataStore = [];
      Future<void> getNews(String category) async {
        Uri url = Uri.parse(
            "https://newsapi.org/v2/top-headlines?country=us&category=$category&apiKey=313e712139fc486796d895c700aef894");
        var response = await http.get(url);
        var jsonData = jsonDecode(response.body);
    
        if (jsonData["status"] == 'ok') {
          jsonData["articles"].forEach((element) {
            if (element['urlToImage'] != null &&
                element['description'] != null &&
                element['author'] != null &&
                element['content'] != null) {
              NewsModel newsModel = NewsModel(
                title: element['title'], // name must be same fron api
                urlToImage: element['urlToImage'],
                description: element['description'],
                author: element['author'],
                content: element['content'],
              );
              dataStore.add(newsModel);
            }
          });
        }
      }
    }
    // for category news
    // we have used the free news api. for that, first you need to create a account and  then login 
    // after that get the api key  
    

    Screen/category_news.dart

    
    import 'package:flutter/material.dart';
    import 'package:new_app_api/Screen/news_detail.dart';
    import 'package:new_app_api/Services/services.dart';
    
    import '../model/new_model.dart';
    
    class SelectedCategoryNews extends StatefulWidget {
      String category;
      SelectedCategoryNews({super.key, required this.category});
    
      @override
      State<SelectedCategoryNews> createState() => _SelectedCategoryNewsState();
    }
    
    class _SelectedCategoryNewsState extends State<SelectedCategoryNews> {
      List<NewsModel> articles = [];
      bool isLoadin = true;
      getNews() async {
        CategoryNews news = CategoryNews();
        await news.getNews(widget.category);
        articles = news.dataStore;
        setState(() {
          isLoadin = false;
        });
      }
    
      @override
      void initState() {
        getNews();
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.blue,
            foregroundColor: Colors.white,
            title: Text(
              widget.category,
              style: const TextStyle(
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
          body: isLoadin
              ? const Center(
                  child: CircularProgressIndicator(),
                )
              : SingleChildScrollView(
                  child: ListView.builder(
                    itemCount: articles.length,
                    shrinkWrap: true,
                    physics: const ClampingScrollPhysics(),
                    itemBuilder: (context, index) {
                      final article = articles[index];
                      return GestureDetector(
                        onTap: () {
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => NewsDetail(newsModel: article),
                            ),
                          );
                        },
                        child: Container(
                          margin: const EdgeInsets.all(15),
                          child: Column(
                            children: [
                              ClipRRect(
                                borderRadius: BorderRadius.circular(10),
                                child: Image.network(
                                  article.urlToImage!,
                                  height: 250,
                                  width: 400,
                                  fit: BoxFit.cover,
                                ),
                              ),
                              const SizedBox(height: 10),
                              Text(
                                article.title!,
                                style: const TextStyle(
                                  fontWeight: FontWeight.bold,
                                  fontSize: 18,
                                ),
                              ),
                              const Divider(thickness: 2),
                            ],
                          ),
                        ),
                      );
                    },
                  ),
                ),
        );
      }
    }
    

    Screen/home_screen.dart

    
    import 'package:flutter/material.dart';
    import 'package:flutter/widgets.dart';
    import 'package:new_app_api/Screen/category_news.dart';
    import 'package:new_app_api/Screen/news_detail.dart';
    import 'package:new_app_api/Services/services.dart';
    import 'package:new_app_api/model/category_data.dart';
    
    import '../model/new_model.dart';
    
    class NewsHomeScreen extends StatefulWidget {
      const NewsHomeScreen({super.key});
    
      @override
      _NewsHomeScreenState createState() => _NewsHomeScreenState();
    }
    
    class _NewsHomeScreenState extends State<NewsHomeScreen> {
      List<NewsModel> articles = [];
      List<CategoryModel> categories = [];
      bool isLoadin = true;
      getNews() async {
        NewsApi newsApi = NewsApi();
        await newsApi.getNews();
        articles = newsApi.dataStore;
        setState(() {
          isLoadin = false;
        });
      }
    
      @override
      void initState() {
        categories = getCategories();
        getNews();
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text(
              "Flutte News App",
              style: TextStyle(
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
          body: isLoadin
              ? const Center(
                  child: CircularProgressIndicator(),
                )
              : SingleChildScrollView(
                  child: Column(
                    children: [
                      // for category selection
                      Container(
                        height: 55,
                        padding: const EdgeInsets.symmetric(
                          horizontal: 15,
                        ),
                        child: ListView.builder(
                          itemCount: categories.length,
                          shrinkWrap: true,
                          scrollDirection: Axis.horizontal,
                          itemBuilder: (context, index) {
                            final category = categories[index];
                            return GestureDetector(
                              onTap: () {
                                Navigator.push(
                                  context,
                                  MaterialPageRoute(
                                    builder: (context) => SelectedCategoryNews(
                                      category: category.categoryName!,
                                    ),
                                  ),
                                );
                              },
                              child: Padding(
                                padding: const EdgeInsets.only(right: 15),
                                child: Container(
                                  alignment: Alignment.center,
                                  padding: const EdgeInsets.all(15),
                                  decoration: BoxDecoration(
                                      borderRadius: BorderRadius.circular(20),
                                      color: Colors.blue),
                                  child: Center(
                                    child: Text(
                                      category.categoryName!,
                                      style: const TextStyle(
                                        fontWeight: FontWeight.bold,
                                        fontSize: 18,
                                        color: Colors.white,
                                      ),
                                    ),
                                  ),
                                ),
                              ),
                            );
                          },
                        ),
                      ),
                      // for home screen news
                      ListView.builder(
                        itemCount: articles.length,
                        shrinkWrap: true,
                        physics: const ClampingScrollPhysics(),
                        itemBuilder: (context, index) {
                          final article = articles[index];
                          return GestureDetector(
                            onTap: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                  builder: (context) =>
                                      NewsDetail(newsModel: article),
                                ),
                              );
                            },
                            child: Container(
                              margin: const EdgeInsets.all(15),
                              child: Column(
                                children: [
                                  ClipRRect(
                                    borderRadius: BorderRadius.circular(10),
                                    child: Image.network(
                                      article.urlToImage!,
                                      height: 250,
                                      width: 400,
                                      fit: BoxFit.cover,
                                    ),
                                  ),
                                  const SizedBox(height: 10),
                                  Text(
                                    article.title!,
                                    style: const TextStyle(
                                      fontWeight: FontWeight.bold,
                                      fontSize: 18,
                                    ),
                                  ),
                                  const Divider(thickness: 2),
                                ],
                              ),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                ),
        );
      }
    }
    
    

    Screen/news_detail.dart

    
    import 'package:flutter/material.dart';
    import 'package:new_app_api/model/new_model.dart';
    
    class NewsDetail extends StatelessWidget {
      final NewsModel newsModel;
      const NewsDetail({super.key, required this.newsModel});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          body: Padding(
            padding: const EdgeInsets.all(8.0),
            child: ListView(
              children: [
                Text(
                  newsModel.title!,
                  style: const TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 20,
                  ),
                ),
                Row(
                  children: [
                    const Expanded(
                      child: SizedBox(),
                    ),
                    Expanded(
                        child: Text(
                      "- ${newsModel.author!}",
                      maxLines: 1,
                    ))
                  ],
                ),
                const SizedBox(height: 10),
                Image.network(newsModel.urlToImage!),
                const SizedBox(height: 10),
                Text(
                  newsModel.content!,
                  style: const TextStyle(
                    fontSize: 18,
                  ),
                ),
                const SizedBox(height: 10),
                Text(
                  newsModel.description!,
                  style: const TextStyle(
                    fontSize: 18,
                  ),
                )
              ],
            ),
          ),
        );
      }
    }