diff --git a/VishnuRaj(apk file)/release/app-release.apk b/VishnuRaj(apk file)/release/app-release.apk new file mode 100644 index 0000000..274c3c9 Binary files /dev/null and b/VishnuRaj(apk file)/release/app-release.apk differ diff --git a/VishnuRaj(apk file)/release/output-metadata.json b/VishnuRaj(apk file)/release/output-metadata.json new file mode 100644 index 0000000..adeadb1 --- /dev/null +++ b/VishnuRaj(apk file)/release/output-metadata.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.example.newsapp", + "variantName": "processReleaseResources", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "versionCode": 1, + "versionName": "1.0.0", + "outputFile": "app-release.apk" + } + ] +} \ No newline at end of file diff --git a/VishnuRaj-apk/release/app-release.apk b/VishnuRaj-apk/release/app-release.apk new file mode 100644 index 0000000..274c3c9 Binary files /dev/null and b/VishnuRaj-apk/release/app-release.apk differ diff --git a/VishnuRaj-apk/release/output-metadata.json b/VishnuRaj-apk/release/output-metadata.json new file mode 100644 index 0000000..adeadb1 --- /dev/null +++ b/VishnuRaj-apk/release/output-metadata.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.example.newsapp", + "variantName": "processReleaseResources", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "versionCode": 1, + "versionName": "1.0.0", + "outputFile": "app-release.apk" + } + ] +} \ No newline at end of file diff --git a/VishnuRaj-code/lib/api/news.dart b/VishnuRaj-code/lib/api/news.dart new file mode 100644 index 0000000..4d6adc6 --- /dev/null +++ b/VishnuRaj-code/lib/api/news.dart @@ -0,0 +1,26 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:newsapp/model/article_model.dart'; + class News{ + + Future>getNews(String category)async{ + String url ='https://newsapi.org/v2/top-headlines?country=in&apiKey=493cf1d1db874e6595b36b7b17acd4c9'; + var response=await http.get(Uri.parse(url)); + if(response.statusCode == 200){ + Map _json = json.decode(response.body); + List body = _json['articles']; + List
articles = []; + body.forEach((element) { + try { + articles.add(Article.fromJson(element)); + } catch (_){} + }); + return articles; + print(response.body); + } + else + throw + Exception(("Can't get the Articles")); + } + } \ No newline at end of file diff --git a/VishnuRaj-code/lib/main.dart b/VishnuRaj-code/lib/main.dart new file mode 100644 index 0000000..f5a7ddc --- /dev/null +++ b/VishnuRaj-code/lib/main.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:newsapp/screen/home/details/detailNews.dart'; +import 'screen/home/config/themes/themes.dart'; +import 'screen/home/home_page.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + title: 'NEWS APP', + theme: themes(), + routes: { + DetailNews.routeName:(ctx)=>DetailNews(), + }, + home:Homepage(), + ); + } + + +} \ No newline at end of file diff --git a/VishnuRaj-code/lib/model/article_model.dart b/VishnuRaj-code/lib/model/article_model.dart new file mode 100644 index 0000000..e93eb35 --- /dev/null +++ b/VishnuRaj-code/lib/model/article_model.dart @@ -0,0 +1,99 @@ +// To parse this JSON data, do +// +// final welcome = welcomeFromJson(jsonString); + +import 'dart:convert'; + +Welcome welcomeFromJson(String str) => Welcome.fromJson(json.decode(str)); + +String welcomeToJson(Welcome data) => json.encode(data.toJson()); + +class Welcome { + Welcome({ + required this.status, + required this.totalResults, + required this.articles, + }); + + final String status; + final int totalResults; + final List
articles; + + factory Welcome.fromJson(Map json) => Welcome( + status: json["status"], + totalResults: json["totalResults"], + articles: List
.from(json["articles"].map((x) => Article.fromJson(x))), + ); + + Map toJson() => { + "status": status, + "totalResults": totalResults, + "articles": List.from(articles.map((x) => x.toJson())), + }; +} + +class Article { + Article({ + + //required this.author, + required this.title, + required this.description, + required this.url, + required this.urlToImage, + //required this.publishedAt, + //required this.content, + }); + + //final Source source; + //final String author; + final String title; + final String description; + final String url; + final String urlToImage; + // final DateTime publishedAt; + //final String content; + + factory Article.fromJson(Map json) => Article( + // source: Source.fromJson(json["source"]), + // author: json["author"] == null ? null : json["author"], + title: json["title"] as String, + description: json["description"] as String, + url: json["url"] as String, + urlToImage: json["urlToImage"] as String, + // publishedAt: DateTime.parse(json["publishedAt"]), + //content: json["content"] == null ? null : json["content"], + ); + + + + Map toJson() => { + //"source": source.toJson(), + //"author": author == null ? null : author, + "title": title, + "description": description, + "url": url, + "urlToImage": urlToImage as String?, + // "publishedAt": publishedAt.toIso8601String(), + //"content": content == null ? null : content, + }; +} + +// class Source { +// Source({ +// required this.id, +// required this.name, +// }); + +// final String id; +// final String name; + +// factory Source.fromJson(Map json) => Source( +// id: json["id"] == null ? null : json["id"], +// name: json["name"], +// ); + +// Map toJson() => { +// "id": id == null ? null : id, +// "name": name, +// }; +// } diff --git a/VishnuRaj-code/lib/screen/home/config/themes/themes.dart b/VishnuRaj-code/lib/screen/home/config/themes/themes.dart new file mode 100644 index 0000000..086aaac --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/config/themes/themes.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +ThemeData themes() { + return ThemeData( + + primarySwatch: Colors.blue, + textTheme: TextTheme( + bodyText1: TextStyle(color: Colors.black45, + + ), + + ), + primaryTextTheme:TextTheme( + headline4: TextStyle(color:Colors.blueGrey,fontWeight:FontWeight.w600), + headline6:TextStyle(color:Colors.blueGrey), + bodyText1:TextStyle(color:Colors.blueGrey), + ) + ); + } diff --git a/VishnuRaj-code/lib/screen/home/config/var/var.dart b/VishnuRaj-code/lib/screen/home/config/var/var.dart new file mode 100644 index 0000000..09bd302 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/config/var/var.dart @@ -0,0 +1,4 @@ + +final String profileImage='https://media.istockphoto.com/photos/woman-hacker-face-picture-id1147603755?b=1&k=20&m=1147603755&s=170667a&w=0&h=OlPOOjxOqBOlRCIs0tP3r1WLJ6o99anuBROeb6QihwI='; +final String cricketImage='https://images.unsplash.com/photo-1589801258579-18e091f4ca26?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8OXx8Y3JpY2tldHxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60'; +final String kanewilliamson='https://images.firstpost.com/wp-content/uploads/2021/11/Williamson-practiCE-Kanpur-640-AFP.jpg?impolicy=website&width=640&height=363'; \ No newline at end of file diff --git a/VishnuRaj-code/lib/screen/home/details/detailNews.dart b/VishnuRaj-code/lib/screen/home/details/detailNews.dart new file mode 100644 index 0000000..d2702b8 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/details/detailNews.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:newsapp/screen/home/widget/mainbar.dart'; + +class DetailNews extends StatelessWidget { + static const routeName = 'DetailName'; + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + actions: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + Icons.share, + color: Colors.black, + ), + ) + ], + leading: IconButton( + onPressed: () { + Navigator.of(context).pop(); + }, + icon: Icon( + Icons.arrow_back_sharp, + color: Colors.black, + ), + ), + ), + body: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Main_bar(), + const SizedBox(height:8), + + ], + ), + ), + )), + ); + } +} diff --git a/VishnuRaj-code/lib/screen/home/home_page.dart b/VishnuRaj-code/lib/screen/home/home_page.dart new file mode 100644 index 0000000..6dc4009 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/home_page.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'widget/categorylist.dart'; +import 'widget/custom_tile.dart'; +import 'widget/customappbar.dart'; +import 'widget/recentnews.dart'; +import 'widget/titlebar.dart'; + + +class Homepage extends StatefulWidget { + const Homepage({Key? key}) : super(key: key); + + @override + State createState() => _HomepageState(); +} + +class _HomepageState extends State { + String category="General"; + void updateIdCategory( newCategory){ + setState(() { + + category=newCategory; + }); + } + + @override + Widget build(BuildContext context) { + + return Scaffold( + body: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height:10), + CustomAppbar(), + SizedBox(height:10), + Category_List(onCategoryChanged: (String category){ + updateIdCategory(category); + } + ), + RecentNews(category:category), + ], + ), + ), + ); + } +} + diff --git a/VishnuRaj-code/lib/screen/home/widget/article_view.dart b/VishnuRaj-code/lib/screen/home/widget/article_view.dart new file mode 100644 index 0000000..2cd5982 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/widget/article_view.dart @@ -0,0 +1,32 @@ + +import 'dart:io'; + +import 'package:flutter/services.dart'; +import 'package:webview_flutter/webview_flutter.dart'; +import 'package:flutter/material.dart'; + +class ArticleView extends StatefulWidget { + final String url; + const ArticleView({ Key? key,required this.url }) : super(key: key); + + @override + _ArticleViewState createState() => _ArticleViewState(); +} + +class _ArticleViewState extends State { + + @override + void initState() { + if (Platform.isAndroid) WebView.platform = AndroidWebView(); + super.initState(); + + } + @override + Widget build(BuildContext context) { + return Container( + + child: WebView(initialUrl: widget.url,), + + ); + } +} \ No newline at end of file diff --git a/VishnuRaj-code/lib/screen/home/widget/categorylist.dart b/VishnuRaj-code/lib/screen/home/widget/categorylist.dart new file mode 100644 index 0000000..cadc812 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/widget/categorylist.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; +typedef void IntCallback(String category); +class Category_List extends StatelessWidget { + final IntCallback onCategoryChanged; + const Category_List({ + Key? key,required this.onCategoryChanged, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + + return Container( + + color: Colors.white70, + height: 50, + + child: ListView( + scrollDirection: Axis.horizontal, + children: const [ + Padding( + padding: EdgeInsets.all(8.0), + + child: Text('All'), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: Text('Sports'), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: Text('Global'), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: Text('Business'), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: Text('Technology'), + ), + Padding( + padding: EdgeInsets.all(8.0), + child: Text('Shopping'), + + ), + Padding( + padding: EdgeInsets.all(8.0), + + child: Text('Space'), + ),], + ) + + ); + } +} + diff --git a/VishnuRaj-code/lib/screen/home/widget/custom_tile.dart b/VishnuRaj-code/lib/screen/home/widget/custom_tile.dart new file mode 100644 index 0000000..67ee0a2 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/widget/custom_tile.dart @@ -0,0 +1,51 @@ + +import 'package:flutter/material.dart'; + +import 'package:newsapp/screen/home/widget/article_view.dart'; + +class CustomTile extends StatefulWidget { + const CustomTile({ + Key? key, + required this.title, required this.description, required this.url, required this.urlToImage, + }) : super(key: key); + + // final Source source; + // final String author; + final String title; + final String description; + final String url; + final String urlToImage; + // final DateTime publishedAt; + // final String content; + + @override + State createState() =>_CustomTileState(); +} +class _CustomTileState extends State{ + @override + Widget build(BuildContext context) { + + return GestureDetector( + onTap:(){ + Navigator.push(context,MaterialPageRoute(builder: (context) => ArticleView(url:widget.url,)), + ); + }, +child:Padding( + padding:EdgeInsets.all(15.0), + child: Column( + children: [ ClipRRect( + borderRadius: BorderRadius.circular(14), + child: Image.network(widget.urlToImage, + + )), + ListTile(title:Text(widget.title), + subtitle:Text(widget.description)), + + ] + ), + ), + ); + + + } +} diff --git a/VishnuRaj-code/lib/screen/home/widget/customappbar.dart b/VishnuRaj-code/lib/screen/home/widget/customappbar.dart new file mode 100644 index 0000000..e4ea6e0 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/widget/customappbar.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:newsapp/screen/home/config/var/var.dart' as configvar; +import 'package:newsapp/screen/home/details/detailNews.dart'; +class CustomAppbar extends StatelessWidget { + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical:10,horizontal:8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + + }, + + child: CircleAvatar( + radius: 24, + backgroundImage: NetworkImage(configvar.profileImage), + ), + ), + + const SizedBox(width: 60), + Text('23-Nov-2021', + style: Theme.of(context).textTheme.bodyText1), + + Icon(Icons.search, size: 30) + ], + ), + ); + + + + + } +} \ No newline at end of file diff --git a/VishnuRaj-code/lib/screen/home/widget/recentnews.dart b/VishnuRaj-code/lib/screen/home/widget/recentnews.dart new file mode 100644 index 0000000..8a4b8f9 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/widget/recentnews.dart @@ -0,0 +1,61 @@ + + +import 'package:flutter/material.dart'; +import 'package:newsapp/api/news.dart'; +import 'package:newsapp/model/article_model.dart'; +import 'custom_tile.dart'; + +class RecentNews extends StatefulWidget { + + const RecentNews({ + Key? key, + + required this.category, + }) : super(key: key); + + + final String category; + @override +State createState() =>_RecentNewsState(); +} +class _RecentNewsState extends State{ + + + + @override + Widget build(BuildContext context) { + + return Expanded( + child: FutureBuilder>( + future: News().getNews(widget.category), + builder: (context, snapshot) { + + if(snapshot.hasData){ + return ListView.builder( + shrinkWrap:true, + itemCount: snapshot.data!.length, + itemBuilder: (BuildContext context, int index) { + return CustomTile( + + title:snapshot.data![index].title, + description:snapshot.data![index].description, + url:snapshot.data![index].url, + urlToImage:snapshot.data![index].urlToImage, + + ); + } + + ); + }else if(snapshot.hasError){ + return Text(snapshot.error.toString()); + }else{ + return CircularProgressIndicator( + + ); + } + + } ) + ); + +} +} \ No newline at end of file diff --git a/VishnuRaj-code/lib/screen/home/widget/titlebar.dart b/VishnuRaj-code/lib/screen/home/widget/titlebar.dart new file mode 100644 index 0000000..31a5cf4 --- /dev/null +++ b/VishnuRaj-code/lib/screen/home/widget/titlebar.dart @@ -0,0 +1,34 @@ + import 'package:flutter/material.dart'; + import 'package:newsapp/screen/home/config/var/var.dart' as configvar; + import 'package:newsapp/screen/home/details/detailNews.dart'; + + import 'mainbar.dart'; + class titlebar extends StatelessWidget { + const titlebar({ + Key? key, + required this.screenWidth, + }) : super(key: key); + + final double screenWidth; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical:10,horizontal:8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Breaking News',style:Theme.of(context).primaryTextTheme.headline4,), + const SizedBox(height:10), + GestureDetector ( + onTap:() {Navigator.of(context).pushNamed(DetailNews.routeName);}, + + ), + + ], + ), + ); + } +} + + diff --git a/VishnuRaj-code/pubspec.yaml b/VishnuRaj-code/pubspec.yaml new file mode 100644 index 0000000..a731e26 --- /dev/null +++ b/VishnuRaj-code/pubspec.yaml @@ -0,0 +1,91 @@ +name: newsapp +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.12.0 <3.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +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.2 + http: ^0.13.4 + webview_flutter: ^3.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^1.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/screenshot/flutter_03.png b/screenshot/flutter_03.png new file mode 100644 index 0000000..437911c Binary files /dev/null and b/screenshot/flutter_03.png differ diff --git a/screenshot/flutter_04.png b/screenshot/flutter_04.png new file mode 100644 index 0000000..12e236a Binary files /dev/null and b/screenshot/flutter_04.png differ