android - How to remove black bars when using the front camera? - Stack Overflow

I am using the video_player package in Flutter to play videos, and when switching to fullscreen mode, I

I am using the video_player package in Flutter to play videos, and when switching to fullscreen mode, I see black bars on the sides or top and bottom. I want the video to fully fill the screen without these black bars, either by stretching or adjusting the aspect ratio properly:

What I have tried:

  • Using BoxFit.cover – This scales the video to fill the screen but sometimes crops part of it.

  • Using BoxFit.fill – This stretches the video but may distort it.

  • Printing video and screen dimensions – The video aspect ratio sometimes doesn’t match the screen’s aspect ratio, leading to black bars.

  • Toggling between fit modes – Implemented a toggle to switch between BoxFit.fill and BoxFit.contain, but black bars still appear in some cases.

This is my full screen video player:

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:flutter/services.dart';

class CustomVideoPlayer extends StatefulWidget {
  const CustomVideoPlayer({super.key});

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

class _CustomVideoPlayerState extends State<CustomVideoPlayer> {
  late VideoPlayerController _controller;
  bool isPlaying = false;
  bool isStretched = false;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.asset("assets/videos/sample.mp4")
      ..initialize().then((_) {
        setState(() {});
      });
  }

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

  void togglePlayPause() {
    setState(() {
      if (isPlaying) {
        _controller.pause();
      } else {
        _controller.play();
      }
      isPlaying = !isPlaying;
    });
  }

  void toggleStretch() {
    setState(() {
      isStretched = !isStretched;
    });
  }

  void toggleFullScreen() async {
    if (_controller.value.isPlaying) {
      _controller.pause();
    }

    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => FullScreenPlayer(controller: _controller, isStretched: isStretched),
      ),
    );

    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        _controller.value.isInitialized
            ? SizedBox(
          width: double.infinity,
          height: 250,
          child: FittedBox(
            fit: isStretched ? BoxFit.fill : BoxFit.cover,
            child: SizedBox(
              width: _controller.value.size.width,
              height: _controller.value.size.height,
              child: VideoPlayer(_controller),
            ),
          ),
        )
            : const CircularProgressIndicator(),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            IconButton(
              icon: Icon(isPlaying ? Icons.pause : Icons.play_arrow),
              onPressed: togglePlayPause,
            ),
            IconButton(
              icon: const Icon(Icons.fullscreen),
              onPressed: toggleFullScreen,
            ),
            IconButton(
              icon: Icon(isStretched ? Icons.aspect_ratio : Icons.fit_screen),
              onPressed: toggleStretch,
            ),
          ],
        ),
      ],
    );
  }
}

class FullScreenPlayer extends StatefulWidget {
  final VideoPlayerController controller;
  final bool isStretched;
  const FullScreenPlayer({super.key, required this.controller, required this.isStretched});

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

class _FullScreenPlayerState extends State<FullScreenPlayer> {
  @override
  void initState() {
    super.initState();
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.landscapeRight,
    ]);

    widget.controller.addListener(() {
      if (mounted) setState(() {});
    });

    widget.controller.play();
  }

  @override
  void dispose() {
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!widget.controller.value.isInitialized) {
      return const Scaffold(
        backgroundColor: Colors.black,
        body: Center(
          child: CircularProgressIndicator(color: Colors.white),
        ),
      );
    }

    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(
        children: [
          Center(
            child: FittedBox(
              fit: widget.isStretched ? BoxFit.fill : BoxFit.contain,
              child: SizedBox(
                width: MediaQuery.of(context).size.width,
                height: MediaQuery.of(context).size.height,
                child: VideoPlayer(widget.controller),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

This is my homepage:

import 'package:flutter/material.dart';
import 'package:livestream_project/pages/video_player/player_code.dart'; // Update the path

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: const Center(


        child: CustomVideoPlayer(),
      ),
    );
  }
}

This is my AndroidManifest.xml:

<manifest xmlns:android=";>
    <application
        android:label="livestream_project"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:taskAffinity=""
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
    <!-- Required to query activities that can process text, see:
          and
         .

         In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
    <queries>
        <intent>
            <action android:name="android.intent.action.PROCESS_TEXT"/>
            <data android:mimeType="text/plain"/>
        </intent>
    </queries>
</manifest>

This is my main.dart:

import 'package:flutter/material.dart';
import 'pages/homepage_page.dart'; // Import the HomePage

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Live Stream Player',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomePage(), // Set HomePage as the home screen
    );
  }
}

I am using the video_player package in Flutter to play videos, and when switching to fullscreen mode, I see black bars on the sides or top and bottom. I want the video to fully fill the screen without these black bars, either by stretching or adjusting the aspect ratio properly:

What I have tried:

  • Using BoxFit.cover – This scales the video to fill the screen but sometimes crops part of it.

  • Using BoxFit.fill – This stretches the video but may distort it.

  • Printing video and screen dimensions – The video aspect ratio sometimes doesn’t match the screen’s aspect ratio, leading to black bars.

  • Toggling between fit modes – Implemented a toggle to switch between BoxFit.fill and BoxFit.contain, but black bars still appear in some cases.

This is my full screen video player:

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:flutter/services.dart';

class CustomVideoPlayer extends StatefulWidget {
  const CustomVideoPlayer({super.key});

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

class _CustomVideoPlayerState extends State<CustomVideoPlayer> {
  late VideoPlayerController _controller;
  bool isPlaying = false;
  bool isStretched = false;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.asset("assets/videos/sample.mp4")
      ..initialize().then((_) {
        setState(() {});
      });
  }

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

  void togglePlayPause() {
    setState(() {
      if (isPlaying) {
        _controller.pause();
      } else {
        _controller.play();
      }
      isPlaying = !isPlaying;
    });
  }

  void toggleStretch() {
    setState(() {
      isStretched = !isStretched;
    });
  }

  void toggleFullScreen() async {
    if (_controller.value.isPlaying) {
      _controller.pause();
    }

    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => FullScreenPlayer(controller: _controller, isStretched: isStretched),
      ),
    );

    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        _controller.value.isInitialized
            ? SizedBox(
          width: double.infinity,
          height: 250,
          child: FittedBox(
            fit: isStretched ? BoxFit.fill : BoxFit.cover,
            child: SizedBox(
              width: _controller.value.size.width,
              height: _controller.value.size.height,
              child: VideoPlayer(_controller),
            ),
          ),
        )
            : const CircularProgressIndicator(),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            IconButton(
              icon: Icon(isPlaying ? Icons.pause : Icons.play_arrow),
              onPressed: togglePlayPause,
            ),
            IconButton(
              icon: const Icon(Icons.fullscreen),
              onPressed: toggleFullScreen,
            ),
            IconButton(
              icon: Icon(isStretched ? Icons.aspect_ratio : Icons.fit_screen),
              onPressed: toggleStretch,
            ),
          ],
        ),
      ],
    );
  }
}

class FullScreenPlayer extends StatefulWidget {
  final VideoPlayerController controller;
  final bool isStretched;
  const FullScreenPlayer({super.key, required this.controller, required this.isStretched});

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

class _FullScreenPlayerState extends State<FullScreenPlayer> {
  @override
  void initState() {
    super.initState();
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.landscapeRight,
    ]);

    widget.controller.addListener(() {
      if (mounted) setState(() {});
    });

    widget.controller.play();
  }

  @override
  void dispose() {
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
    ]);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!widget.controller.value.isInitialized) {
      return const Scaffold(
        backgroundColor: Colors.black,
        body: Center(
          child: CircularProgressIndicator(color: Colors.white),
        ),
      );
    }

    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(
        children: [
          Center(
            child: FittedBox(
              fit: widget.isStretched ? BoxFit.fill : BoxFit.contain,
              child: SizedBox(
                width: MediaQuery.of(context).size.width,
                height: MediaQuery.of(context).size.height,
                child: VideoPlayer(widget.controller),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

This is my homepage:

import 'package:flutter/material.dart';
import 'package:livestream_project/pages/video_player/player_code.dart'; // Update the path

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: const Center(


        child: CustomVideoPlayer(),
      ),
    );
  }
}

This is my AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android/apk/res/android">
    <application
        android:label="livestream_project"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:taskAffinity=""
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
    <!-- Required to query activities that can process text, see:
         https://developer.android/training/package-visibility and
         https://developer.android/reference/android/content/Intent#ACTION_PROCESS_TEXT.

         In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
    <queries>
        <intent>
            <action android:name="android.intent.action.PROCESS_TEXT"/>
            <data android:mimeType="text/plain"/>
        </intent>
    </queries>
</manifest>

This is my main.dart:

import 'package:flutter/material.dart';
import 'pages/homepage_page.dart'; // Import the HomePage

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Live Stream Player',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomePage(), // Set HomePage as the home screen
    );
  }
}
Share Improve this question edited Mar 22 at 8:33 tyg 16.6k4 gold badges37 silver badges49 bronze badges asked Mar 22 at 7:18 shubham goyalshubham goyal 1 2
  • What do you mean by "How to remove black bars when using the front camera?" It seems that the front camera has no relationship with your issue. – DevQt Commented Mar 22 at 9:39
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – DevQt Commented Mar 22 at 9:39
Add a comment  | 

1 Answer 1

Reset to default 0

I think it will depend on the aspect ratio of the original video.

You can't dodge the black bars without cropping in my opinion, for example if you have a 4:3 content displayed on a 16:9 screen, you will have black bars

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744322988a4568512.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信