Skip to content

Instantly share code, notes, and snippets.

@nooralibutt
Last active February 15, 2023 10:10
Show Gist options
  • Save nooralibutt/2504540c03e7ef76a92f1c2d46a55501 to your computer and use it in GitHub Desktop.
Save nooralibutt/2504540c03e7ef76a92f1c2d46a55501 to your computer and use it in GitHub Desktop.
Manager ratings with this gist

How to integrate rating manager

1. Installing plugins

2. Add rating_manager.dart class

3. Call this in your welcome or splash screen RatingManager.incrementAppLaunches();

4. if you are targeting app store then mention app store id static const appStoreId = 'your-app-store-id'; in rating manager

5. Usage

  • To show in app review on button or level end use RatingManager.tryShowingCustomInAppReview(context)
  • To show native platform provided dialog use RatingManager.tryShowingNativeInAppReview();
import 'package:flutter/material.dart';
import 'package:in_app_review/in_app_review.dart';
import 'package:shared_preferences/shared_preferences.dart';
class RateFloatingButton extends StatefulWidget {
const RateFloatingButton({
Key? key,
}) : super(key: key);
@override
_RateFloatingButtonState createState() => _RateFloatingButtonState();
}
class _RateFloatingButtonState extends State<RateFloatingButton>
with SingleTickerProviderStateMixin {
AnimationController? controller;
static const _shake = 12.0;
@override
void initState() {
super.initState();
if (RatingManager.isAlreadyRated) return;
controller = AnimationController(
duration: const Duration(milliseconds: 500), vsync: this);
Future.delayed(Duration(seconds: 2), () => controller?.forward(from: 0.0));
}
@override
void dispose() {
controller?.dispose();
controller = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
if (RatingManager.isAlreadyRated || controller == null)
return const SizedBox();
final Animation<double> offsetAnimation = Tween(begin: 0.0, end: _shake)
.chain(CurveTween(curve: Curves.elasticIn))
.animate(controller!)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller?.reverse();
}
});
final button = FloatingActionButton(
onPressed: () => RatingManager._showRatingDialog(context),
child: Icon(Icons.star, size: 30),
);
return AnimatedBuilder(
animation: offsetAnimation,
builder: (buildContext, child) {
return Container(
margin: const EdgeInsets.only(bottom: 50),
padding: EdgeInsets.only(
left: offsetAnimation.value + _shake,
right: _shake - offsetAnimation.value),
child: button,
);
});
}
}
class RatingManager {
static const appStoreId = 'your-app-store-id';
static const _keyAppLaunches = "appLaunches2";
static const _keyAlreadyRated = "rated2";
static SharedPreferences? _prefs;
static Future<void> _init() async =>
_prefs = await SharedPreferences.getInstance();
static bool get isAlreadyRated => _prefs?.getBool(_keyAlreadyRated) ?? false;
static void setAlreadyRated({bool rated = true}) =>
_prefs?.setBool(_keyAlreadyRated, rated);
static void incrementAppLaunches() async {
if (_prefs == null) await _init();
_prefs?.setInt(_keyAppLaunches, getAppLaunches() + 1);
}
static int getAppLaunches() => _prefs?.getInt(_keyAppLaunches) ?? 0;
static Future<bool> tryShowingCustomInAppReview(BuildContext context) async {
if (isAlreadyRated) return false;
final isSuccessful = await _showRatingDialog(context);
return isSuccessful == true;
}
static Future<bool?> _showRatingDialog(BuildContext context) {
return showDialog<bool>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
'App Review',
style: Theme.of(context)
.textTheme
.titleLarge!
.copyWith(color: Colors.white),
),
content: Text(
'If you like our app, would you like to rate us on play store?',
style: Theme.of(context)
.textTheme
.bodyLarge!
.copyWith(color: Colors.white),
),
actions: <Widget>[
TextButton(
child: Text(
'Later',
style: Theme.of(context)
.textTheme
.labelMedium!
.copyWith(color: Colors.redAccent),
),
onPressed: () => Navigator.of(context).pop(false),
),
TextButton(
child: Text('Rate Us'),
onPressed: () async {
await InAppReview.instance
.openStoreListing(appStoreId: appStoreId);
Navigator.of(context).pop(true);
setAlreadyRated();
},
),
],
);
},
);
}
static Future<bool> tryShowingNativeInAppReview() async {
// if launches are 3 then show in app review
if (getAppLaunches() % 3 == 0) {
final InAppReview inAppReview = InAppReview.instance;
if (await inAppReview.isAvailable()) {
inAppReview.requestReview();
return true;
}
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment