当前位置:网站首页>"Fluent live series" develops an app that can watch movies and TV dramas

"Fluent live series" develops an app that can watch movies and TV dramas

2021-09-15 07:45:46 Oil cake

Recently, I have time to pay attention to flutter Empty security upgrade , I also upgraded , Refactor what you wrote dart-cms-flutter project . The main use of flutter + getx, 《getx yyds》

I won't release and collect those data , Just handle it yourself . Here's just how to do it

Project address :Dart-Cms-Flutter

Project screenshots

 untitled -1.jpg

Screenshot_20210909-075322.png

Start with the home page

Due to the use of getx, therefore , The part of the home page needs to be changed , What needs to be mentioned here is ,getx A global injection controller is provided , Equivalent to global state , Very easy to use , Use GetxService, Here is an example

This is an example of collecting records ,

import 'package:get/get.dart';
import 'package:dart_cms_flutter/utils/storage.dart';
import 'package:dart_cms_flutter/interface/videoDetaill.dart';

//  Global response data 
class StoreService extends GetxService {
  //  Historical record 
  RxList<dynamic> storeList = [].obs;

  Future<StoreService> init() async {
    List<Map<String, dynamic>> storeData =
        List.from(StorageUtil().getJSON("store") ?? []);
    storeList.addAll(storeData);
    return this;
  }

  Future<bool> add<T extends VideoDetaillInterFace>(
    T obj,
  ) async {
    //  Insert a new 
    String newKey = obj.Id!;
    //  Check for presence 
    bool isExist = storeList.any((el) => el["Id"] == newKey);
    //  Whether the limit is exceeded 50 Storage quota ,  And this video is not in the current history 
    if (storeList.length >= 50 && !isExist) {
      storeList.removeLast();
    }
    //  Current id Does it already exist 
    if (isExist) {
      //  Delete if it exists , reinsert , Change position , Insert to the front 
      storeList.removeWhere((el) => el["Id"] == newKey);
    }
    //  Current video data  formant
    Map<String, dynamic> curVideoMap = _formantVideoDetaill(
      obj,
    );
    //  Insert a new 
    storeList.insert(0, curVideoMap);
    //  Deposit in 
    // ignore: invalid_use_of_protected_member
    return StorageUtil().setJSON('store', storeList.value);
  }

  Future<bool> removeKey(String keyName) async {
    storeList.removeWhere((element) => true);
    return StorageUtil().remove(keyName);
  }

  Map<String, dynamic> _formantVideoDetaill<T extends VideoDetaillInterFace>(
    T obj,
  ) {
    return {
      "Id": obj.Id,
      "videoTitle": obj.videoTitle,
      "director": obj.director,
      "poster": obj.performer,
      "videoImage": obj.videoImage,
      "video_type": obj.videoType!.name,
      "video_rate": obj.videoRate,
      "update_time": obj.updateTime,
      "language": obj.language,
      "sub_region": obj.subRegion,
      "rel_time": obj.relTime,
      "introduce": obj.introduce,
      "remind_tip": obj.remindTip,
      "popular": obj.popular,
      "allow_reply": obj.allowReply,
      "display": obj.display,
      "scource_sort": obj.scourceSort,
    };
  }
}

Global Injection , So that the controller will not be recycled , The following is an example of injection

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // debugPaintSizeEnabled = true;
  await initStore();
  runApp(MyApp());
}

Future<void> initStore() async {
  //  initialization http request 
  HttpUtils().init(baseUrl: hostUrl);
  //  Initialize singleton mode 
  await StorageUtil().init();
  //  The history module is injected here 
  await Get.putAsync(() => HistoryService().init());
  //  Here, the collection record module is injected 
  await Get.putAsync(() => StoreService().init());
  print(" Global Injection ");
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      // designSize: Size(375, 812),
      builder: () => GetMaterialApp(
        debugShowCheckedModeBanner: false,
        initialRoute: PageName.HOME,
        getPages: PageRoutes.routes,
      ),
    );
  }
}

stay runapp Inject these required dependencies before , And singleton objects ,

home page , Article page , Category pages , Page part

The page is mainly statefullwdiget, however getx It provides us with a simple operation , That's it getview, Use getview We have some one-time request pages ( This means that there will be no drop-down refresh after the data appears ) Use getview It's very convenient , For example, the article page above me , Here is an example :


// view part 
class AppBarIndexView extends GetView<AppbarIndexViewStore>{

    @override
    Widget build(BuildContext context) {
        //  Here's the injection controller 
        AppbarIndexViewStore controller = Get.put(AppbarIndexViewStore());
        return controller.obx(
            //  Here is the content of success 
            (state) => Widget,
            //  Here is loading The content of the time 
            onLoading: widget,
            //  Here is the content when the data is empty 
            onEmpty: widget,
            //  Here's what happens when you fail 
            onError: widget,
        )
    }
}

//  Controller part 
class AppbarIndexViewStore extends GetxController with SingleGetTickerProviderMixin,StateMixin {

    initEvent(){
        //  Change state , call change Method 
        change(" Failure ", status: RxStatus.error());
        change(" success ", status: RxStatus.success());
        change(" Loading ", status: RxStatus.loading());
    }

    @override
    void onInit() {
        super.onInit();
        //  Initialization controls what to run 
        initEvent();
    }
}

A key part , Video player

flutter Video player , I sent a water post , You can see ,flutter The player you can find right now , such as chewie,betterplayer, These don't slide fast forward, slide up and down, change the volume and screen brightness . So if you want to use it out of the box , And satisfy yourself , It is difficult to . According to my observation for a long time . If you're a little garbage front end like me ( Big waste ). Then you'd better be based on fijkplayer.

Speaking of fijkplayer, You have to mention , I based on fijkplayer Developed skin , stay fijkplayer Developed on the basis of the author's skin , Added gesture sliding up and down to change volume and screen brightness , Slide left and right, fast forward and fast backward . Project address :fijkplayer_skin

The effect is the effect of the screenshot above

Here we will focus on adding functions to the playing skin ,

Fast forward and fast backward to achieve

Fast forward, fast backward , To put it bluntly, it is to judge the distance between the current point and the point when the screen is pressed when detecting sliding , The easiest way is > Greater than just +1, Less than -1, Here's my implementation . This is just the function part ,ui part , You need to write your own layout , If you don't want to write, you can copy my skin

_onHorizontalDragStart(detills) {
    setState(() {
      //  The position of the current point exists when pressing 
      updatePrevDx = detills.globalPosition.dx;
      updatePosX = _currentPos.inSeconds;
    });
  }

  _onHorizontalDragUpdate(detills) {
    double curDragDx = detills.globalPosition.dx;
    //  Determine whether the current is forward or backward 
    int cdx = curDragDx.toInt();
    int pdx = updatePrevDx!.toInt();
    bool isBefore = cdx > pdx;
    // + -,  dissatisfaction ,  Left and right sliding value ,> 1
    if (isBefore && cdx - pdx < 1 || !isBefore && pdx - cdx < 1) return null;

    int dragRange = isBefore ? updatePosX! + 1 : updatePosX! - 1;

    //  Overflow or not   Maximum 
    int lastSecond = _duration.inSeconds;
    if (dragRange >= _duration.inSeconds) {
      dragRange = lastSecond;
    }
    //  Overflow or not   Minimum 
    if (dragRange <= 0) {
      dragRange = 0;
    }
    //
    this.setState(() {
      _isHorizontalMove = true;
      _hideStuff = false;
      _isTouch = true;
      //  Update the next stored slide position 
      updatePrevDx = curDragDx;
      //  Update time 
      updatePosX = dragRange.toInt();
      _dargPos = Duration(seconds: updatePosX!.toInt());
    });
  }
  
  //  When you let go , That means no fighting , So go home , Go find your mother 
  _onHorizontalDragEnd(detills) {
    //  Here, set the updated location for the player , It's time 
    player.seekTo(_dargPos.inMilliseconds);
    this.setState(() {
      _isHorizontalMove = false;
      _isTouch = false;
      _hideStuff = true;
      _currentPos = _dargPos;
    });
  }
  

Sliding up and down is the same , With a little modification, you can complete . This concludes with some of the main points .

版权声明
本文为[Oil cake]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/09/20210909132240444C.html

随机推荐