Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
galaxy-iOS
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
mobile-group
galaxy-iOS
Commits
8079abe0
Commit
8079abe0
authored
Nov 30, 2024
by
Alex朱枝文
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
增加直播点播入口
parent
ce194313
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
406 additions
and
152 deletions
+406
-152
YHLifeViewController.swift
...es/Modules/Home(首页)/Life(生活)/C/YHLifeViewController.swift
+5
-1
YHHomeBannerView.swift
.../galaxy/Classes/Modules/Home(首页)/V/YHHomeBannerView.swift
+75
-1
YHSelectLookView.swift
...lasses/Modules/Home(首页)/YHSelect/V/YHSelectLookView.swift
+5
-1
YHLivePlayerViewController+Api.swift
...estreamSales(直播销售)/C/YHLivePlayerViewController+Api.swift
+12
-0
YHLivePlayerViewController.swift
.../LivestreamSales(直播销售)/C/YHLivePlayerViewController.swift
+41
-0
YHLiveDetailModel.swift
...s/Modules/LivestreamSales(直播销售)/M/YHLiveDetailModel.swift
+20
-0
YHFloatingWindow.swift
...es/Modules/LivestreamSales(直播销售)/V/YHFloatingWindow.swift
+180
-149
YHLiveSalesViewModel.swift
...dules/LivestreamSales(直播销售)/VM/YHLiveSalesViewModel.swift
+42
-0
YHAllApiName.swift
galaxy/galaxy/Classes/Tools/NetWork/YHAllApiName.swift
+4
-0
Contents.json
....xcassets/YinHeLive/live_win_close.imageset/Contents.json
+22
-0
live_win_close@2x.png
...s/YinHeLive/live_win_close.imageset/live_win_close@2x.png
+0
-0
live_win_close@3x.png
...s/YinHeLive/live_win_close.imageset/live_win_close@3x.png
+0
-0
No files found.
galaxy/galaxy/Classes/Modules/Home(首页)/Life(生活)/C/YHLifeViewController.swift
View file @
8079abe0
...
@@ -273,7 +273,11 @@ extension YHLifeViewController: UICollectionViewDelegate, UICollectionViewDataSo
...
@@ -273,7 +273,11 @@ extension YHLifeViewController: UICollectionViewDelegate, UICollectionViewDataSo
func
collectionView
(
_
collectionView
:
UICollectionView
,
didSelectItemAt
indexPath
:
IndexPath
)
{
func
collectionView
(
_
collectionView
:
UICollectionView
,
didSelectItemAt
indexPath
:
IndexPath
)
{
//跳转直播 文哥代办
//跳转直播 文哥代办
YHShareAlertView
.
show
(
image
:
"http://gips3.baidu.com/it/u=3886271102,3123389489&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960"
,
title
:
"12344"
,
subMessage
:
"12213243"
,
linkUrl
:
"https://www.baidu.com"
,
isLive
:
true
)
guard
self
.
viewModel
.
liveArr
.
count
>
indexPath
.
row
else
{
return
}
let
item
=
self
.
viewModel
.
liveArr
[
indexPath
.
row
]
YHPlayerManager
.
shared
.
enterLive
(
from
:
nil
,
id
:
item
.
id
,
url
:
item
.
pull_url
,
title
:
item
.
live_title
,
roomId
:
item
.
room_id
)
}
}
}
}
...
...
galaxy/galaxy/Classes/Modules/Home(首页)/V/YHHomeBannerView.swift
View file @
8079abe0
...
@@ -24,8 +24,14 @@ class YHHomeBannerView: UIView {
...
@@ -24,8 +24,14 @@ class YHHomeBannerView: UIView {
self
.
indicatorView
.
curIndicatorIndex
=
0
self
.
indicatorView
.
curIndicatorIndex
=
0
// 指定显示图片为第一个
// 指定显示图片为第一个
bannerView
.
selectItem
(
at
:
0
,
animated
:
false
)
bannerView
.
selectItem
(
at
:
0
,
animated
:
false
)
let
noNeedAutoScroll
=
dataArr
.
contains
(
where
:
{
$0
.
skip_type
==
100
||
$0
.
skip_type
==
102
})
// // TODO: - alex测试
// noNeedAutoScroll = true
// // TODO: - alex测试
// 开启定时器开始滚动
// 开启定时器开始滚动
bannerView
.
automaticSlidingInterval
=
bannerSildingInterval
bannerView
.
automaticSlidingInterval
=
noNeedAutoScroll
?
0
:
bannerSildingInterval
bannerView
.
removesInfiniteLoopForSingleItem
=
true
bannerView
.
removesInfiniteLoopForSingleItem
=
true
bannerView
.
alwaysBounceHorizontal
=
true
bannerView
.
alwaysBounceHorizontal
=
true
}
}
...
@@ -132,6 +138,13 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
...
@@ -132,6 +138,13 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
if
model
.
isLocalItemFlag
{
if
model
.
isLocalItemFlag
{
return
return
}
}
// // TODO: - alex测试
// if index == 1 {
// let cell: YHHomeBannerCollectionViewCell? = pagerView.cellForItem(at: index) as? YHHomeBannerCollectionViewCell
// YHPlayerManager.shared.enterLive(from: cell?.bannerImagV, id: 23, url: "https://pull-flv-l6.douyincdn.com/stage/stream-116295918585905183.flv?k=e21f1ae1e7591521&t=1733551151&major_anchor_level=common&abr_pts=-800&_session_id=037-202411301359108030CAEAC1F742805E6D.1732946351732.18942&rsi=1", title: nil, roomId: nil, type: .secondary)
// return
// }
// // TODO: - alex测试
if
model
.
skip_url
.
isEmpty
==
false
{
if
model
.
skip_url
.
isEmpty
==
false
{
switch
model
.
skip_type
{
switch
model
.
skip_type
{
case
1
:
//跳转H5
case
1
:
//跳转H5
...
@@ -201,6 +214,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
...
@@ -201,6 +214,7 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
vc
.
url
=
model
.
skip_url
vc
.
url
=
model
.
skip_url
self
.
parentViewController
?
.
navigationController
?
.
pushViewController
(
vc
)
self
.
parentViewController
?
.
navigationController
?
.
pushViewController
(
vc
)
case
100
:
// 直播
case
100
:
// 直播
//文哥
// media_type 投放类型:1 图片,2 直播
// media_type 投放类型:1 图片,2 直播
// live_id 直播ID
// live_id 直播ID
// live_status 直播状态 1:直播中 2:未直播 0:未知状态 3:结束直播
// live_status 直播状态 1:直播中 2:未直播 0:未知状态 3:结束直播
...
@@ -208,11 +222,17 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
...
@@ -208,11 +222,17 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
// live_pull_url 直播拉流链接
// live_pull_url 直播拉流链接
// video_url 视频链接
// video_url 视频链接
// recorded_cate_id 录播分类id
// recorded_cate_id 录播分类id
let
cell
:
YHHomeBannerCollectionViewCell
?
=
pagerView
.
cellForItem
(
at
:
index
)
as?
YHHomeBannerCollectionViewCell
YHPlayerManager
.
shared
.
enterLive
(
from
:
cell
?
.
bannerImagV
,
id
:
model
.
live_id
,
url
:
model
.
live_pull_url
,
title
:
nil
,
roomId
:
nil
,
type
:
.
secondary
)
printLog
(
"跳转直播"
)
printLog
(
"跳转直播"
)
case
101
:
//录播
case
101
:
//录播
printLog
(
"跳转录播"
)
printLog
(
"跳转录播"
)
let
cell
:
YHHomeBannerCollectionViewCell
?
=
pagerView
.
cellForItem
(
at
:
index
)
as?
YHHomeBannerCollectionViewCell
YHPlayerManager
.
shared
.
enterVOD
(
from
:
cell
?
.
bannerImagV
,
id
:
model
.
live_id
,
url
:
model
.
video_url
,
title
:
nil
,
type
:
.
secondary
)
case
102
:
//图片直播
case
102
:
//图片直播
printLog
(
"跳转录播"
)
printLog
(
"跳转录播"
)
let
cell
:
YHHomeBannerCollectionViewCell
?
=
pagerView
.
cellForItem
(
at
:
index
)
as?
YHHomeBannerCollectionViewCell
YHPlayerManager
.
shared
.
enterLive
(
from
:
cell
?
.
bannerImagV
,
id
:
model
.
live_id
,
url
:
model
.
live_pull_url
,
title
:
nil
,
roomId
:
nil
,
type
:
.
secondary
)
case
0
:
//0 不需要跳转
case
0
:
//0 不需要跳转
printLog
(
"0 不需要跳转"
)
printLog
(
"0 不需要跳转"
)
default
:
default
:
...
@@ -233,4 +253,58 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
...
@@ -233,4 +253,58 @@ extension YHHomeBannerView: FSPagerViewDataSource, FSPagerViewDelegate {
func
pagerViewDidEndScrollAnimation
(
_
pagerView
:
FSPagerView
)
{
func
pagerViewDidEndScrollAnimation
(
_
pagerView
:
FSPagerView
)
{
self
.
indicatorView
.
curIndicatorIndex
=
pagerView
.
currentIndex
self
.
indicatorView
.
curIndicatorIndex
=
pagerView
.
currentIndex
}
}
func
pagerView
(
_
pagerView
:
FSPagerView
,
willDisplay
cell
:
FSPagerViewCell
,
forItemAt
index
:
Int
)
{
if
index
>=
dataArr
.
count
{
return
}
let
model
=
dataArr
[
index
]
if
model
.
isLocalItemFlag
{
return
}
// // TODO: - alex测试
// if let cell = cell as? YHHomeBannerCollectionViewCell {
// if index == 1 {
// YHPlayerManager.shared.play(url: "https://pull-flv-l11.douyincdn.com/thirdgame/stream-404525958790382412.flv?expire=1733554587&sign=d1e9f927e20f4a3fb4e2dd2a2712e256&major_anchor_level=common&abr_pts=-800&_session_id=037-20241130145626DBDEB00EB11CB388DD95.1732949787574.66743&rsi=1", inView: cell.bannerImagV, title: nil, type: .secondary)
// } else {
// let player = YHPlayerManager.shared.getPlayer(.secondary)
// player?.setPlayView(nil)
// }
// return
// }
// // TODO: - alex测试
if
model
.
skip_url
.
isEmpty
==
false
{
if
let
cell
=
cell
as?
YHHomeBannerCollectionViewCell
{
if
model
.
skip_type
==
100
{
YHPlayerManager
.
shared
.
play
(
url
:
model
.
live_pull_url
,
inView
:
cell
.
bannerImagV
,
title
:
nil
,
type
:
.
secondary
)
}
else
{
let
player
=
YHPlayerManager
.
shared
.
getPlayer
(
.
secondary
)
player
?
.
setPlayView
(
nil
)
}
}
}
}
func
pagerView
(
_
pagerView
:
FSPagerView
,
didEndDisplaying
cell
:
FSPagerViewCell
,
forItemAt
index
:
Int
)
{
if
index
>=
dataArr
.
count
{
return
}
let
model
=
dataArr
[
index
]
if
model
.
isLocalItemFlag
{
return
}
// // TODO: - alex测试
// if index == 1 {
// YHPlayerManager.shared.stop(type: .secondary)
// return
// }
// // TODO: - alex测试
if
model
.
skip_url
.
isEmpty
==
false
{
if
model
.
skip_type
==
100
{
YHPlayerManager
.
shared
.
stop
(
type
:
.
secondary
)
}
}
}
}
}
galaxy/galaxy/Classes/Modules/Home(首页)/YHSelect/V/YHSelectLookView.swift
View file @
8079abe0
...
@@ -90,7 +90,11 @@ extension YHSelectLookView: UICollectionViewDelegate, UICollectionViewDataSource
...
@@ -90,7 +90,11 @@ extension YHSelectLookView: UICollectionViewDelegate, UICollectionViewDataSource
func
collectionView
(
_
collectionView
:
UICollectionView
,
didSelectItemAt
indexPath
:
IndexPath
)
{
func
collectionView
(
_
collectionView
:
UICollectionView
,
didSelectItemAt
indexPath
:
IndexPath
)
{
//跳转直播 文哥代办
//跳转直播 文哥代办
guard
items
.
count
>
indexPath
.
row
else
{
return
}
let
item
=
items
[
indexPath
.
row
]
YHPlayerManager
.
shared
.
enterLive
(
from
:
nil
,
id
:
item
.
id
,
url
:
item
.
pull_url
,
title
:
item
.
live_title
,
roomId
:
item
.
room_id
)
}
}
}
}
...
...
galaxy/galaxy/Classes/Modules/LivestreamSales(直播销售)/C/YHLivePlayerViewController+Api.swift
View file @
8079abe0
...
@@ -15,4 +15,16 @@ extension YHLivePlayerViewController {
...
@@ -15,4 +15,16 @@ extension YHLivePlayerViewController {
callback
(
liveDetail
,
error
)
callback
(
liveDetail
,
error
)
}
}
}
}
func
joinLiveRoom
(
id
:
Int
,
callback
:
@escaping
(
_
success
:
Bool
,
_
error
:
YHErrorModel
?)
->
Void
)
{
viewModel
.
joinLiveRoom
(
id
:
id
)
{
success
,
error
in
callback
(
success
,
error
)
}
}
func
leaveLiveRoom
(
id
:
Int
,
callback
:
@escaping
(
_
success
:
Bool
,
_
error
:
YHErrorModel
?)
->
Void
)
{
viewModel
.
leaveLiveRoom
(
id
:
id
)
{
success
,
error
in
callback
(
success
,
error
)
}
}
}
}
galaxy/galaxy/Classes/Modules/LivestreamSales(直播销售)/C/YHLivePlayerViewController.swift
View file @
8079abe0
...
@@ -69,6 +69,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
...
@@ -69,6 +69,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
setupLiveUI
()
setupLiveUI
()
setupLiveNotifications
()
setupLiveNotifications
()
setupData
()
setupData
()
if
YHLoginManager
.
shared
.
isLogin
()
{
joinLiveRoom
(
id
:
liveId
,
callback
:
{
_
,
_
in
})
}
}
}
deinit
{
deinit
{
...
@@ -95,6 +98,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
...
@@ -95,6 +98,7 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
topBarView
.
closeButtonClickEvent
=
{
[
weak
self
]
in
topBarView
.
closeButtonClickEvent
=
{
[
weak
self
]
in
self
?
.
quitChatRoom
()
self
?
.
quitChatRoom
()
self
?
.
leaveLiveRoom
()
YHPlayerManager
.
shared
.
stop
(
type
:
.
main
)
YHPlayerManager
.
shared
.
stop
(
type
:
.
main
)
if
let
navigationController
=
self
?
.
navigationController
{
if
let
navigationController
=
self
?
.
navigationController
{
navigationController
.
popViewController
(
animated
:
true
)
navigationController
.
popViewController
(
animated
:
true
)
...
@@ -105,6 +109,10 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
...
@@ -105,6 +109,10 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
topBarView
.
zoomButtonClickEvent
=
{
[
weak
self
]
in
topBarView
.
zoomButtonClickEvent
=
{
[
weak
self
]
in
self
?
.
enterFloating
()
self
?
.
enterFloating
()
}
}
topBarView
.
shareButtonClickEvent
=
{
[
weak
self
]
in
self
?
.
shareLive
()
}
}
}
private
func
setupData
()
{
private
func
setupData
()
{
...
@@ -169,6 +177,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
...
@@ -169,6 +177,9 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
name
:
YHIMHelper
.
didLogOutEaseIM
,
name
:
YHIMHelper
.
didLogOutEaseIM
,
object
:
nil
object
:
nil
)
)
NotificationCenter
.
default
.
addObserver
(
self
,
selector
:
#selector(
didLoginYH
)
,
name
:
YhConstant
.
YhNotification
.
didLoginSuccessNotifiction
,
object
:
nil
)
NotificationCenter
.
default
.
addObserver
(
self
,
selector
:
#selector(
didLogOutYH
)
,
name
:
YhConstant
.
YhNotification
.
didLogoutSuccessNotifiction
,
object
:
nil
)
}
}
// MARK: - Public Methods
// MARK: - Public Methods
...
@@ -207,6 +218,19 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
...
@@ -207,6 +218,19 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
}
}
}
}
private
func
leaveLiveRoom
()
{
guard
YHLoginManager
.
shared
.
isLogin
()
else
{
return
}
leaveLiveRoom
(
id
:
liveId
)
{
_
,
error
in
if
let
error
=
error
{
printLog
(
"leaveLiveRoom:
\(
error
)
"
)
}
else
{
printLog
(
"leaveLiveRoom: success"
)
}
}
}
private
func
quitChatRoom
()
{
private
func
quitChatRoom
()
{
guard
let
roomId
=
roomId
else
{
return
}
guard
let
roomId
=
roomId
else
{
return
}
...
@@ -219,6 +243,13 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
...
@@ -219,6 +243,13 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
}
}
}
}
private
func
shareLive
()
{
guard
let
liveModel
=
viewModel
.
liveDetailModel
else
{
return
}
YHShareAlertView
.
show
(
image
:
liveModel
.
live_image
,
title
:
"@"
+
liveModel
.
account
,
subMessage
:
liveModel
.
live_title
,
linkUrl
:
liveModel
.
live_h5_url
,
isLive
:
true
)
}
// MARK: - Message Handling
// MARK: - Message Handling
private
func
handleMessageInput
(
text
:
String
,
controller
:
YHMessageInputViewController
)
{
private
func
handleMessageInput
(
text
:
String
,
controller
:
YHMessageInputViewController
)
{
guard
checkLogin
(),
guard
checkLogin
(),
...
@@ -276,6 +307,16 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
...
@@ -276,6 +307,16 @@ class YHLivePlayerViewController: YHBasePlayerViewController {
appendHistoryMessages
(
messages
)
appendHistoryMessages
(
messages
)
}
}
@objc
private
func
didLoginYH
()
{
if
YHLoginManager
.
shared
.
isLogin
()
{
joinLiveRoom
(
id
:
liveId
,
callback
:
{
_
,
_
in
})
}
}
@objc
private
func
didLogOutYH
()
{
//
}
@objc
private
func
didLoginEaseIMSuccess
()
{
@objc
private
func
didLoginEaseIMSuccess
()
{
if
let
roomId
=
roomId
{
if
let
roomId
=
roomId
{
joinChatRoom
(
roomId
:
roomId
)
joinChatRoom
(
roomId
:
roomId
)
...
...
galaxy/galaxy/Classes/Modules/LivestreamSales(直播销售)/M/YHLiveDetailModel.swift
View file @
8079abe0
...
@@ -16,10 +16,30 @@ class YHLiveDetailModel: SmartCodable {
...
@@ -16,10 +16,30 @@ class YHLiveDetailModel: SmartCodable {
var
hxUid
:
String
=
""
var
hxUid
:
String
=
""
var
access_num
:
Int
=
0
var
access_num
:
Int
=
0
var
tips
:
String
=
""
var
tips
:
String
=
""
// 1:直播中 2:未直播 0:未知状态 3:结束直播
var
status
:
Int
=
0
var
status
:
Int
=
0
var
roomId
:
String
=
""
var
roomId
:
String
=
""
var
pullUrl
:
String
=
""
var
pullUrl
:
String
=
""
var
goods
:
[
YHLiveGoodsItem
]
=
[]
var
goods
:
[
YHLiveGoodsItem
]
=
[]
// 直播封面
var
live_image
:
String
=
""
// 直播主题
var
live_title
:
String
=
""
// h5直播地址
var
live_h5_url
:
String
=
""
// 预计开始时间
var
start_time
:
String
=
""
// 拉流地址360p
var
pull_sd1_url
:
String
=
""
// 拉流地址720p
var
pull_hd_url
:
String
=
""
// 1:直播中 2:未直播 0:未知状态 3:结束直播
var
stream_status
:
Int
=
0
// 实际开始时间
var
actual_start_time
:
String
=
""
// 实际结束时间
var
actual_end_time
:
String
=
""
required
init
()
{
required
init
()
{
}
}
...
...
galaxy/galaxy/Classes/Modules/LivestreamSales(直播销售)/V/YHFloatingWindow.swift
View file @
8079abe0
...
@@ -19,16 +19,16 @@ protocol YHFloatingWindowDelegate: AnyObject {
...
@@ -19,16 +19,16 @@ protocol YHFloatingWindowDelegate: AnyObject {
class
YHFloatingWindow
:
NSObject
{
class
YHFloatingWindow
:
NSObject
{
// MARK: - Properties
// MARK: - Properties
weak
var
player
:
YHPlayer
?
weak
var
player
:
YHPlayer
?
weak
var
delegate
:
YHFloatingWindowDelegate
?
weak
var
delegate
:
YHFloatingWindowDelegate
?
var
playbackInfo
:
YHPlayerManager
.
PlaybackInfo
?
var
playbackInfo
:
YHPlayerManager
.
PlaybackInfo
?
// 视频方向
// 视频方向
enum
VideoOrientation
{
enum
VideoOrientation
{
case
portrait
// 竖屏 9:16
case
portrait
// 竖屏 9:16
case
landscape
// 横屏 16:9
case
landscape
// 横屏 16:9
var
aspectRatio
:
CGFloat
{
var
aspectRatio
:
CGFloat
{
switch
self
{
switch
self
{
case
.
portrait
:
return
9.0
/
16.0
case
.
portrait
:
return
9.0
/
16.0
...
@@ -36,215 +36,219 @@ class YHFloatingWindow: NSObject {
...
@@ -36,215 +36,219 @@ class YHFloatingWindow: NSObject {
}
}
}
}
}
}
// 窗口尺寸
// 窗口尺寸
private
struct
Size
{
private
struct
Size
{
static
let
minWidth
:
CGFloat
=
120
static
let
minWidth
:
CGFloat
=
120
static
let
maxWidth
:
CGFloat
=
UIScreen
.
main
.
bounds
.
width
static
let
maxWidth
:
CGFloat
=
UIScreen
.
main
.
bounds
.
width
static
let
minHeight
:
CGFloat
=
67.5
// 16:9
static
let
minHeight
:
CGFloat
=
67.5
// 16:9
static
let
maxHeight
:
CGFloat
=
UIScreen
.
main
.
bounds
.
height
static
let
maxHeight
:
CGFloat
=
UIScreen
.
main
.
bounds
.
height
static
let
defaultWidth
:
CGFloat
=
150
static
let
defaultWidth
:
CGFloat
=
150
static
let
defaultHeight
:
CGFloat
=
84.375
// 16:9
static
let
defaultHeight
:
CGFloat
=
84.375
// 16:9
}
}
private(set)
var
contentView
:
UIView
private(set)
var
contentView
:
UIView
private
var
containerView
:
UIView
private
var
containerView
:
UIView
private
var
videoOrientation
:
VideoOrientation
=
.
landscape
private
var
videoOrientation
:
VideoOrientation
=
.
landscape
// 手势相关
// 手势相关
private
var
initialFrame
:
CGRect
=
.
zero
private
var
initialFrame
:
CGRect
=
.
zero
private
var
lastScale
:
CGFloat
=
1.0
private
var
isResizing
:
Bool
=
false
private
var
isResizing
:
Bool
=
false
private
var
initialCenter
:
CGPoint
=
.
zero
private
var
initialCenter
:
CGPoint
=
.
zero
// 缩放相关
private
var
currentScale
:
CGFloat
=
1.0
private
var
initialDistance
:
CGFloat
=
0
private
let
scaleMultiplier
:
CGFloat
=
1.5
// UI组件
// UI组件
private
lazy
var
closeButton
:
UIButton
=
{
private
lazy
var
closeButton
:
UIButton
=
{
let
button
=
UIButton
(
type
:
.
custom
)
let
button
=
UIButton
(
type
:
.
custom
)
button
.
setImage
(
UIImage
(
named
:
"
ico
n_close"
),
for
:
.
normal
)
button
.
setImage
(
UIImage
(
named
:
"
live_wi
n_close"
),
for
:
.
normal
)
button
.
addTarget
(
self
,
action
:
#selector(
closeButtonTapped
)
,
for
:
.
touchUpInside
)
button
.
addTarget
(
self
,
action
:
#selector(
closeButtonTapped
)
,
for
:
.
touchUpInside
)
button
.
frame
=
CGRect
(
x
:
0
,
y
:
0
,
width
:
24
,
height
:
24
)
return
button
return
button
}()
}()
private
lazy
var
closeButtonContainer
:
UIView
=
{
let
container
=
UIView
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
30
,
height
:
30
))
container
.
backgroundColor
=
.
clear
container
.
addSubview
(
closeButton
)
closeButton
.
center
=
CGPoint
(
x
:
container
.
bounds
.
width
/
2
,
y
:
container
.
bounds
.
height
/
2
)
return
container
}()
// MARK: - Initialization
// MARK: - Initialization
override
init
()
{
override
init
()
{
// 创建容器视图
containerView
=
UIView
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
containerView
=
UIView
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
Size
.
defaultWidth
,
width
:
Size
.
defaultWidth
,
height
:
Size
.
defaultHeight
))
height
:
Size
.
defaultHeight
))
// 创建内容视图
contentView
=
UIView
(
frame
:
containerView
.
bounds
)
contentView
=
UIView
(
frame
:
containerView
.
bounds
)
super
.
init
()
super
.
init
()
setupUI
()
setupUI
()
setupGestures
()
setupGestures
()
}
}
// MARK: - Setup
// MARK: - Setup
private
func
setupUI
()
{
private
func
setupUI
()
{
// 容器视图设置
containerView
.
backgroundColor
=
.
black
containerView
.
backgroundColor
=
.
black
containerView
.
layer
.
cornerRadius
=
8
containerView
.
layer
.
cornerRadius
=
3
containerView
.
clipsToBounds
=
true
containerView
.
clipsToBounds
=
true
containerView
.
layer
.
masksToBounds
=
true
containerView
.
layer
.
masksToBounds
=
true
// 添加阴影
containerView
.
layer
.
shadowColor
=
UIColor
.
black
.
cgColor
containerView
.
layer
.
shadowColor
=
UIColor
.
black
.
cgColor
containerView
.
layer
.
shadowOffset
=
CGSize
(
width
:
0
,
height
:
2
)
containerView
.
layer
.
shadowOffset
=
CGSize
(
width
:
0
,
height
:
2
)
containerView
.
layer
.
shadowRadius
=
4
containerView
.
layer
.
shadowRadius
=
4
containerView
.
layer
.
shadowOpacity
=
0.3
containerView
.
layer
.
shadowOpacity
=
0.3
// 添加内容视图
containerView
.
addSubview
(
contentView
)
containerView
.
addSubview
(
contentView
)
contentView
.
snp
.
makeConstraints
{
make
in
contentView
.
translatesAutoresizingMaskIntoConstraints
=
false
make
.
edges
.
equalToSuperview
()
NSLayoutConstraint
.
activate
([
}
contentView
.
leadingAnchor
.
constraint
(
equalTo
:
containerView
.
leadingAnchor
),
contentView
.
trailingAnchor
.
constraint
(
equalTo
:
containerView
.
trailingAnchor
),
// 添加关闭按钮
contentView
.
topAnchor
.
constraint
(
equalTo
:
containerView
.
topAnchor
),
containerView
.
addSubview
(
closeButton
)
contentView
.
bottomAnchor
.
constraint
(
equalTo
:
containerView
.
bottomAnchor
)
closeButton
.
snp
.
makeConstraints
{
make
in
])
make
.
top
.
right
.
equalToSuperview
()
.
inset
(
8
)
make
.
size
.
equalTo
(
CGSize
(
width
:
24
,
height
:
24
))
containerView
.
addSubview
(
closeButtonContainer
)
}
closeButtonContainer
.
translatesAutoresizingMaskIntoConstraints
=
false
NSLayoutConstraint
.
activate
([
closeButtonContainer
.
topAnchor
.
constraint
(
equalTo
:
containerView
.
topAnchor
),
closeButtonContainer
.
trailingAnchor
.
constraint
(
equalTo
:
containerView
.
trailingAnchor
),
closeButtonContainer
.
widthAnchor
.
constraint
(
equalToConstant
:
30
),
closeButtonContainer
.
heightAnchor
.
constraint
(
equalToConstant
:
30
)
])
}
}
private
func
setupGestures
()
{
private
func
setupGestures
()
{
// 平移手势
let
panGesture
=
UIPanGestureRecognizer
(
target
:
self
,
action
:
#selector(
handlePan(_:)
)
)
let
panGesture
=
UIPanGestureRecognizer
(
target
:
self
,
action
:
#selector(
handlePan(_:)
)
)
// 缩放手势
let
pinchGesture
=
UIPinchGestureRecognizer
(
target
:
self
,
action
:
#selector(
handlePinch(_:)
)
)
let
pinchGesture
=
UIPinchGestureRecognizer
(
target
:
self
,
action
:
#selector(
handlePinch(_:)
)
)
// 点击手势
let
tapGesture
=
UITapGestureRecognizer
(
target
:
self
,
action
:
#selector(
handleTap(_:)
)
)
let
tapGesture
=
UITapGestureRecognizer
(
target
:
self
,
action
:
#selector(
handleTap(_:)
)
)
tapGesture
.
delegate
=
self
tapGesture
.
delegate
=
self
containerView
.
addGestureRecognizer
(
panGesture
)
containerView
.
addGestureRecognizer
(
panGesture
)
containerView
.
addGestureRecognizer
(
pinchGesture
)
containerView
.
addGestureRecognizer
(
pinchGesture
)
containerView
.
addGestureRecognizer
(
tapGesture
)
containerView
.
addGestureRecognizer
(
tapGesture
)
}
}
// MARK: - Public Methods
// MARK: - Public Methods
func
calculateInitialFrame
()
->
CGRect
{
func
calculateInitialFrame
()
->
CGRect
{
// 计算浮窗的初始位置和大小
let
width
:
CGFloat
=
Size
.
defaultWidth
let
width
:
CGFloat
=
150
// 或其他合适的宽度
let
height
:
CGFloat
=
width
/
videoOrientation
.
aspectRatio
let
height
:
CGFloat
=
width
*
9
/
16
// 保持16:9比例
let
x
=
UIScreen
.
main
.
bounds
.
width
-
width
-
16
let
x
=
UIScreen
.
main
.
bounds
.
width
-
width
-
16
let
y
=
UIScreen
.
main
.
bounds
.
height
-
height
-
100
// 距离底部适当距离
let
y
=
UIScreen
.
main
.
bounds
.
height
-
height
-
100
return
CGRect
(
x
:
x
,
y
:
y
,
width
:
width
,
height
:
height
)
return
CGRect
(
x
:
x
,
y
:
y
,
width
:
width
,
height
:
height
)
}
}
func
show
(
in
window
:
UIWindow
)
{
func
show
(
in
window
:
UIWindow
)
{
containerView
.
frame
=
calculateInitialFrame
()
containerView
.
frame
=
calculateInitialFrame
()
window
.
addSubview
(
containerView
)
window
.
addSubview
(
containerView
)
}
}
func
show
(
in
window
:
UIWindow
,
at
point
:
CGPoint
?
=
nil
)
{
func
show
(
in
window
:
UIWindow
,
at
point
:
CGPoint
?
=
nil
)
{
// 设置初始位置
if
let
point
=
point
{
if
let
point
=
point
{
containerView
.
center
=
point
containerView
.
center
=
point
}
else
{
}
else
{
// 默认位置:右下角
containerView
.
frame
.
origin
=
CGPoint
(
containerView
.
frame
.
origin
=
CGPoint
(
x
:
window
.
bounds
.
width
-
containerView
.
bounds
.
width
-
20
,
x
:
window
.
bounds
.
width
-
containerView
.
bounds
.
width
-
20
,
y
:
window
.
bounds
.
height
-
containerView
.
bounds
.
height
-
100
y
:
window
.
bounds
.
height
-
containerView
.
bounds
.
height
-
100
)
)
}
}
window
.
addSubview
(
containerView
)
window
.
addSubview
(
containerView
)
// 显示动画
containerView
.
alpha
=
0
containerView
.
alpha
=
0
// containerView.transform = CGAffineTransform(scaleX: 0.3, y: 0.3)
UIView
.
animate
(
withDuration
:
0.3
)
{
UIView
.
animate
(
withDuration
:
0.3
)
{
self
.
containerView
.
alpha
=
1
self
.
containerView
.
alpha
=
1
self
.
containerView
.
transform
=
.
identity
}
}
}
}
func
dismiss
()
{
func
dismiss
()
{
UIView
.
animate
(
withDuration
:
0.3
,
animations
:
{
UIView
.
animate
(
withDuration
:
0.3
,
animations
:
{
self
.
containerView
.
alpha
=
0
self
.
containerView
.
alpha
=
0
//self.containerView.transform = CGAffineTransform(scaleX: 0.3, y: 0.3)
})
{
_
in
})
{
_
in
self
.
containerView
.
removeFromSuperview
()
self
.
containerView
.
removeFromSuperview
()
}
}
}
}
func
setVideoSize
(
_
size
:
CGSize
)
{
func
setVideoSize
(
_
size
:
CGSize
)
{
// 更新视频方向
let
orientation
:
VideoOrientation
=
size
.
width
>
size
.
height
?
.
landscape
:
.
portrait
let
orientation
:
VideoOrientation
=
size
.
width
>
size
.
height
?
.
landscape
:
.
portrait
if
orientation
!=
videoOrientation
{
if
orientation
!=
videoOrientation
{
videoOrientation
=
orientation
videoOrientation
=
orientation
updateLayoutForOrientation
()
updateLayoutForOrientation
()
}
}
}
}
// MARK: - Private Methods
// MARK: - Private Methods
private
func
updateLayoutForOrientation
()
{
private
func
updateLayoutForOrientation
()
{
let
currentWidth
=
containerView
.
bounds
.
width
let
currentWidth
=
containerView
.
bounds
.
width
let
newHeight
=
currentWidth
/
videoOrientation
.
aspectRatio
let
newHeight
=
currentWidth
/
videoOrientation
.
aspectRatio
UIView
.
animate
(
withDuration
:
0.3
)
{
UIView
.
animate
(
withDuration
:
0.3
)
{
var
frame
=
self
.
containerView
.
frame
var
frame
=
self
.
containerView
.
frame
frame
.
size
.
height
=
newHeight
frame
.
size
.
height
=
newHeight
self
.
containerView
.
frame
=
frame
self
.
containerView
.
frame
=
frame
// 通知代理
self
.
delegate
?
.
floatingWindow
(
self
,
didChangeSize
:
frame
.
size
)
self
.
delegate
?
.
floatingWindow
(
self
,
didChangeSize
:
frame
.
size
)
}
}
}
}
private
func
snapToNearestSize
()
{
private
func
snapToNearestSize
()
{
let
currentWidth
=
containerView
.
bounds
.
width
let
currentWidth
=
containerView
.
bounds
.
width
// 定义三种尺寸状态
let
sizeSteps
:
[
CGFloat
]
=
[
let
smallWidth
=
Size
.
minWidth
Size
.
minWidth
,
let
mediumWidth
=
Size
.
maxWidth
*
0.5
Size
.
maxWidth
*
0.33
,
let
largeWidth
=
Size
.
maxWidth
Size
.
maxWidth
*
0.5
,
Size
.
maxWidth
*
0.75
,
// 确定目标尺寸
Size
.
maxWidth
let
targetWidth
:
CGFloat
]
if
currentWidth
<
(
smallWidth
+
mediumWidth
)
/
2
{
targetWidth
=
smallWidth
var
targetWidth
=
sizeSteps
[
0
]
}
else
if
currentWidth
<
(
mediumWidth
+
largeWidth
)
/
2
{
var
minDifference
=
abs
(
currentWidth
-
targetWidth
)
targetWidth
=
mediumWidth
}
else
{
for
size
in
sizeSteps
{
targetWidth
=
largeWidth
let
difference
=
abs
(
currentWidth
-
size
)
if
difference
<
minDifference
{
minDifference
=
difference
targetWidth
=
size
}
}
}
// 计算对应高度
let
targetHeight
=
targetWidth
/
videoOrientation
.
aspectRatio
let
targetHeight
=
targetWidth
/
videoOrientation
.
aspectRatio
let
centerX
=
containerView
.
center
.
x
// 执行动画
let
centerY
=
containerView
.
center
.
y
UIView
.
animate
(
withDuration
:
0.3
)
{
UIView
.
animate
(
withDuration
:
0.3
,
delay
:
0
,
options
:
[
.
curveEaseOut
],
animations
:
{
var
frame
=
self
.
containerView
.
frame
var
frame
=
self
.
containerView
.
frame
frame
.
size
=
CGSize
(
width
:
targetWidth
,
height
:
targetHeight
)
frame
.
size
=
CGSize
(
width
:
targetWidth
,
height
:
targetHeight
)
frame
.
origin
.
x
=
self
.
containerView
.
center
.
x
-
targetWidth
/
2
frame
.
origin
.
x
=
centerX
-
targetWidth
/
2
frame
.
origin
.
y
=
self
.
containerView
.
center
.
y
-
targetHeight
/
2
frame
.
origin
.
y
=
centerY
-
targetHeight
/
2
self
.
containerView
.
frame
=
frame
self
.
containerView
.
frame
=
frame
// 通知代理
self
.
delegate
?
.
floatingWindow
(
self
,
didChangeSize
:
frame
.
size
)
self
.
delegate
?
.
floatingWindow
(
self
,
didChangeSize
:
frame
.
size
)
}
}
)
}
}
// MARK: - Gesture Handlers
// MARK: - Gesture Handlers
@objc
private
func
handlePan
(
_
gesture
:
UIPanGestureRecognizer
)
{
@objc
private
func
handlePan
(
_
gesture
:
UIPanGestureRecognizer
)
{
guard
!
isResizing
else
{
return
}
guard
!
isResizing
else
{
return
}
let
translation
=
gesture
.
translation
(
in
:
containerView
.
superview
)
let
translation
=
gesture
.
translation
(
in
:
containerView
.
superview
)
switch
gesture
.
state
{
switch
gesture
.
state
{
case
.
began
:
case
.
began
:
initialCenter
=
containerView
.
center
initialCenter
=
containerView
.
center
case
.
changed
:
case
.
changed
:
var
newCenter
=
CGPoint
(
var
newCenter
=
CGPoint
(
x
:
initialCenter
.
x
+
translation
.
x
,
x
:
initialCenter
.
x
+
translation
.
x
,
...
@@ -252,113 +256,140 @@ class YHFloatingWindow: NSObject {
...
@@ -252,113 +256,140 @@ class YHFloatingWindow: NSObject {
)
)
newCenter
=
adjustedPosition
(
for
:
newCenter
)
newCenter
=
adjustedPosition
(
for
:
newCenter
)
containerView
.
center
=
newCenter
containerView
.
center
=
newCenter
// 通知代理
delegate
?
.
floatingWindow
(
self
,
didChangePosition
:
newCenter
)
delegate
?
.
floatingWindow
(
self
,
didChangePosition
:
newCenter
)
case
.
ended
:
case
.
ended
:
let
velocity
=
gesture
.
velocity
(
in
:
containerView
.
superview
)
let
velocity
=
gesture
.
velocity
(
in
:
containerView
.
superview
)
handlePanEndedWithVelocity
(
velocity
)
handlePanEndedWithVelocity
(
velocity
)
default
:
default
:
break
break
}
}
}
}
@objc
private
func
handlePinch
(
_
gesture
:
UIPinchGestureRecognizer
)
{
@objc
private
func
handlePinch
(
_
gesture
:
UIPinchGestureRecognizer
)
{
switch
gesture
.
state
{
switch
gesture
.
state
{
case
.
began
:
case
.
began
:
isResizing
=
true
isResizing
=
true
initialFrame
=
containerView
.
frame
initialFrame
=
containerView
.
frame
lastScale
=
1.0
currentScale
=
1.0
let
touch1
=
gesture
.
location
(
ofTouch
:
0
,
in
:
containerView
)
let
touch2
=
gesture
.
location
(
ofTouch
:
1
,
in
:
containerView
)
initialDistance
=
hypot
(
touch2
.
x
-
touch1
.
x
,
touch2
.
y
-
touch1
.
y
)
case
.
changed
:
case
.
changed
:
let
scale
=
gesture
.
scale
/
lastScale
let
touch1
=
gesture
.
location
(
ofTouch
:
0
,
in
:
containerView
)
let
newWidth
=
initialFrame
.
width
*
scale
let
touch2
=
gesture
.
location
(
ofTouch
:
1
,
in
:
containerView
)
let
currentDistance
=
hypot
(
touch2
.
x
-
touch1
.
x
,
touch2
.
y
-
touch1
.
y
)
let
scale
=
(
currentDistance
/
initialDistance
)
*
scaleMultiplier
let
scaleDelta
=
scale
/
currentScale
currentScale
=
scale
let
newWidth
=
initialFrame
.
width
*
scaleDelta
let
newHeight
=
newWidth
/
videoOrientation
.
aspectRatio
let
newHeight
=
newWidth
/
videoOrientation
.
aspectRatio
var
newFrame
=
initialFrame
var
newFrame
=
initialFrame
newFrame
.
size
=
constrainSize
(
CGSize
(
width
:
newWidth
,
height
:
newHeight
))
newFrame
.
size
=
constrainSize
(
CGSize
(
width
:
newWidth
,
height
:
newHeight
))
newFrame
.
origin
.
x
=
containerView
.
center
.
x
-
newFrame
.
width
/
2
newFrame
.
origin
.
y
=
containerView
.
center
.
y
-
newFrame
.
height
/
2
let
centerX
=
containerView
.
center
.
x
let
centerY
=
containerView
.
center
.
y
newFrame
.
origin
.
x
=
centerX
-
newFrame
.
width
/
2
newFrame
.
origin
.
y
=
centerY
-
newFrame
.
height
/
2
CATransaction
.
begin
()
CATransaction
.
setDisableActions
(
true
)
containerView
.
frame
=
newFrame
containerView
.
frame
=
newFrame
CATransaction
.
commit
()
// 通知代理
delegate
?
.
floatingWindow
(
self
,
didChangeSize
:
newFrame
.
size
)
delegate
?
.
floatingWindow
(
self
,
didChangeSize
:
newFrame
.
size
)
case
.
ended
:
case
.
ended
,
.
cancelled
:
isResizing
=
false
isResizing
=
false
snapToNearestSize
()
snapToNearestSize
()
default
:
default
:
break
break
}
}
}
}
@objc
private
func
handleTap
(
_
gesture
:
UITapGestureRecognizer
)
{
@objc
private
func
handleTap
(
_
gesture
:
UITapGestureRecognizer
)
{
let
location
=
gesture
.
location
(
in
:
containerView
)
if
closeButtonContainer
.
frame
.
contains
(
location
)
{
return
}
delegate
?
.
floatingWindowDidTap
(
self
)
delegate
?
.
floatingWindowDidTap
(
self
)
}
}
@objc
private
func
closeButtonTapped
()
{
@objc
private
func
closeButtonTapped
()
{
delegate
?
.
floatingWindowDidClose
(
self
)
delegate
?
.
floatingWindowDidClose
(
self
)
dismiss
()
dismiss
()
}
}
// MARK: - Helper Methods
// MARK: - Helper Methods
private
func
constrainSize
(
_
size
:
CGSize
)
->
CGSize
{
private
func
constrainSize
(
_
size
:
CGSize
)
->
CGSize
{
var
width
=
size
.
width
var
width
=
size
.
width
var
height
=
size
.
height
var
height
=
size
.
height
// 限制最小/最大尺寸
if
width
<
Size
.
minWidth
{
width
=
max
(
min
(
width
,
Size
.
maxWidth
),
Size
.
minWidth
)
width
=
Size
.
minWidth
}
else
if
width
>
Size
.
maxWidth
{
width
=
Size
.
maxWidth
}
height
=
width
/
videoOrientation
.
aspectRatio
height
=
width
/
videoOrientation
.
aspectRatio
if
height
>
Size
.
maxHeight
{
height
=
Size
.
maxHeight
width
=
height
*
videoOrientation
.
aspectRatio
}
return
CGSize
(
width
:
width
,
height
:
height
)
return
CGSize
(
width
:
width
,
height
:
height
)
}
}
private
func
adjustedPosition
(
for
center
:
CGPoint
)
->
CGPoint
{
private
func
adjustedPosition
(
for
center
:
CGPoint
)
->
CGPoint
{
guard
let
superview
=
containerView
.
superview
else
{
return
center
}
guard
let
superview
=
containerView
.
superview
else
{
return
center
}
var
adjustedCenter
=
center
var
adjustedCenter
=
center
let
halfWidth
=
containerView
.
bounds
.
width
/
2
let
halfWidth
=
containerView
.
bounds
.
width
/
2
let
halfHeight
=
containerView
.
bounds
.
height
/
2
let
halfHeight
=
containerView
.
bounds
.
height
/
2
// 限制不超出屏幕边界
adjustedCenter
.
x
=
min
(
max
(
halfWidth
,
adjustedCenter
.
x
),
superview
.
bounds
.
width
-
halfWidth
)
adjustedCenter
.
y
=
min
(
max
(
halfHeight
,
adjustedCenter
.
y
),
superview
.
bounds
.
height
-
halfHeight
)
// 计算实际可用区域
let
safeAreaInsets
:
UIEdgeInsets
let
topLimit
=
superview
.
safeAreaInsets
.
top
+
halfHeight
if
#available(iOS 11.0, *)
{
let
bottomLimit
=
superview
.
bounds
.
height
-
superview
.
safeAreaInsets
.
bottom
-
halfHeight
safeAreaInsets
=
superview
.
safeAreaInsets
}
else
{
// 限制不超出屏幕边界和安全区域
safeAreaInsets
=
.
zero
}
let
topLimit
=
safeAreaInsets
.
top
+
halfHeight
let
bottomLimit
=
superview
.
bounds
.
height
-
safeAreaInsets
.
bottom
-
halfHeight
adjustedCenter
.
x
=
min
(
max
(
halfWidth
,
adjustedCenter
.
x
),
adjustedCenter
.
x
=
min
(
max
(
halfWidth
,
adjustedCenter
.
x
),
superview
.
bounds
.
width
-
halfWidth
)
superview
.
bounds
.
width
-
halfWidth
)
adjustedCenter
.
y
=
min
(
max
(
topLimit
,
adjustedCenter
.
y
),
adjustedCenter
.
y
=
min
(
max
(
topLimit
,
adjustedCenter
.
y
),
bottomLimit
)
bottomLimit
)
return
adjustedCenter
return
adjustedCenter
}
}
private
func
handlePanEndedWithVelocity
(
_
velocity
:
CGPoint
)
{
private
func
handlePanEndedWithVelocity
(
_
velocity
:
CGPoint
)
{
let
magnitude
=
sqrt
((
velocity
.
x
*
velocity
.
x
)
+
(
velocity
.
y
*
velocity
.
y
))
let
magnitude
=
sqrt
((
velocity
.
x
*
velocity
.
x
)
+
(
velocity
.
y
*
velocity
.
y
))
let
slideMultiplier
=
magnitude
/
200
let
slideMultiplier
=
magnitude
/
200
let
slideFactor
=
0.1
*
slideMultiplier
let
slideFactor
=
0.1
*
slideMultiplier
var
finalCenter
=
CGPoint
(
var
finalCenter
=
CGPoint
(
x
:
containerView
.
center
.
x
+
(
velocity
.
x
*
slideFactor
),
x
:
containerView
.
center
.
x
+
(
velocity
.
x
*
slideFactor
),
y
:
containerView
.
center
.
y
+
(
velocity
.
y
*
slideFactor
)
y
:
containerView
.
center
.
y
+
(
velocity
.
y
*
slideFactor
)
)
)
finalCenter
=
adjustedPosition
(
for
:
finalCenter
)
finalCenter
=
adjustedPosition
(
for
:
finalCenter
)
UIView
.
animate
(
withDuration
:
0.3
)
{
UIView
.
animate
(
withDuration
:
0.3
)
{
self
.
containerView
.
center
=
finalCenter
self
.
containerView
.
center
=
finalCenter
// 通知代理
self
.
delegate
?
.
floatingWindow
(
self
,
didChangePosition
:
finalCenter
)
self
.
delegate
?
.
floatingWindow
(
self
,
didChangePosition
:
finalCenter
)
}
}
}
}
...
@@ -368,14 +399,14 @@ class YHFloatingWindow: NSObject {
...
@@ -368,14 +399,14 @@ class YHFloatingWindow: NSObject {
extension
YHFloatingWindow
:
UIGestureRecognizerDelegate
{
extension
YHFloatingWindow
:
UIGestureRecognizerDelegate
{
func
gestureRecognizer
(
_
gestureRecognizer
:
UIGestureRecognizer
,
func
gestureRecognizer
(
_
gestureRecognizer
:
UIGestureRecognizer
,
shouldRecognizeSimultaneouslyWith
otherGestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
shouldRecognizeSimultaneouslyWith
otherGestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
return
true
return
true
}
}
func
gestureRecognizer
(
_
gestureRecognizer
:
UIGestureRecognizer
,
func
gestureRecognizer
(
_
gestureRecognizer
:
UIGestureRecognizer
,
shouldReceive
touch
:
UITouch
)
->
Bool
{
shouldReceive
touch
:
UITouch
)
->
Bool
{
// 如果点击的是按钮,不触发点击手势
let
location
=
touch
.
location
(
in
:
containerView
)
if
touch
.
view
is
UIButton
{
if
closeButtonContainer
.
frame
.
contains
(
location
)
{
return
false
return
false
}
}
return
true
return
true
...
...
galaxy/galaxy/Classes/Modules/LivestreamSales(直播销售)/VM/YHLiveSalesViewModel.swift
View file @
8079abe0
...
@@ -133,4 +133,46 @@ extension YHLiveSalesViewModel {
...
@@ -133,4 +133,46 @@ extension YHLiveSalesViewModel {
callback
(
nil
,
err
)
callback
(
nil
,
err
)
}
}
}
}
/*
离开直播间
*/
func
leaveLiveRoom
(
id
:
Int
,
callback
:
@escaping
(
_
success
:
Bool
,
_
error
:
YHErrorModel
?)
->
Void
)
{
let
strUrl
=
YHBaseUrlManager
.
shared
.
curURL
()
+
YHAllApiName
.
LiveSales
.
leaveLiveRoom
_
=
YHNetRequest
.
getRequest
(
url
:
strUrl
,
params
:
[
"live_id"
:
id
])
{
json
,
_
in
// 1. json字符串 转 对象
printLog
(
"model 是 ==>
\(
json
)
"
)
if
json
.
code
==
200
{
callback
(
true
,
nil
)
}
else
{
let
err
=
YHErrorModel
(
errorCode
:
Int32
(
json
.
code
),
errorMsg
:
json
.
msg
.
isEmpty
?
""
:
json
.
msg
)
callback
(
false
,
err
)
}
}
failBlock
:
{
err
in
callback
(
false
,
err
)
}
}
/*
进入直播间
*/
func
joinLiveRoom
(
id
:
Int
,
callback
:
@escaping
(
_
success
:
Bool
,
_
error
:
YHErrorModel
?)
->
Void
)
{
let
strUrl
=
YHBaseUrlManager
.
shared
.
curURL
()
+
YHAllApiName
.
LiveSales
.
joinLiveRoom
_
=
YHNetRequest
.
getRequest
(
url
:
strUrl
,
params
:
[
"live_id"
:
id
])
{
json
,
_
in
// 1. json字符串 转 对象
printLog
(
"model 是 ==>
\(
json
)
"
)
if
json
.
code
==
200
{
callback
(
true
,
nil
)
}
else
{
let
err
=
YHErrorModel
(
errorCode
:
Int32
(
json
.
code
),
errorMsg
:
json
.
msg
.
isEmpty
?
""
:
json
.
msg
)
callback
(
false
,
err
)
}
}
failBlock
:
{
err
in
callback
(
false
,
err
)
}
}
}
}
galaxy/galaxy/Classes/Tools/NetWork/YHAllApiName.swift
View file @
8079abe0
...
@@ -676,5 +676,9 @@ class YHAllApiName {
...
@@ -676,5 +676,9 @@ class YHAllApiName {
static
let
categoryList
=
"super-app/goods/category-list"
static
let
categoryList
=
"super-app/goods/category-list"
static
let
goodsList
=
"super-app/goods/list"
static
let
goodsList
=
"super-app/goods/list"
// 离开直播间
static
let
leaveLiveRoom
=
"super-app/live/app-live-exit"
// 进入直播间--需求登录
static
let
joinLiveRoom
=
"super-app/live/app-live-join"
}
}
}
}
galaxy/galaxy/Res/Assets.xcassets/YinHeLive/live_win_close.imageset/Contents.json
0 → 100644
View file @
8079abe0
{
"images"
:
[
{
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"filename"
:
"live_win_close@2x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"filename"
:
"live_win_close@3x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
galaxy/galaxy/Res/Assets.xcassets/YinHeLive/live_win_close.imageset/live_win_close@2x.png
0 → 100644
View file @
8079abe0
751 Bytes
galaxy/galaxy/Res/Assets.xcassets/YinHeLive/live_win_close.imageset/live_win_close@3x.png
0 → 100644
View file @
8079abe0
958 Bytes
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment