Commit 59be051d cgx

整理项目

1 个父辈 29f857b2
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="JOD-MV-Pim">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Sleep Coach Controller-->
<scene sceneID="mSr-VG-EoP">
<objects>
<viewController id="dDK-KA-sPQ" customClass="AISleepCoachController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="1eu-Nn-5E0">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="Pf1-fh-l6V"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
<navigationItem key="navigationItem" id="05K-ik-z2W"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8JB-OR-j2U" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2786" y="201"/>
</scene>
<!--AI睡眠教练-->
<scene sceneID="zZV-8x-0UY">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="JOD-MV-Pim" customClass="BaseNaviController" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="AI睡眠教练" image="aisleep" selectedImage="aisleep_selected" id="Il3-d5-iMT"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="IbM-gj-oZu">
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="dDK-KA-sPQ" kind="relationship" relationship="rootViewController" id="ACD-cx-BP7"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="hMf-jH-a0Q" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2021.7391304347827" y="200.89285714285714"/>
</scene>
</scenes>
<resources>
<image name="aisleep" width="25" height="25"/>
<image name="aisleep_selected" width="25" height="25"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
//
// AISleepCoachController.h
// DreamSleep
//
// Created by peter on 2022/4/1.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface AISleepCoachController : UIViewController
@end
NS_ASSUME_NONNULL_END
//
// RelaxTrainController.h
// DreamSleep
//
// Created by peter on 2022/6/1.
//
#import "DSBaseViewController.h"
NS_ASSUME_NONNULL_BEGIN
@protocol RelaxTrainControllerDelegate <NSObject>
/// 刷新AI睡眠教练页面
- (void)reloadAIPage;
@end
/// 放松训练、腹式呼吸法页面
@interface RelaxTrainController : DSBaseViewController
@property (nonatomic, weak) id<RelaxTrainControllerDelegate> refreshDelegate;
/// title和step参数
@property (nonatomic, strong) NSDictionary *params;
@end
NS_ASSUME_NONNULL_END
//
// RelaxTrainController.m
// DreamSleep
//
// Created by peter on 2022/6/1.
//
#import "RelaxTrainController.h"
#import "RelaxTrainRequestModel.h"
#import "RelaxBodyView.h"
@interface RelaxTrainController () <RelaxBodyViewDelegate, UIScrollViewDelegate>
@property (nonatomic, strong) UIImageView *bgIV;
@property (nonatomic, strong) UILabel *cusTitleLab;
@property (nonatomic, strong) NSArray *listArr;
@property (nonatomic, strong) UIScrollView *lucencyView;
@property (nonatomic, strong) RelaxBodyView *bodyView;
@end
@implementation RelaxTrainController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG);
[self.view addSubview:self.bgIV];
[self.view addSubview:self.lucencyView];
[self.lucencyView addSubview:self.bodyView];
[self.view addSubview:self.dsNaviBar];
[self.view addSubview:self.dkBackBtn];
[self.dkBackBtn dk_setImage:DKImagePickerWithNames(@"cus_back_icon", @"cus_back_icon", @"dk_cus_back_icon") forState:UIControlStateNormal];
[self.view addSubview:self.cusTitleLab];
CGFloat iv_h = kScreenWidth*1233/1125.0;
[self.bgIV mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.equalTo(self.view);
make.height.equalTo(@(iv_h));
}];
[self.cusTitleLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.dsNaviBar);
make.bottom.equalTo(self.dsNaviBar).offset(-9);
}];
[self.lucencyView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.bottom.equalTo(self.view);
}];
[RelaxTrainRequestModel queryRelaxAudioListWithCompletion:^(RelaxTrainRequestModel * _Nonnull requestModel) {
if (requestModel.resCode == DSResCodeSuccess) {
if (requestModel.trainAudioList.count) {
self.listArr = requestModel.trainAudioList;
if (self.listArr && self.listArr.count > 0) {
NSInteger currentIndex = [self getIndexWithListData:self.listArr];
[self.bodyView refreshData:self.listArr currentIndex:currentIndex];
}
}
}
}];
[[NSNotificationCenter defaultCenter] postNotificationName:NeedPauseAllNoise object:nil];
[DataStatisticsUtil event:RelaxTrain attributes:@{@"data":@"腹式放松法页面"}];
}
#pragma mark - 根据title匹配下标索引
- (NSInteger)getIndexWithListData:(NSArray *)listData {
__block NSInteger currentIndex = 0;
NSString *title = self.params[@"title"];
// 放松音频随机选一个
if ([title isEqualToString:@"练习放松训练"]) {
currentIndex = arc4random() % listData.count;
} else {
[listData enumerateObjectsUsingBlock:^(RelaxTrainModel * obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj.audio_name containsString:title]) {
currentIndex = idx;
*stop = YES;
}
}];
}
return currentIndex;
}
#pragma mark - Actions
- (void)backAction {
[super backAction];
[self.bodyView stopAudio];
if (self.refreshDelegate && [self.refreshDelegate respondsToSelector:@selector(reloadAIPage)]) {
[self.refreshDelegate reloadAIPage];
}
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - RelaxBodyViewDelegate
- (void)updateNaviTitleAndBgImg:(RelaxTrainModel *)trainModel {
[self.bgIV setImageWithURL:[NSURL URLWithString:trainModel.bg_url] placeholderImage:[UIImage imageNamed:@"basicPlaceholder"]];
self.cusTitleLab.text = trainModel.audio_name;
self.titleLab.text = trainModel.audio_name;
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView*)scrollView {
CGFloat offset = scrollView.contentOffset.y;
if (offset >= self.lucencyView.contentSize.height - kScreenHeight) {
self.dkBackBtn.hidden = YES;
self.dsNaviBar.alpha = 1;
self.titleLab.hidden = NO;
self.cusTitleLab.hidden = YES;
self.isNeedUpdateStatusBarStyle = YES;
}
if (offset <= 0) {
self.dkBackBtn.hidden = NO;
self.dsNaviBar.alpha = 0;
self.titleLab.hidden = YES;
self.cusTitleLab.hidden = NO;
self.isNeedUpdateStatusBarStyle = NO;
}
}
#pragma mark - lazy
- (UIImageView *)bgIV {
if (!_bgIV) {
_bgIV = [UIImageView new];
}
return _bgIV;
}
- (UILabel *)cusTitleLab {
if (!_cusTitleLab) {
_cusTitleLab = [UILabel labWithTextColor:MainTextColor font:BoldFont(18)];
_cusTitleLab.textAlignment = NSTextAlignmentCenter;
}
return _cusTitleLab;
}
- (NSArray *)listArr {
if (!_listArr) {
_listArr = [NSArray array];
}
return _listArr;
}
- (UIScrollView *)lucencyView {
if (!_lucencyView) {
_lucencyView = [UIScrollView new];
_lucencyView.showsVerticalScrollIndicator = NO;
_lucencyView.delegate = self;
CGFloat bodyTopMargin = 351;
CGFloat bodyH = 420 + Bottom_SafeArea_Height;
_lucencyView.contentSize = CGSizeMake(kScreenWidth, bodyH + bodyTopMargin);
_lucencyView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
return _lucencyView;
}
- (RelaxBodyView *)bodyView {
if (!_bodyView) {
_bodyView = [[RelaxBodyView alloc] initWithFrame:CGRectMake(0, 351, kScreenWidth, 420 + Bottom_SafeArea_Height)];
_bodyView.delegate = self;
_bodyView.updateParams = self.params;
}
return _bodyView;
}
#pragma mark - 设置状态栏文字颜色(重写父类)
- (UIStatusBarStyle)preferredStatusBarStyle {
if (self.isNeedUpdateStatusBarStyle) {
return UIStatusBarStyleLightContent;
}
return UIStatusBarStyleDefault;
}
@end
//
// RelaxTrainModel.h
// DreamSleep
//
// Created by peter on 2022/6/2.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// 放松训练数据model
@interface RelaxTrainModel : NSObject
/// 音频id
@property (nonatomic, assign) int audio_id;
/// 播放背景图
@property (nonatomic, copy) NSString *bg_url;
/// 音频封面
@property (nonatomic, copy) NSString *audio_img;
/// 音频名称
@property (nonatomic, copy) NSString *audio_name;
/// 音频播放链接
@property (nonatomic, copy) NSString *audio_url;
/// 是否推荐(1:推荐,0:不推荐)
@property (nonatomic, copy) NSString *is_recommend;
/// 描述信息
@property (nonatomic, copy) NSString *audio_desc;
@end
NS_ASSUME_NONNULL_END
//
// RelaxTrainModel.m
// DreamSleep
//
// Created by peter on 2022/6/2.
//
#import "RelaxTrainModel.h"
@implementation RelaxTrainModel
+ (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper {
return @{@"audio_id" : @"id"};
}
@end
//
// RelaxTrainRequestModel.h
// DreamSleep
//
// Created by peter on 2022/6/2.
//
#import "DSNetworkTool.h"
#import "RelaxTrainModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface RelaxTrainRequestModel : DSNetworkTool
/// 训练音频列表
@property (nonatomic, strong) NSArray *trainAudioList;
/// 获取放松音频列表数据
/// @param completion completion
+ (NSURLSessionDataTask *)queryRelaxAudioListWithCompletion:(void (^)(RelaxTrainRequestModel *requestModel))completion;
/// 睡眠-AI教练任务更新操作步骤接口
/// @param params @{@"title":xxx, @"step":xxx}
/// @param completion completion
+ (NSURLSessionDataTask *)userCurTaskStateWithParams:(NSDictionary *)params completion:(void (^)(RelaxTrainRequestModel *requestModel))completion;
@end
NS_ASSUME_NONNULL_END
//
// RelaxTrainRequestModel.m
// DreamSleep
//
// Created by peter on 2022/6/2.
//
#import "RelaxTrainRequestModel.h"
@implementation RelaxTrainRequestModel
+ (NSURLSessionDataTask *)queryRelaxAudioListWithCompletion:(void (^)(RelaxTrainRequestModel *requestModel))completion {
RelaxTrainRequestModel * requestModel = [[RelaxTrainRequestModel alloc] init];
NSString *api = @"query_relax_audio_list";
NSString *argStr = [NSString stringWithFormat:@"query{%@}", api];
return [self httpPostBodyRequestWithAPI:api params:@{@"query" : argStr} view:nil hasNetActivity:YES loadingInfo:nil hasFailInfo:YES success:^(NSDictionary * _Nonnull apiDic) {
DSLog(@"获取放松音频列表数据接口apiDic:%@", apiDic);
requestModel.resCode = DSResCodeSuccess;
NSArray *resultArr = apiDic[@"result"];
NSMutableArray *tmpArr = [NSMutableArray array];
for (NSDictionary *audioDic in resultArr) {
RelaxTrainModel *trainModel = [RelaxTrainModel yy_modelWithDictionary:audioDic];
[tmpArr addObject:trainModel];
}
requestModel.trainAudioList = [tmpArr copy];
completion(requestModel);
} failure:^(id _Nonnull failureInfo) {
requestModel.resCode = [failureInfo[@"errorCode"] integerValue];
requestModel.errMessage = failureInfo[@"errMessage"];
completion(requestModel);
}];
}
+ (NSURLSessionDataTask *)userCurTaskStateWithParams:(NSDictionary *)params completion:(void (^)(RelaxTrainRequestModel *requestModel))completion {
RelaxTrainRequestModel * requestModel = [[RelaxTrainRequestModel alloc] init];
NSString *api = @"user_cur_task_state";
NSString *title = params[@"title"];
int step = [params[@"step"] intValue];
NSString *argStr = [NSString stringWithFormat:@"mutation{%@(title:\"%@\",step:%d)}", api, title, step];
return [self httpPostBodyRequestWithAPI:api params:@{@"query" : argStr} view:nil hasNetActivity:YES loadingInfo:nil hasFailInfo:YES success:^(NSDictionary * _Nonnull apiDic) {
DSLog(@"睡眠-AI教练任务更新操作步骤接口apiDic:%@", apiDic);
requestModel.resCode = DSResCodeSuccess;
completion(requestModel);
} failure:^(id _Nonnull failureInfo) {
requestModel.resCode = [failureInfo[@"errorCode"] integerValue];
requestModel.errMessage = failureInfo[@"errMessage"];
completion(requestModel);
}];
}
@end
//
// RelaxBodyView.h
// DreamSleep
//
// Created by peter on 2022/6/6.
//
#import <UIKit/UIKit.h>
#import "RelaxTrainModel.h"
NS_ASSUME_NONNULL_BEGIN
@protocol RelaxBodyViewDelegate <NSObject>
- (void)updateNaviTitleAndBgImg:(RelaxTrainModel *)trainModel;
@end
/// 放松body主视图
@interface RelaxBodyView : UIView
@property (nonatomic, weak) id<RelaxBodyViewDelegate> delegate;
- (void)refreshData:(NSArray *)listArr currentIndex:(NSInteger)index;
/// title和step参数
@property (nonatomic, strong) NSDictionary *updateParams;
/// 页面退出时停止音频播放
- (void)stopAudio;
@end
NS_ASSUME_NONNULL_END
//
// RelaxBodyView.m
// DreamSleep
//
// Created by peter on 2022/6/6.
//
#import "RelaxBodyView.h"
#import "RelaxTrainModel.h"
#import <FSAudioController.h>
#import "RelaxTrainCell.h"
#import "RelaxTrainRequestModel.h"
#import "DSSlider.h"
@interface RelaxBodyView () <UIGestureRecognizerDelegate, UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) UIButton *playerBtn;
@property (nonatomic, strong) UILabel *titleLab;
@property (nonatomic, strong) DSSlider *sliderView;
@property (nonatomic, strong) UILabel *proLeftLb;
@property (nonatomic, strong) UILabel *proRightLb;
@property (nonatomic, strong) UILabel *tipsLab;
@property (nonatomic, strong) FSAudioStream *audioStream;
@property (nonatomic, strong) CADisplayLink *progressTimer;
@property (nonatomic, assign) BOOL isDraging;
@property (nonatomic, assign) FSAudioStreamState streamState;
@property (nonatomic, strong) UIView *relaxRecView;
@property (nonatomic, strong) UICollectionView *relaxCollectionView;
@property (nonatomic, strong) NSArray *relaxList;
@property (nonatomic, assign) NSInteger curIndex;
@property (nonatomic, assign) BOOL isUpdateTask;
@end
@implementation RelaxBodyView {
UITapGestureRecognizer *_tapGesture;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.curIndex = 0;
self.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG);
self.layer.cornerRadius = 26.0;
self.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner;
[self addSubview:self.playerBtn];
[self addSubview:self.titleLab];
[self addSubview:self.sliderView];
[self addSubview:self.proLeftLb];
[self addSubview:self.proRightLb];
[self addSubview:self.tipsLab];
[self addSubview:self.relaxRecView];
[self addSubview:self.relaxCollectionView];
[self.playerBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self).offset(-45);
make.top.equalTo(self).offset(-35);
}];
[self.titleLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self).offset(15);
make.top.equalTo(self).offset(40);
}];
[self.sliderView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.mas_left).offset(38);
make.right.equalTo(self.mas_right).offset(-37);
make.height.equalTo(@15);
make.top.equalTo(self.titleLab.mas_bottom).offset(11);
}];
[self.proLeftLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.sliderView.mas_left);
make.top.equalTo(self.sliderView.mas_bottom).offset(6);
make.height.equalTo(@17);
make.width.equalTo(@100);
}];
[self.proRightLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.sliderView.mas_right);
make.top.equalTo(self.sliderView.mas_bottom).offset(6);
make.height.equalTo(@17);
make.width.equalTo(@100);
}];
[self.tipsLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.mas_left).offset(15);
make.right.equalTo(self.mas_right).offset(-15);
make.top.equalTo(self.sliderView.mas_bottom).offset(43);
}];
[self.relaxRecView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self).offset(15);
make.right.equalTo(self).offset(-15);
make.top.equalTo(self.tipsLab.mas_bottom).offset(24);
make.height.equalTo(@22);
}];
[self.relaxCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.relaxRecView.mas_bottom).offset(17);
make.left.equalTo(self.relaxRecView);
make.right.equalTo(self);
make.bottom.equalTo(self).offset(-Bottom_SafeArea_Height);
}];
self.progressTimer = [CADisplayLink displayLinkWithTarget:[TimerProxy proxyWithTarget:self] selector:@selector(updateProgress)];
[self.progressTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
return self;
}
- (void)dealloc {
[self.progressTimer invalidate];
self.progressTimer = nil;
}
- (void)playControlAction:(UIButton *)sender {
if (self.streamState == kFsAudioStreamStopped || self.streamState == kFsAudioStreamRetrievingURL) {
[self.audioStream play];
} else if (self.streamState == kFsAudioStreamPlaying) {
// 暂停播放
[self.audioStream pause];
} else if (self.streamState == kFsAudioStreamPaused) {
// 恢复播放
[self.audioStream pause];
}
}
#pragma mark - 解决按钮超出父视图区域无法点击
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if (view == nil) {
CGPoint tempPoint = [self.playerBtn convertPoint:point fromView:self];
// 判断点击的点是否在按钮区域内
if (CGRectContainsPoint(self.playerBtn.bounds, tempPoint)) {
//返回按钮
return self.playerBtn;
}
}
return view;
}
- (void)updateProgress {
if (self.isDraging == YES) return;
FSStreamPosition cur = self.audioStream.currentTimePlayed;
FSStreamPosition end = self.audioStream.duration;
// 更新音频播放进度、音频当前播放时间、音频总时间
self.sliderView.value = cur.position;
self.proLeftLb.text = [NSString stringWithFormat:@"%02i:%02i", cur.minute, cur.second];
self.proRightLb.text = [NSString stringWithFormat:@"%02i:%02i", end.minute, end.second];
}
- (void)refreshData:(NSArray *)listArr currentIndex:(NSInteger)index {
if (listArr.count && index < listArr.count) {
self.curIndex = index;
RelaxTrainModel *relaxModel = listArr[index];
[self refreshTopData:relaxModel isStartPlay:NO];
self.relaxList = listArr;
[self.relaxCollectionView reloadData];
}
}
- (void)stopAudio {
if (self.streamState == kFsAudioStreamPlaying) {
[self.audioStream pause];
}
[self.audioStream stop];
}
- (void)refreshTopData:(RelaxTrainModel *)relaxModel isStartPlay:(BOOL)isStartPlay {
if (self.delegate && [self.delegate respondsToSelector:@selector(updateNaviTitleAndBgImg:)]) {
[self.delegate updateNaviTitleAndBgImg:relaxModel];
}
self.titleLab.text = relaxModel.audio_name;
NSString *audio_desc = [[NSString stringWithFormat:@"%@", relaxModel.audio_desc] stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"];
self.tipsLab.height = [NSString getHeightWithText:audio_desc withFont:SysFont(14.0) withMaxWidth:kScreenWidth - 30];
self.tipsLab.text = audio_desc;
// 不是正在播放的状态需要先停止
if (self.audioStream.isPlaying == NO) { [self.audioStream stop]; }
self.audioStream.url = [NSURL URLWithString:relaxModel.audio_url];
if (isStartPlay) { [self.audioStream play]; }
}
#pragma mark - UIGestureRecognizerDelegate
- (void)actionTapGesture:(UITapGestureRecognizer *)sender {
CGPoint touchPoint = [sender locationInView:self.sliderView];
float value = (self.sliderView.maximumValue - self.sliderView.minimumValue) * (touchPoint.x / self.sliderView.width);
[self.sliderView setValue:value animated:YES];
[self didSliderTouchEnded:value];
}
#pragma mark - 滑块事件
- (void)sliderValueChanged:(UISlider *)sender {
self.isDraging = YES;
}
- (void)sliderTouchDown:(UISlider *)sender {
_tapGesture.enabled = NO;
self.isDraging = YES;
}
- (void)sliderTouchUpInSide:(UISlider *)sender {
_tapGesture.enabled = YES;
[self didSliderTouchEnded:sender.value];
}
- (void)didSliderTouchEnded:(float)value {
self.isDraging = NO;
// 避免用户拖动进度条出现极值导致音频文件加载失败问题
if (value == 0) value = 0.001;
if (value == 1) value = 0.999;
FSStreamPosition pos = {0};
pos.position = value;
[self.audioStream seekToPosition:pos];
}
#pragma mark - UICollectionViewDelegate && UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.relaxList.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
RelaxTrainCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([RelaxTrainCell class]) forIndexPath:indexPath];
[cell updateRelaxCell:self.relaxList[indexPath.row] isShowPlayIcon:(self.curIndex == indexPath.row)];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if (self.curIndex == indexPath.row) {
return;
}
self.curIndex = indexPath.row;
RelaxTrainModel *relaxModel = [self.relaxList objectAtIndex:indexPath.row];
[self refreshTopData:relaxModel isStartPlay:YES];
[self.relaxCollectionView reloadData];
}
#pragma mark - lazy
- (UIButton *)playerBtn {
if (!_playerBtn) {
_playerBtn = [UIButton new];
[_playerBtn addTarget:self action:@selector(playControlAction:) forControlEvents:UIControlEventTouchUpInside];
[_playerBtn dk_setBackgroundImage:DKImagePickerWithNames(@"audio_play_icon", @"audio_play_icon", @"audio_play_icon") forState:UIControlStateNormal];
[_playerBtn dk_setBackgroundImage:DKImagePickerWithNames(@"relax_pause", @"relax_pause", @"relax_pause") forState:UIControlStateSelected];
}
return _playerBtn;
}
- (UILabel *)titleLab {
if (!_titleLab) {
_titleLab = [UILabel dkLabWithFont:BoldFont(16.0)];
}
return _titleLab;
}
- (DSSlider *)sliderView {
if (!_sliderView) {
_sliderView = [DSSlider new];
[_sliderView cornerRadius:2.0];
_sliderView.minimumTrackTintColor = BrandColor;
_sliderView.maximumTrackTintColor = ColorFromHex(0xE3E1E1);
[_sliderView setThumbImage:[UIImage imageNamed:@"muse_slider_thumbImage"] forState:UIControlStateNormal];
[_sliderView addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
[_sliderView addTarget:self action:@selector(sliderTouchDown:) forControlEvents:UIControlEventTouchDown];
[_sliderView addTarget:self action:@selector(sliderTouchUpInSide:) forControlEvents:UIControlEventTouchUpInside];
// 为UISlider添加点击事件
_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionTapGesture:)];
_tapGesture.delegate = self;
[_sliderView addGestureRecognizer:_tapGesture];
}
return _sliderView;
}
- (UILabel *)tipsLab {
if (!_tipsLab) {
_tipsLab = [UILabel labWithFont:SysFont(14.0)];
_tipsLab.dk_textColorPicker = DKColorPickerWithColors(SubTitleColor, ColorFromHexA(0xFFFFFF, .5), DSWhite);
_tipsLab.numberOfLines = 0;
_tipsLab.lineBreakMode = NSLineBreakByWordWrapping;
}
return _tipsLab;
}
- (UILabel *)proLeftLb {
if (!_proLeftLb) {
_proLeftLb = [UILabel labWithFont:SysFont(12)];
_proLeftLb.textAlignment = NSTextAlignmentLeft;
_proLeftLb.dk_textColorPicker = DKColorPickerWithColors(ColorFromHex(0xAAAAAA), ColorFromHex(0x5A6073), DSWhite);
}
return _proLeftLb;
}
- (UILabel *)proRightLb {
if (!_proRightLb) {
_proRightLb = [UILabel labWithFont:SysFont(12)];
_proRightLb.textAlignment = NSTextAlignmentRight;
_proRightLb.dk_textColorPicker = DKColorPickerWithColors(ColorFromHex(0xAAAAAA), ColorFromHex(0x5A6073), DSWhite);
}
return _proRightLb;
}
- (FSAudioStream *)audioStream {
if (_audioStream == nil) {
_audioStream = [[FSAudioStream alloc] init];
_audioStream.strictContentTypeChecking = NO;
_audioStream.defaultContentType = @"audio/mpeg";
WS(weakSelf);
[_audioStream setOnStateChange:^(FSAudioStreamState state) {
weakSelf.streamState = state;
weakSelf.playerBtn.selected = state == kFsAudioStreamPlaying;
[weakSelf.progressTimer setPaused:!(state == kFsAudioStreamPlaying)];
switch (state) {
case kFsAudioStreamRetrievingURL:
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
DSLog(@"retrieving URL -- 检索文件");
break;
case kFsAudioStreamStopped:
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
DSLog(@"kFsAudioStreamStopped --- 停止播放了");
break;
case kFsAudioStreamBuffering: {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
DSLog(@"buffering --- 缓存中");
break;
}
case kFsAudioStreamPaused:
DSLog(@"暂停了");
break;
case kFsAudioStreamSeeking:
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
DSLog(@"kFsAudioStreamSeeking -- 快进 或者 快退");
break;
case kFsAudioStreamPlaying:
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
DSLog(@"播放ing...");
// 更新腹式呼吸放松法任务状态
@synchronized (weakSelf) {
if (weakSelf.isUpdateTask == NO) {
[RelaxTrainRequestModel userCurTaskStateWithParams:weakSelf.updateParams completion:^(RelaxTrainRequestModel * _Nonnull requestModel) {
if (requestModel.resCode == DSResCodeSuccess) {
weakSelf.isUpdateTask = YES;
}
}];
}
}
break;
case kFsAudioStreamFailed:
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
DSLog(@"音频文件加载失败");
break;
case kFsAudioStreamPlaybackCompleted:
break;
case kFsAudioStreamRetryingStarted:
DSLog(@"回放失败");
break;
case kFsAudioStreamRetryingSucceeded:
DSLog(@"重试成功");
break;
case kFsAudioStreamRetryingFailed:
DSLog(@"Failed to retry playback -- 重试失败");
break;
default:
break;
}
}];
}
return _audioStream;
}
- (UIView *)relaxRecView {
if (!_relaxRecView) {
_relaxRecView = [UIView new];
UIView *icon = [UIView new];
icon.backgroundColor = BrandColor;
[icon cornerRadius:2.0];
[_relaxRecView addSubview:icon];
UILabel *lab = [UILabel dkLabWithText:@"放松训练|推荐" font:BoldFont(16.0)];
[_relaxRecView addSubview:lab];
[icon mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_relaxRecView);
make.top.equalTo(_relaxRecView).offset(2);
make.bottom.equalTo(_relaxRecView).offset(-2);
make.width.equalTo(@4);
}];
[lab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(icon.mas_right).offset(4);
make.top.bottom.equalTo(icon);
}];
}
return _relaxRecView;
}
- (UICollectionView *)relaxCollectionView {
if (!_relaxCollectionView) {
CGFloat width = 120;
CGFloat height = 150;
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 15);
layout.itemSize = CGSizeMake(width, height);
layout.minimumLineSpacing = 12;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_relaxCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_relaxCollectionView.showsHorizontalScrollIndicator = NO;
_relaxCollectionView.delegate = self;
_relaxCollectionView.dataSource = self;
[_relaxCollectionView registerClass:[RelaxTrainCell class] forCellWithReuseIdentifier:NSStringFromClass([RelaxTrainCell class])];
_relaxCollectionView.backgroundColor = DSClearColor;
}
return _relaxCollectionView;
}
- (NSArray *)relaxList {
if (!_relaxList) {
_relaxList = [NSArray array];
}
return _relaxList;
}
@end
//
// RelaxTrainCell.h
// DreamSleep
//
// Created by peter on 2022/6/6.
//
#import <UIKit/UIKit.h>
#import "RelaxTrainModel.h"
NS_ASSUME_NONNULL_BEGIN
/// 放松训练音频cell
@interface RelaxTrainCell : UICollectionViewCell
- (void)updateRelaxCell:(RelaxTrainModel *)trainModel isShowPlayIcon:(BOOL)isShowPlayIcon;
@end
NS_ASSUME_NONNULL_END
//
// RelaxTrainCell.m
// DreamSleep
//
// Created by peter on 2022/6/6.
//
#import "RelaxTrainCell.h"
@interface RelaxTrainCell ()
// 主圆角图片
@property (nonatomic, strong) UIImageView *homeIV;
// 音频名标签
@property (nonatomic, strong) UILabel *audioNameLab;
@property (nonatomic, strong) UIImageView *recIcon;
@property (nonatomic, strong) UILabel *recLab;
@property (nonatomic, strong) UIImageView *playIcon;
@end
@implementation RelaxTrainCell
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self.contentView addSubview:self.homeIV];
[self.contentView addSubview:self.audioNameLab];
[self.contentView addSubview:self.recIcon];
[self.contentView addSubview:self.recLab];
[self.contentView addSubview:self.playIcon];
[self.homeIV mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentView);
make.left.equalTo(self.contentView);
make.width.height.equalTo(@(120));
}];
[self.audioNameLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.homeIV);
make.top.equalTo(self.homeIV.mas_bottom).offset(8);
}];
[self.recIcon mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.homeIV);
make.left.equalTo(self.homeIV).offset(11);
}];
[self.recLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.recIcon);
}];
[self.playIcon mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.homeIV);
}];
}
return self;
}
- (void)updateRelaxCell:(RelaxTrainModel *)trainModel isShowPlayIcon:(BOOL)isShowPlayIcon {
[self.homeIV yy_setImageWithURL:[NSURL URLWithString:trainModel.bg_url] placeholder:[UIImage imageNamed:@"basicPlaceholder"]];
self.audioNameLab.text = trainModel.audio_name;
self.recIcon.hidden = [trainModel.is_recommend isEqualToString:@"0"];
self.recLab.hidden = [trainModel.is_recommend isEqualToString:@"0"];
self.playIcon.hidden = !isShowPlayIcon;
}
#pragma mark - lazy
- (UIImageView *)homeIV {
if (!_homeIV) {
_homeIV = [UIImageView new];
_homeIV.contentMode = UIViewContentModeScaleAspectFill;
[_homeIV cornerRadius:12.0];
_homeIV.dk_alphaPicker = DKAlphaPickerWithAlphas(1.0, .5, .5);
}
return _homeIV;
}
- (UILabel *)audioNameLab {
if (!_audioNameLab) {
_audioNameLab = [UILabel labWithFont:SysFont(15)];
_audioNameLab.dk_textColorPicker = DKColorPickerWithColors(MainTextColor, DkTitleColor, DSWhite);
}
return _audioNameLab;
}
- (UIImageView *)recIcon {
if (!_recIcon) {
_recIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"relax_rec_icon"]];
}
return _recIcon;
}
- (UILabel *)recLab {
if (!_recLab) {
_recLab = [UILabel labWithText:@"优选" textColor:DSWhite font:SysFont(12.0)];
_recLab.textAlignment = NSTextAlignmentCenter;
}
return _recLab;
}
- (UIImageView *)playIcon {
if (!_playIcon) {
_playIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"relax_play_show"]];
}
return _playIcon;
}
@end
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!