You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:基于RevenueCat实现Flutter应用中免费与付费用户的差异化首页底部导航配置

Solution: Switch Home Screen Based on RevenueCat Entitlement Status

Got it, let's get your bottom navigation set up to dynamically switch between the free and paid home screens based on the user's subscription status. Here's the adjusted code with step-by-step explanations:

Step 1: Ensure RevenueCatProvider is Available in Your Widget Tree

First, make sure you wrap your app (or this bottom navigation widget) with a ChangeNotifierProvider so the entitlement state can be accessed across your widget tree. For example, in your main.dart:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'your_file_path_here.dart'; // Import your bottomNavi and RevenueCatProvider

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => RevenueCatProvider(),
      child: MyApp(),
    ),
  );
}

Step 2: Update the Bottom Navigation Widget to Listen to Entitlement Changes

Modify your _bottomNaviState to react to entitlement updates and dynamically serve the correct home screen:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:purchases_flutter/offerings_wrapper.dart';
import 'package:purchases_flutter/purchases_flutter.dart';
import 'home.dart';
import 'homefree.dart';
import 'list.dart'; // Don't forget to import your list widget
import 'account.dart'; // Don't forget to import your account widget

// Define your Entitlement enum clearly (matching your RevenueCat setup)
enum Entitlement {
  free,
  all_charts,
}

class bottomNavi extends StatefulWidget {
  bottomNavi({Key? key}) : super(key: key);

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

class _bottomNaviState extends State<bottomNavi> {
  int _selectedIndex = 0;
  static const TextStyle optionStyle = TextStyle(fontSize: 30, fontWeight: FontWeight.bold);

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    // Access the latest entitlement state from the provider
    final revenueCatProvider = Provider.of<RevenueCatProvider>(context);
    
    // Dynamically build the pages list based on current entitlement
    final _pages = <Widget>[
      revenueCatProvider.entitlement == Entitlement.all_charts 
          ? home() 
          : homeFree(),
      list(),
      account(),
    ];

    return Scaffold(
      body: Center(
        child: _pages.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.description),
            label: 'todo',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.account_box),
            label: 'Account',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

class RevenueCatProvider extends ChangeNotifier{
  RevenueCatProvider() {
    init();
  }

  Entitlement _entitlement = Entitlement.free;
  Entitlement get entitlement => _entitlement;

  Future init() async {
    // Don't forget to configure RevenueCat with your API key first!
    // await Purchases.configure(PurchasesConfiguration("YOUR_REVENUECAT_API_KEY"));
    
    // Listen for real-time purchase updates
    Purchases.addPurchaserInfoUpdateListener((purchaserInfo) {
      updatePurchaseStatus();
    });
    
    // Fetch initial entitlement status when the provider loads
    await updatePurchaseStatus();
  }

  Future updatePurchaseStatus() async {
    try {
      final purchaseInfo = await Purchases.getPurchaserInfo();
      final activeEntitlements = purchaseInfo.entitlements.active;
      
      // Check if the user has your paid entitlement (match this to your RevenueCat entitlement ID)
      if (activeEntitlements.containsKey('all_charts')) {
        _entitlement = Entitlement.all_charts;
      } else {
        _entitlement = Entitlement.free;
      }
      
      notifyListeners(); // Trigger widget rebuilds with the new state
    } catch (e) {
      print('Error checking subscription status: $e');
      _entitlement = Entitlement.free;
      notifyListeners();
    }
  }
}

Key Changes Explained:

  • Dynamic Page Generation: Instead of a fixed _pages list, we generate it inside the build method using the latest entitlement state. This ensures the home screen switches instantly when the user's subscription status changes.
  • Provider State Listening: Using Provider.of<RevenueCatProvider>(context) lets the widget react to entitlement updates automatically. When notifyListeners() is called in the provider, the widget rebuilds with the correct home screen.
  • Initial Status Check: Added await updatePurchaseStatus() in the provider's init method to fetch the user's current subscription status on app launch, not just when a purchase is made.
  • Error Handling: Added a try/catch block to handle any issues fetching purchaser info gracefully, falling back to the free state if something goes wrong.

Quick Reminders:

  • Replace YOUR_REVENUECAT_API_KEY with your actual API key from the RevenueCat dashboard.
  • Make sure your entitlement ID in activeEntitlements.containsKey('all_charts') matches exactly what you've set up in RevenueCat.
  • When a user completes a purchase, RevenueCat's listener will trigger updatePurchaseStatus, which updates the entitlement and triggers a widget rebuild to show the paid home screen.

内容的提问来源于stack exchange,提问作者akhicoda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 11:53:10