Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/images/background/bluebg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/background/greenbg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/background/purplebg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/background/redbg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/background/yellowbg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/heros/capitan.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/heros/dedpool.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/heros/iron.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/heros/spiderman.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/heros/strange.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/heros/tanos.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/heros/thor.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/marvel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 15 additions & 48 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'package:flutter/material.dart';
import 'package:marvel_app/models/hero.dart';
import 'package:marvel_app/models/models_data.dart';
import 'package:marvel_app/screens/main_screen.dart';

void main() {
runApp(const MyApp());
Expand All @@ -9,61 +12,25 @@ class MyApp extends StatelessWidget {

@override
Widget build(BuildContext context) {

return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});

final String title;

@override
State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;

void _incrementCounter() {
setState(() {
_counter++;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
home: FutureBuilder(
future: fetchHeroes(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Scaffold(body: Center(child: CircularProgressIndicator()));
} else {
return MainScreen(snapshot.data as List<MarvelHero>);
}
}
),
);
}
}

23 changes: 23 additions & 0 deletions lib/models/hero.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class MarvelHero {
late String name;
late String description;
late String imagePath;
// String imageBGPath ='assets/images/background/bluebg.png';

MarvelHero(
//String? imageBGPath,
{
required this.name,
required this.description,
required this.imagePath,
}
);


MarvelHero.fromJson(Map<String, dynamic> json, String imageBGPath){
name = json['name'];
description = json['description'];
imagePath = json['thumbnail']['path'] + '.' + json['thumbnail']['extension'];
//this.imageBGPath = imageBGPath;
}
}
51 changes: 51 additions & 0 deletions lib/models/models_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:marvel_app/models/hero.dart';

const String publicKey = 'b599b2cea5c8b794ba83cadf41a70e67';
const String privateKey = '768333402f2317458d0ead51c300c9f3947a0b64';
const String baseUrl = 'https://gateway.marvel.com/v1/public/characters';

final List<String> imagesBG = [
'assets/images/background/bluebg.png',
'assets/images/background/redbg.png',
'assets/images/background/yellowbg.png',
'assets/images/background/purplebg.png',
'assets/images/background/greenbg.png',
];

final List<MarvelHero> herosAPI = [];

String generateHash(String timeStamp) {
var bytes = utf8.encode('$timeStamp$privateKey$publicKey');
var digest = md5.convert(bytes);
return digest.toString();
}

Future<List<dynamic>> fetchHeroes() async {
final timeStamp = 1.toString();
final hash = generateHash(timeStamp);

final dio = Dio();

final response = await dio.get('$baseUrl?apikey=$publicKey&ts=$timeStamp&hash=$hash');

if (response.statusCode == 200) {
Map<String, dynamic> responseData = response.data; // response.data is already a Map
Map<String, dynamic> data = responseData['data'] as Map<String, dynamic>;

List<dynamic> heroesList = data['results'];

int indeximageBG = 0;
for (var i = 0; i < heroesList.length; i++) {
Map<String, dynamic> hero = heroesList[i] as Map<String, dynamic>;
herosAPI.add(MarvelHero.fromJson(hero, imagesBG[indeximageBG]));
indeximageBG++;
if (indeximageBG >= imagesBG.length) indeximageBG = 0;
}
return herosAPI;
} else {
throw Exception('Failed to load heroes');
}
}
89 changes: 89 additions & 0 deletions lib/screens/info_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import 'package:flutter/material.dart';
import 'package:marvel_app/models/hero.dart';
import 'package:marvel_app/models/models_data.dart';

class InfoScreen extends StatefulWidget {
const InfoScreen({super.key, required this.hero, required this.indeximageBG});

final MarvelHero hero;
final int indeximageBG;

@override
State<InfoScreen> createState() => _InfoScreenState();
}

class _InfoScreenState extends State<InfoScreen> {


_backPage(){
Navigator.pop(context);
}

@override
Widget build(BuildContext context) {
return Scaffold(
//appBar: AppBar(backgroundColor: Colors.transparent,),
body: Stack(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
padding: const EdgeInsets.only(top: 80),
decoration: BoxDecoration(
image: DecorationImage(
image: ExactAssetImage(imagesBG[widget.indeximageBG]),
fit: BoxFit.cover,
),
),
),
Hero(
tag: widget.hero.name,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(widget.hero.imagePath),
fit: BoxFit.cover),
),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.hero.name,
style: const TextStyle(
color: Colors.white,
fontSize: 40,
fontWeight: FontWeight.bold),
),
Text(
widget.hero.description,
style: const TextStyle(
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.bold),
),
],
),
),
),
),
Padding(
padding: const EdgeInsets.all(18.0),
child: IconButton(
alignment: Alignment.topLeft,
onPressed: () {_backPage();},
icon: const Icon(
Icons.arrow_back,
color: Colors.white,
),
),
),
],
),
);
}
}
146 changes: 146 additions & 0 deletions lib/screens/main_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import 'package:flutter/material.dart';
import 'package:marvel_app/models/hero.dart';
import 'package:marvel_app/models/models_data.dart';
import 'package:marvel_app/screens/info_screen.dart';
import 'package:marvel_app/widgets/marvel_logo.dart';

class MainScreen extends StatefulWidget {
const MainScreen(this.marvelHeros, {Key? key}) : super(key: key);

final List<MarvelHero> marvelHeros;

@override
_MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {

late List<MarvelHero> heros;

late final PageController _pageController;

int currentPage = 0;
int indeximageBG = 0;

_nextPage(MarvelHero hero, int indeximageBG) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => InfoScreen(
hero: hero,
indeximageBG: indeximageBG,
)),
);
}

@override
void initState() {
super.initState();
_pageController = PageController(viewportFraction: 0.8);
heros = widget.marvelHeros;
}

@override
void dispose() {
super.dispose();
_pageController.dispose();
}


@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
alignment: Alignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
padding: const EdgeInsets.only(top: 80),
decoration: BoxDecoration(
image: DecorationImage(
image: ExactAssetImage(imagesBG[indeximageBG]),
fit: BoxFit.cover,
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.only(
top: 50,
),
child: MarvelLogo(),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 40.0),
child: Text(
'Choose your hero',
style: TextStyle(
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.bold),
),
),
SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 1.5,
child: PageView.builder(
controller: _pageController,
onPageChanged: (value) => {
setState(
() {
currentPage = value;
indeximageBG++;
if (indeximageBG >= imagesBG.length - 1) indeximageBG = 0;
},
)
},
itemCount: heros.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, int index) {
return GestureDetector( //row gesture detector
onTap: () {
_nextPage(heros[index], indeximageBG);
},
child: AnimatedScale(
scale: index == currentPage ? 1 : 0.8,
duration: const Duration(milliseconds: 300),
child: Hero(
tag: heros[index].name,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
image: DecorationImage(
image: NetworkImage(heros[index].imagePath),
fit: BoxFit.cover),
),
child: Container(
alignment: Alignment.bottomLeft,
child: Padding(
padding: const EdgeInsets.all(25.0),
child: Text(
heros[index].name,
style: const TextStyle(
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.bold),
),
),
),
),
),
),
);
},
),
),
],
)
],
),
);
}
}
Loading