菜单类型
1、首页点击更多按钮弹起的菜单:FunctionView。
2、详情页点击更多按钮弹出的菜单:YYWMenuView。
3、长按webview中的链接弹出的菜单:YYWContextMenuHelp.swift。
具体实现
-
FunctionView
界面由nib搭建。view加在mainviewcontroller的view中。
通过以下代码来隐藏和显示,有动画效果。
部分按钮在首页时置灰不可点击。
该菜单的具体功能实现全由PageViewManager代理实现。
func showFunctionBar(_ sender: UIButton)
{
guard self.functionView.isAnimatting == false else {
return
}
self.mainViewController().view.bringSubview(toFront: self.functionView)
let show = self.functionView.contentViewBottomAL.constant < 0
self.functionView.isHidden = false
self.functionView.isAnimatting = true
if show
{
self.functionView.showAnimation()
MobClick.event("homeToolBar_showMenu")
let enabled = MainViewFacade.sharedInstance.isNotHomeWebPage()
self.setUpButtonEnabled(functionView.addBookmarkButton, label: functionView.addBookmarkLabel, enabled: enabled)
self.setUpButtonEnabled(functionView.shareBtn, label: functionView.shareLabel, enabled: enabled)
self.setUpButtonEnabled(functionView.webSnapShotButton, label: functionView.webSnapShotLabel, enabled: enabled)
self.setUpButtonEnabled(functionView.refreshBtn, label: functionView.refreshLabel, enabled: enabled)
}
else
{
self.functionView.hideAnimation()
}
self.functionView.contentView.layoutIfNeeded()
}
- ** YYWMenuView**
该菜单是添加在window上的,因此全局调用一次show方法即可显示出来。
该枚举代表显示的位置,不同类型显示不同的菜单项。
enum contentType: Int {
case home = 0//
case web
case card
}
switch ctype {
case .home:
self.menuItems = [
YYWMenuItem(defaultType: .accountStatus),
YYWMenuItem(defaultType: .bookmarkHistiry),
YYWMenuItem(defaultType: .setting)
]
break
case .web:
self.menuItems = [
YYWMenuItem(defaultType: .accountStatus),
YYWMenuItem(defaultType: .setting),
YYWMenuItem(defaultType: .capture),
YYWMenuItem(defaultType: .copyLink),
YYWMenuItem(defaultType: .bookmarkHistiry),
YYWMenuItem(defaultType: .addBookmark)
]
case .card:
self.menuItems = [
YYWMenuItem(defaultType: .setFont),
YYWMenuItem(defaultType: .feedback)
]
break
}
各菜单项对应的title与image已经预先定义好。
init(defaultType: YYWMenuItemType) {
type = defaultType
switch type {
case .accountStatus:
title = NSLocalizedString("未登录", comment: "")
image = UIImage(named: "menu_visitor")!
case .setting:
title = NSLocalizedString("设置", comment: "")
image = UIImage(named: "menu_setting")!
case .darkModel:
title = NSLocalizedString("夜间模式", comment: "")
image = UIImage(named: "menu_night")!
case .capture:
title = NSLocalizedString("截图", comment: "")
image = UIImage(named: "menu_screenshot")!
case .copyLink:
title = NSLocalizedString("复制链接", comment: "")
image = UIImage(named: "menu_copy")!
case .cloudOof:
title = NSLocalizedString("收藏到115", comment: "")
image = UIImage(named: "menu_star")!
case .bookmarkHistiry:
title = NSLocalizedString("书签/历史", comment: "")
image = UIImage(named: "menu_sc")!
case .addBookmark:
title = NSLocalizedString("添加书签", comment: "")
image = UIImage(named: "menu_bookmark")!
case .setFont:
title = NSLocalizedString("字体设置", comment: "")
image = UIImage(named: "menu_font")!
case .feedback:
title = NSLocalizedString("意见反馈", comment: "")
image = UIImage(named: "menu_edit")!
case .itemType:
assert(true, "itemType 不是默认类型, 使用上面那个方法初始化。")
title = ""
image = UIImage()
}
super.init()
}
因此初始化时指定type,显示方向type,以及一个block。
init(archorView: UIView, contentType ctype: contentType, directionType dtype: directionType, action: @escaping YYWMenuAction)
// block定义 回调时返回点击的type项,根据该type处理事件。
typealias YYWMenuAction = (YYWMenuItemType) -> Void
-
YYWContextMenuHelp
该弹层使用系统自带的UIAlertController实现。
根据以下方法获取的webview元素决定显示哪些弹层。
userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
YYWContextMenuHelp.Elements(link: linkURL, image: imageURL, imageUrls: self.allImagesUrl, linkText: linkText)
创建代码
func contextMenuHelper(_ elements: Elements, cookie:String?, gestureRecognizer: UILongPressGestureRecognizer) {
// locationInView can return (0, 0) when the long press is triggered in an invalid page
// state (e.g., long pressing a link before the document changes, then releasing after a
// different page loads).
guard let navigationController = UIApplication.shared.delegate?.window??.rootViewController as? UINavigationController else { return }
guard let mainViewController = navigationController.viewControllers.first as? MainViewController else { return }
let view = MainViewFacade.sharedInstance.currentPageView()
let touchPoint = view.tabWebView!.gestureRecognizer.location(in: view)
guard touchPoint != CGPoint.zero else { return }
let touchSize = CGSize(width: 0, height: 16)
let actionSheetController = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
var dialogTitle: String?
if let url = elements.link, let imageUrl = elements.image {//长按链接与图片
dialogTitle = url.absoluteString
if dialogTitle?.hasPrefix("javascript:") == true {
return
}
if dialogTitle?.characters.count > 0{
if !view.isPushPageView {
actionSheetController.addAction(openNewTabAction(url, mainViewController))
}
actionSheetController.addAction(copyAction(url))
actionSheetController.addAction(shareAction(url.absoluteString,elements.linkText ?? ""))
actionSheetController.addAction(saveImageAction(imageUrl, cookie ?? ""))
actionSheetController.addAction(shareImageAction(imageUrl, cookie ?? ""))
actionSheetController.addAction(browserImageAction(imageUrl, elements, cookie ?? "", mainViewController))
// if let _ = UserDefaults.standard.object(forKey: "defaults_user_authdata"), !imageUrl.absoluteString.hasPrefix("data:image/") {
// actionSheetController.addAction(cloudImageAction(imageUrl))
// }
}
} else if let url = elements.link {///长按链接
dialogTitle = url.absoluteString
if dialogTitle?.hasPrefix("javascript:") == true {
return
}
if dialogTitle?.characters.count > 0{
// actionSheetController.addAction(openNewTabAction(url, mainViewController))
if !view.isPushPageView {
if (yywFunctionMatch != "" && url.absoluteString.hasPrefix(yywFunctionMatch) == true)
{
var originalString = url.absoluteString
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
originalString = "http://115.com/lx?mag="
originalString = originalString + (escapedString ?? "")
if let strUrl = URL(string: originalString){
actionSheetController.addAction(openNewTabAction(strUrl, mainViewController))
}
} else {
actionSheetController.addAction(openNewTabAction(url, mainViewController))
}
}
actionSheetController.addAction(copyAction(url))
actionSheetController.addAction(copyLinkTextAction(elements.linkText ?? ""))
actionSheetController.addAction(shareAction(url.absoluteString,elements.linkText ?? ""))
}
} else if let imageUrl = elements.image {//长按图片
if dialogTitle == nil {
dialogTitle = imageUrl.absoluteString
}
dialogTitle = ""
actionSheetController.addAction(browserImageAction(imageUrl, elements, cookie ?? "", mainViewController))
actionSheetController.addAction(saveImageAction(imageUrl, cookie ?? ""))
actionSheetController.addAction(shareImageAction(imageUrl, cookie ?? ""))
// if let _ = UserDefaults.standard.object(forKey: "defaults_user_authdata"), !imageUrl.absoluteString.hasPrefix("data:image/") {
// actionSheetController.addAction(cloudImageAction(imageUrl))
// }
}
// If we're showing an arrow popup, set the anchor to the long press location.
if let popoverPresentationController = actionSheetController.popoverPresentationController {
popoverPresentationController.delegate = self
popoverPresentationController.sourceView = view
popoverPresentationController.sourceRect = CGRect(origin: touchPoint, size: touchSize)
popoverPresentationController.permittedArrowDirections = .any
}
if dialogTitle != nil && dialogTitle?.characters.count > 0 {
actionSheetController.title = dialogTitle?.ellipsize(maxLength: 120)
}
let cancelAction = UIAlertAction(title: "取消", style: UIAlertActionStyle.cancel, handler: nil).changeAlertActionTextColor()
actionSheetController.addAction(cancelAction)
if let navVc = mainViewController.presentedViewController as? UINavigationController {
navVc.present(actionSheetController, animated: true, completion: nil)
} else {
mainViewController.present(actionSheetController, animated: true, completion: nil)
}
}
旋转屏幕时会将弹出收起。模仿UC做法。