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

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

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 .

Please bring the original link to reprint ,thank
Similar articles

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15

2021-09-15