How to Build Wallpaper App Using Flutter
hello and welcome, in this discussion I will share how to Build Wallpaper Apps using Flutter, in this part I will show the process how to build it
this is the table of Content What will we be the topic this time
Table of Content
- Creating Your Flutter Project
- Creating Base Applications
- Creating Views
- Creating Widget
- Creating Class to Fetching API and Handling Category
- Creating Model
let’s go straight to the topic of the first discussion
Creating Your Flutter Project
lets creating a flutter project to start building wallpaper apps
- Open the IDE and select Create New Flutter Project.
- Select Flutter Application as the project type. Then click Next.
- Verify the Flutter SDK path specifies the SDK’s location (select Install SDK… if the text field is blank).
- Enter a project name (for example,
wallpaperapps
). Then click Next. - Click Finish.
- Wait for Android Studio to install the SDK and create the project.
from the official documentation
Creating Base Applications
the second step is to create a base Application Structure, add this to main.dart
import 'package:flutter/material.dart';
import 'package:wallpaperapps/views/home.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Wallpaper Apps',
theme: ThemeData(
primaryColor: Colors.white,
),
home: Home(),
);
}
}
in this code, we call Home()
class from View but Error because not Already created, in next step let's create a views
Creating Views
let’s creating views for our applications, first create Home()
class for Home View like this
Handling Home View
create views
directory inside lib
directory and create home.dart
inside views
directory and create StatefulWidget
for home view
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
// fetch data
// fetching curated photo from API
getCuratedPhotos() async {
var url = Uri.parse("https://api.pexels.com/v1/curated?per_page=20");
var response = await http.get(url,
headers: {
"Authorization":apiKey
});
// print(response.body.toString());
// parsing data from API (Json)
Map<String, dynamic> jsonData = jsonDecode(response.body);
// parsing data
jsonData["photos"].forEach((element){
// print(element); // dev mode
// getting data
WallpaperModel wallpaperModel = new WallpaperModel();
wallpaperModel = WallpaperModel.fromMap(element);
wallpapers.add(wallpaperModel);
// print(wallpapers.length); // dev mode
});
// set state
setState(() {});
}
inside Home()
class, there is a function to retrieve data from the API to determine photos in the category column
// fetching curated photo from API
getCuratedPhotos() async {
var url = Uri.parse("https://api.pexels.com/v1/curated?per_page=20");
var response = await http.get(url,
headers: {
"Authorization":apiKey
});
// print(response.body.toString());
// parsing data from API (Json)
Map<String, dynamic> jsonData = jsonDecode(response.body);
// parsing data
jsonData["photos"].forEach((element){
// getting data
WallpaperModel wallpaperModel = new WallpaperModel();
wallpaperModel = WallpaperModel.fromMap(element);
wallpapers.add(wallpaperModel);
});
// set state
setState(() {});
}
Building Navbar Widget and List Wallpaper
now building Navbar Widget let’s call the widget brandName()
create this inside widgets
directory create file widget.dart
// widget.dart// brandNameWidget brandName(){
return RichText(
text: TextSpan(
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
children: const <TextSpan>[
TextSpan(text: 'Wallpaper', style: TextStyle(color: Colors.black87)),
TextSpan(text: 'Apps', style: TextStyle(color: Colors.blue)),
],
),
);
}
and here is a widget for wallpaper List
// list wallpaper
Widget wallpaperList({required List <WallpaperModel> wallpapers, context }){
return Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: GridView.count(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
crossAxisCount: 2,
childAspectRatio: 0.6,
mainAxisSpacing: 6.0,
crossAxisSpacing: 6.0,
children: wallpapers.map((wallpaper){
return GridTile(
child: GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => ImageView(imgUrl: wallpaper.src!.portrait)
));
},
child: Hero(
tag: wallpaper.src!.portrait,
child: Container(
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(wallpaper.src!.portrait, fit: BoxFit.cover,)),
),
),
));
}).toList(),
),
);
}
Building Home User Interface
The next step is to Build Home User Interface, now let’s see the design
let’s back to our views/home.dart
and add this code inside Home()
class
List <CategoriesModel> categories = [];
List <WallpaperModel> wallpapers = [];
// text controller
TextEditingController searchController = new TextEditingController();
// initState
@override
void initState() {
getCuratedPhotos();
categories = getCategories();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white ,//Colors.white, custom: 0xFF2B4772
appBar: AppBar(
title: brandName(),
elevation: 0.0
),
body: SingleChildScrollView(
child: Container(child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Color(0xfff5f8fd), // default colors: 0xfff5f8fd, custom: 0xFF2B4772
borderRadius: BorderRadius.circular(30)
),
padding: EdgeInsets.symmetric(horizontal: 24),
margin: EdgeInsets.symmetric(horizontal: 24),
child: Row(children: [
Expanded(
child: TextField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search",
border: InputBorder.none,
),
),
),
GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => Search(
searchQuery: searchController.text,
)
));
},
child: Container(
child: Icon(Icons.search)),
)
],)
,),
SizedBox(height: 16,),
Container(
height: 80,
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 24),
itemCount: categories.length,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: ((context, index){
return CategoryTitle(
title: categories[index].categoriesName,
imgUrl: categories[index].imgUrl,
);
}),
),
),
SizedBox(height: 16,),
wallpaperList(wallpapers: wallpapers, context: context),
],),),
),
);
}
}
Search Bar
we just created a function for handling search and a grid for displaying images, which can be seen in
// search BarContainer(
decoration: BoxDecoration(
color: Color(0xfff5f8fd), // default colors: 0xfff5f8fd, custom: 0xFF2B4772
borderRadius: BorderRadius.circular(30)
),
padding: EdgeInsets.symmetric(horizontal: 24),
margin: EdgeInsets.symmetric(horizontal: 24),
child: Row(children: [
Expanded(
child: TextField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search",
border: InputBorder.none,
),
),
),
GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => Search(
searchQuery: searchController.text,
)
));
},
child: Container(
child: Icon(Icons.search)),
)
],)
,),
SizedBox(height: 16,),
Build Category Grid
next is Build Category Grid now inside SingleChildScrollView
add this to Creating Grid Category
Container(
height: 80,
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 24),
itemCount: categories.length,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: ((context, index){
return CategoryTitle(
title: categories[index].categoriesName,
imgUrl: categories[index].imgUrl,
);
}),
),
),
SizedBox(height: 16,),
wallpaperList(wallpapers: wallpapers, context: context),
Create Category Title
to requests Image and Handling title in the category grid, we Need to Request From API now create a class named CategoryTitle
extend with StatelessWidget
class CategoryTitle extends StatelessWidget {
// image url
final String? title, imgUrl;
// initialize using constructor
CategoryTitle({@required this.imgUrl, @required this.title});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => Categories(categoryName: title!.toLowerCase()),
));
},
child: Container(
margin: EdgeInsets.only(right: 4),
child: Stack(children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(imgUrl!, height: 50, width: 100, fit: BoxFit.cover,)),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
// color: Colors.black26,
),
height: 50,
width: 100,
alignment: Alignment.center,
child: Text(
title!,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 16,
),),)
],),
),
);
}
}
now the Home()
the view is Complete but has many errors because we not already create other views and fetch category image for this,
Design Model
to initialize category and wallpaper on home views we need to define a model first create category_model
and wallpaper_model
Initialize Category Model
initialize Category Model in different file create directory call model
and create categories_model.dart
and initialize the model
// model/category_model.dart
class CategoriesModel {
String? categoriesName;
String? imgUrl;
}
Initialize Wallpaper Model
after define CategoryModel
, define WallpaperModel
// model/wallpaper_model.dart
// wallpaper identity model
class WallpaperModel {
String? photographer;
String? photographerUrl;
int? photographerId;
// access keys map
SrcModel? src;
// create name parameter
WallpaperModel({
this.src,
this.photographerUrl,
this.photographerId,
this.photographer,
});
// passing json value from API
factory WallpaperModel.fromMap(Map<String, dynamic> jsonData){
return WallpaperModel(
src: SrcModel.fromMap(jsonData['src']),
photographerUrl: jsonData["photographer_url"],
photographerId: jsonData["photographer_id"],
photographer: jsonData["photographer"],
);
}
}
// wallpaper Source Map Model
class SrcModel {
String original;
String small;
String portrait;
// create name parameter
SrcModel({
required this.original,
required this.small,
required this.portrait,
});
// passing json value from API
factory SrcModel.fromMap(Map<String, dynamic> jsonData){
return SrcModel(
portrait: jsonData["portrait"],
original: jsonData["original"],
small: jsonData["small"],
);
}
}
In this Model we Parsing Data From API using a factory constructor
let’s look at JSON Format in an API Response
{"page": 1,"per_page": 1,"photos": [{"id": 7362829,"width": 4000,"height": 6000,"url": "https://www.pexels.com/photo/wood-light-dawn-landscape-7362829/","photographer": "Bayu Samudro","photographer_url": "https://www.pexels.com/@bayusamudro","photographer_id": 35776645,"avg_color": "#323434","src": {"original": "https://images.pexels.com/photos/7362829/pexels-photo-7362829.jpeg","large2x": "https://images.pexels.com/photos/7362829/pexels-photo-7362829.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940","large": "https://images.pexels.com/photos/7362829/pexels-photo-7362829.jpeg?auto=compress&cs=tinysrgb&h=650&w=940","medium": "https://images.pexels.com/photos/7362829/pexels-photo-7362829.jpeg?auto=compress&cs=tinysrgb&h=350","small": "https://images.pexels.com/photos/7362829/pexels-photo-7362829.jpeg?auto=compress&cs=tinysrgb&h=130","portrait": "https://images.pexels.com/photos/7362829/pexels-photo-7362829.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=1200&w=800","landscape": "https://images.pexels.com/photos/7362829/pexels-photo-7362829.jpeg?auto=compress&cs=tinysrgb&fit=crop&h=627&w=1200","tiny": "https://images.pexels.com/photos/7362829/pexels-photo-7362829.jpeg?auto=compress&cs=tinysrgb&dpr=1&fit=crop&h=200&w=280"},"liked": false}],"total_results": 8000,"next_page": "https://api.pexels.com/v1/curated/?page=2&per_page=1"}
after look the sample response from API now we will create a factory function to parse photos
value from API
// passing json value from API
factory WallpaperModel.fromMap(Map<String, dynamic> jsonData){
return WallpaperModel(
src: SrcModel.fromMap(jsonData['src']),
photographerUrl: jsonData["photographer_url"],
photographerId: jsonData["photographer_id"],
photographer: jsonData["photographer"],
);
}
}
after we Parse From photos
we need access tosrc
and access these keys
- portrait
- small
- original
// passing json value from API
factory SrcModel.fromMap(Map<String, dynamic> jsonData){
return SrcModel(
portrait: jsonData["portrait"],
original: jsonData["original"],
small: jsonData["small"],
);
}
now wallpaper_model will be like this
// wallpaper identity model
class WallpaperModel {
String? photographer;
String? photographerUrl;
int? photographerId;
// access keys map
SrcModel? src;
// create name parameter
WallpaperModel({
this.src,
this.photographerUrl,
this.photographerId,
this.photographer,
});
// passing json value from API
factory WallpaperModel.fromMap(Map<String, dynamic> jsonData){
return WallpaperModel(
src: SrcModel.fromMap(jsonData['src']),
photographerUrl: jsonData["photographer_url"],
photographerId: jsonData["photographer_id"],
photographer: jsonData["photographer"],
);
}
}
// wallpaper Source Map Model
class SrcModel {
String original;
String small;
String portrait;
// create name parameter
SrcModel({
required this.original,
required this.small,
required this.portrait,
});
// passing json value from API
factory SrcModel.fromMap(Map<String, dynamic> jsonData){
return SrcModel(
portrait: jsonData["portrait"],
original: jsonData["original"],
small: jsonData["small"],
);
}
}
and after define the model create a function to get category Model
Get Category Image Model
to get an image in the category grid we need to request that from API, to handle this problem we need to Create a Function to Handle the Category Model, create a new directory call data
and create data.dart
and handling the problem
// data/data.dart
import 'package:wallpaperapps/model/categories_model.dart';
// api keys
String apiKey = "563492ad6f9170000100000174dda4707e934bc58524e21b8e440b15";
List <CategoriesModel> getCategories(){
List <CategoriesModel> categories = [];
CategoriesModel categoryModel = new CategoriesModel();
// define Category
// Street Art
categoryModel.imgUrl = "https://images.pexels.com/photos/908713/pexels-photo-908713.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500";
categoryModel.categoriesName = "Street Art";
categories.add(categoryModel);
categoryModel = new CategoriesModel();
// Wild Live
categoryModel.imgUrl = "https://images.pexels.com/photos/704320/pexels-photo-704320.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500";
categoryModel.categoriesName = "Wild Live";
categories.add(categoryModel);
categoryModel = new CategoriesModel();
// Nature
categoryModel.imgUrl = "https://images.pexels.com/photos/34950/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=2&w=500";
categoryModel.categoriesName = "Nature";
categories.add(categoryModel);
categoryModel = new CategoriesModel();
// city
categoryModel.imgUrl = "https://images.pexels.com/photos/466685/pexels-photo-466685.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500";
categoryModel.categoriesName = "City";
categories.add(categoryModel);
categoryModel = new CategoriesModel();
// motivation
categoryModel.imgUrl = "https://images.pexels.com/photos/3806690/pexels-photo-3806690.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500";
categoryModel.categoriesName = "Motivation";
categories.add(categoryModel);
categoryModel = new CategoriesModel();
// bikes
categoryModel.imgUrl = "https://images.pexels.com/photos/289869/pexels-photo-289869.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500";
categoryModel.categoriesName = "Bikes";
categories.add(categoryModel);
categoryModel = new CategoriesModel();
// cars
categoryModel.imgUrl = "https://images.pexels.com/photos/289869/pexels-photo-289869.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500";
categoryModel.categoriesName = "Cars";
categories.add(categoryModel);
categoryModel = new CategoriesModel();
// return value
return categories;
}
and after complete creating categories_model creating the widget for category
Build Category Widget Views
to fix errors on the home view we need to create a categories widget view after that import the widget to home.dart
let’s create categories.dart
inside views
directory.
mport 'dart:convert';
import 'package:flutter/material.dart';
import 'package:wallpaperapps/data/data.dart';
import 'package:wallpaperapps/model/wallpaper_model.dart';
import 'package:http/http.dart' as http;
import 'package:wallpaperapps/widgets/widget.dart';
class Categories extends StatefulWidget {
// passing category name
final String categoryName;
Categories({required this.categoryName});
@override
_CategoriesState createState() => _CategoriesState();
}
class _CategoriesState extends State<Categories> {
// list wallpaper
List <WallpaperModel> wallpapers = [];
// fetch data
// fetching Search Photo from API
searchPhotos(String query) async {
var url = Uri.parse("https://api.pexels.com/v1/search?query=$query&per_page=20");
var response = await http.get(url,
headers: {
"Authorization":apiKey
});
// print(response.body.toString());
// parsing data from API (Json)
Map<String, dynamic> jsonData = jsonDecode(response.body);
// parsing data
jsonData["photos"].forEach((element){
// print(element); // dev mode
// getting data
WallpaperModel wallpaperModel = new WallpaperModel();
wallpaperModel = WallpaperModel.fromMap(element);
wallpapers.add(wallpaperModel);
});
// set state
setState(() {});
}
@override
void initState() {
// TODO: implement initState
searchPhotos(widget.categoryName);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: brandName(),
elevation: 0.0,
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget> [
SizedBox(height: 16,),
wallpaperList(wallpapers: wallpapers, context: context),
],),
),
),
);
}
}
install http to handling HTTP requests using pub, then fetching category image from pexels API
Build Search Widget Views
and if we looking again search function in home.dart
have many errors because we, not already creating Search Widget, create search.dart
inside views
directory
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:wallpaperapps/data/data.dart';
import 'package:wallpaperapps/model/wallpaper_model.dart';
import 'package:wallpaperapps/widgets/widget.dart';
import 'package:http/http.dart' as http;
// Search Query
class Search extends StatefulWidget {
// Search Query Input
final String searchQuery;
Search({required this.searchQuery});
@override
_SearchState createState() => _SearchState();
}
class _SearchState extends State<Search> {
// text controller
TextEditingController searchController = new TextEditingController();
// list wallpaper
List <WallpaperModel> wallpapers = [];
// fetch data
// fetching Search Photo from API
searchPhotos(String query) async {
var url = Uri.parse("https://api.pexels.com/v1/search?query=$query&per_page=20");
var response = await http.get(url,
headers: {
"Authorization":apiKey
});
// print(response.body.toString());
// parsing data from API (Json)
Map<String, dynamic> jsonData = jsonDecode(response.body);
// parsing data
jsonData["photos"].forEach((element){
// print(element); // dev mode
// getting data
WallpaperModel wallpaperModel = new WallpaperModel();
wallpaperModel = WallpaperModel.fromMap(element);
wallpapers.add(wallpaperModel);
});
// set state
setState(() {});
}
@override
void initState() {
// TODO: implement initState
searchPhotos(widget.searchQuery);
super.initState();
searchController.text = widget.searchQuery;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: brandName(),
elevation: 0.0,
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget> [
Container(
decoration: BoxDecoration(
color: Color(0xfff5f8fd),
borderRadius: BorderRadius.circular(30)
),
padding: EdgeInsets.symmetric(horizontal: 24),
margin: EdgeInsets.symmetric(horizontal: 24),
child: Row(children: [
Expanded(
child: TextField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search",
border: InputBorder.none,
),
),
),
GestureDetector(
onTap: (){
// passing query
searchPhotos(searchController.text);
},
child: Container(
child: Icon(Icons.search)),
)
],)
,),
wallpaperList(wallpapers: wallpapers, context: context),
],),
),
),
);
}
}
after create and handling search and category we need a class to handle wallpaper and image view on our apps, create a new View call image_view.dart
inside views
directory
// views/image_viewimport 'dart:io' as io;
import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';
import 'wallpaper_manager.dart';
// import 'package:wallpaperapps/views/wallpaper_manager.dart';
class ImageView extends StatefulWidget {
// pass image url
final String imgUrl;
ImageView({required this.imgUrl});
@override
_ImageViewState createState() => _ImageViewState();
}
class _ImageViewState extends State<ImageView> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: [
Hero(
tag: widget.imgUrl,
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Image.network(widget.imgUrl, fit: BoxFit.cover,)),
),
// set wallpaper button
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onTap: () {
// save image to photos directory
_save();
},
child: Stack(
children: [
Container(
height: 50,
decoration: BoxDecoration(
color: Color(0xff1C1B1B).withOpacity(0.8),
borderRadius: BorderRadius.circular(30)
),
width: MediaQuery.of(context).size.width/2,
),
Container(
height: 50,
width: MediaQuery.of(context).size.width/2,
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
decoration: BoxDecoration(
border: Border.all(color: Colors.white54, width: 1),
borderRadius: BorderRadius.circular(30),
gradient: LinearGradient(
colors: [
Color(0x36FFFFFF),
Color(0x0FFFFFFF)
]
)
),
child: Column(children: <Widget> [
Text("Set As Wallpaper", style: TextStyle(fontSize: 16, color: Colors.white70),),
Text("Image Will be Save at Galery", style: TextStyle(
fontSize: 10,
color: Colors.white70,
),)
],),
)
],
),
),
SizedBox(height: 16,),
// cancel vutton handler
GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Text("Cancel", style: TextStyle(color: Colors.white),)),
SizedBox(height: 50,)
],),
)
],),
);
}
}
in this view, if we click on an image it will appear in full screen
Set Image as Wallpaper and Save to Galery
to set images as wallpaper then saving to our gallery we need this packages
add to pubspect.yaml
and update the dependencies
after install the required packages create function to asking permission
// asking permission
_askPermission() async {
if (io.Platform.isIOS) {
var photosStatus = await Permission.photos.status;
if (photosStatus.isDenied) {
await Permission.photos.request();
print("Photos Permission Status" + photosStatus.toString());
}
} else {
var photoStatus = await Permission.photos.status;
var storageStatus = await Permission.storage.status;
if (storageStatus.isDenied) {
await Permission.storage.request().then((value) {
if (!value.isGranted) _askPermission();
});
print("Android Storage Permission Status: " + storageStatus.toString());
} else if (photoStatus.isDenied) {
await Permission.photos.request().then((value) {
if (!value.isGranted) _askPermission();
});
print("Android Photos Permission Status: " + photoStatus.toString());
}
// Map<Permission, PermissionStatus> statuses = await [Permission.storage].request();
// print(statuses[Permission.storage]);
}
}
and create a class to manage Wallpaper and Set Wallpaper into lock screen and home screen inside views
directory
// views/wallpaper_manager.dartimport 'dart:async';
import 'package:flutter/services.dart';
/// WallpaperManager plugin begins here
class WallpaperManager {
// Define channel
static const MethodChannel _channel = MethodChannel('wallpaper_manager');
/// Static code for Home Screen Wallpaper Choice
static const int HOME_SCREEN = 1;
/// Static code for Lock Screen Wallpaper Choice
static const int LOCK_SCREEN = 2;
/// Static code for both Home Screen and Lock Screen Wallpaper Choice
static const int BOTH_SCREENS = 3;
/// Function to check working/validity of method channels
static Future<String> get platformVersion async {
// String to store the version number before returning. This is just to test working/validity.
final version =
await _channel.invokeMethod<String>('getPlatformVersion') ?? '';
// Function returns version number
return version;
}
/// Function takes input file's path & location choice
static Future<String> setWallpaperFromFile(
String filePath, int wallpaperLocation) async {
// Variable to store operation result
final result = await _channel.invokeMethod<int>(
'setWallpaperFromFile',
{'filePath': filePath, 'wallpaperLocation': wallpaperLocation},
);
// Function returns the set String as result, use for debugging
return (result ?? 0) > 0 ? 'Wallpaper set' : 'There was an error.';
}
/// Function takes input file's path & location choice
static Future<String> setWallpaperFromFileWithCrop(String filePath,
int wallpaperLocation, int left, int top, int right, int bottom) async {
// Variable to store operation result
int? result;
if (left > right || top > bottom) {
result = 0;
} else {
result =
await _channel.invokeMethod<int>('setWallpaperFromFileWithCrop', {
'filePath': filePath,
'wallpaperLocation': wallpaperLocation,
'left': left,
'top': top,
'right': right,
'bottom': bottom
});
}
// Function returns the set String as result, use for debugging
return (result ?? 0) > 0 ? 'Wallpaper set' : 'There was an error.';
}
/// Function takes input file's asset (Dart/Flutter; pre-indexed in pubspec.yaml) & location choice
static Future<String> setWallpaperFromAsset(
String assetPath, int wallpaperLocation) async {
// Variable to store operation result
final result = await _channel.invokeMethod<int>(
'setWallpaperFromAsset',
{'assetPath': assetPath, 'wallpaperLocation': wallpaperLocation},
);
// Function returns the set String as result, use for debugging
return (result ?? 0) > 0 ? 'Wallpaper set' : 'There was an error.';
}
/// Function takes input file's asset (Dart/Flutter; pre-indexed in pubspec.yaml) & location choice
static Future<String> setWallpaperFromAssetWithCrop(String assetPath,
int wallpaperLocation, int left, int top, int right, int bottom) async {
// Variable to store operation result
int? result;
if (left > right || top > bottom || left < 0 || top < 0) {
result = 0;
} else {
result =
await _channel.invokeMethod<int>('setWallpaperFromAssetWithCrop', {
'assetPath': assetPath,
'wallpaperLocation': wallpaperLocation,
'left': left,
'top': top,
'right': right,
'bottom': bottom
});
}
// Function returns the set String as result, use for debugging
return (result ?? 0) > 0 ? 'Wallpaper set' : 'There was an error.';
}
}
and back to views/image_view.dart
and add function to set Wallpaper Image and Save to gallery
// saving image to gallery function
_save() async {
if (io.Platform.isAndroid){
await _askPermission();
}
var response = await Dio().get(
widget.imgUrl,
options: Options(responseType: ResponseType.bytes)
);
final result = await ImageGallerySaver.saveImage(Uint8List.fromList(response.data));
print(result);
print('default path: '+ result['filePath'].toString());
// set wallpaper to home Screen and LockScreem
// int lockScreenLocation = WallpaperManager.LOCK_SCREEN;
// int homeScreenLocation = WallpaperManager.HOME_SCREEN;
int bothScreenLocation = WallpaperManager.BOTH_SCREENS;
// set path image
final imagePath = result['filePath'].toString().replaceAll(RegExp('file://'), '');
// setting wallpaper
String setBoth;
// String setLockScreen;
// String setHomeScreen;
try {
// setLockScreen = await WallpaperManager.setWallpaperFromFile(imagePath, lockScreenLocation);
// setHomeScreen = await WallpaperManager.setWallpaperFromFile(imagePath, homeScreenLocation);
setBoth = await WallpaperManager.setWallpaperFromFile(imagePath, bothScreenLocation);
// print status to console
print(setBoth);
// print(setHomeScreen);
} on PlatformException {
// setLockScreen = "Failed To Set Wallpaper in LockScreen";
// setHomeScreen = "Failed to Set Wallpaper in HomeScreen";
setBoth = "Failed To Set Wallpaper in Both";
}
if (!mounted) {
return;
}
Navigator.pop(context);
}
Updating Home Views
after creating the models, views, and data adding that to home.dart
inside views
directory
// update views/home.dartimport 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:wallpaperapps/data/data.dart';
import 'package:wallpaperapps/model/categories_model.dart';
import 'package:wallpaperapps/model/wallpaper_model.dart';
import 'package:wallpaperapps/views/categories.dart';
import 'package:wallpaperapps/views/search.dart';
import 'package:wallpaperapps/widgets/widget.dart';
import 'package:http/http.dart' as http;
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
// fetch data
// fetching curated photo from API
getCuratedPhotos() async {
var url = Uri.parse("https://api.pexels.com/v1/curated?per_page=20");
var response = await http.get(url,
headers: {
"Authorization":apiKey
});
// print(response.body.toString());
// parsing data from API (Json)
Map<String, dynamic> jsonData = jsonDecode(response.body);
// parsing data
jsonData["photos"].forEach((element){
// print(element); // dev mode
// getting data
WallpaperModel wallpaperModel = new WallpaperModel();
wallpaperModel = WallpaperModel.fromMap(element);
wallpapers.add(wallpaperModel);
// print(wallpapers.length); // dev mode
});
// set state
setState(() {});
}
List <CategoriesModel> categories = [];
List <WallpaperModel> wallpapers = [];
// text controller
TextEditingController searchController = new TextEditingController();
// initState
@override
void initState() {
getCuratedPhotos();
categories = getCategories();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white ,//Colors.white, custom: 0xFF2B4772
appBar: AppBar(
title: brandName(),
elevation: 0.0
),
body: SingleChildScrollView(
child: Container(child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Color(0xfff5f8fd), // default colors: 0xfff5f8fd, custom: 0xFF2B4772
borderRadius: BorderRadius.circular(30)
),
padding: EdgeInsets.symmetric(horizontal: 24),
margin: EdgeInsets.symmetric(horizontal: 24),
child: Row(children: [
Expanded(
child: TextField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search",
border: InputBorder.none,
),
),
),
GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => Search(
searchQuery: searchController.text,
)
));
},
child: Container(
child: Icon(Icons.search)),
)
],)
,),
SizedBox(height: 16,),
Container(
height: 80,
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 24),
itemCount: categories.length,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: ((context, index){
return CategoryTitle(
title: categories[index].categoriesName,
imgUrl: categories[index].imgUrl,
);
}),
),
),
SizedBox(height: 16,),
wallpaperList(wallpapers: wallpapers, context: context),
],),),
),
);
}
}
class CategoryTitle extends StatelessWidget {
// image url
final String? title, imgUrl;
// initialize using constructor
CategoryTitle({@required this.imgUrl, @required this.title});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => Categories(categoryName: title!.toLowerCase()),
));
},
child: Container(
margin: EdgeInsets.only(right: 4),
child: Stack(children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(imgUrl!, height: 50, width: 100, fit: BoxFit.cover,)),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
// color: Colors.black26,
),
height: 50,
width: 100,
alignment: Alignment.center,
child: Text(
title!,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 16,
),),)
],),
),
);
}
}
Update Android Manifest to handling Permission for User Access
after completing the application updating the Android Manifest, The manifest file describes essential information about your app to the Android build tools, the Android operating system, and Google Play.
<!-- Manifest -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" />
<application
android:requestLegacyExternalStorage="true"
then run the applications press Shift + 10
for android studio
okay until here the discussion this time may be useful and good luck,