New file |
| | |
| | | The MIT License (MIT) |
| | | |
| | | Copyright (c) 2016 Popover (https://github.com/lifution) |
| | | |
| | | Permission is hereby granted, free of charge, to any person obtaining a copy |
| | | of this software and associated documentation files (the "Software"), to deal |
| | | in the Software without restriction, including without limitation the rights |
| | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | | copies of the Software, and to permit persons to whom the Software is |
| | | furnished to do so, subject to the following conditions: |
| | | |
| | | The above copyright notice and this permission notice shall be included in |
| | | all copies or substantial portions of the Software. |
| | | |
| | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| | | THE SOFTWARE. |
New file |
| | |
| | | Pod::Spec.new do |s| |
| | | s.name = "Popover" |
| | | s.version = "1.0" |
| | | s.summary = "A simple Popover of Menu" |
| | | s.license = { :type => "MIT", :file => "LICENSE" } |
| | | s.homepage = "https://github.com/lifution/Popover" |
| | | s.author = { "Steven" => "https://github.com/lifution" } |
| | | s.source = { :git => "https://github.com/lifution/Popover.git", :tag => "1.0.0" } |
| | | s.requires_arc = true |
| | | s.platform = :ios, "6.0" |
| | | s.source_files = "PopoverView/*", "*.{h,m}" |
| | | end |
New file |
| | |
| | | // !$*UTF8*$! |
| | | { |
| | | archiveVersion = 1; |
| | | classes = { |
| | | }; |
| | | objectVersion = 46; |
| | | objects = { |
| | | |
| | | /* Begin PBXBuildFile section */ |
| | | B057A05C1E013E180076287C /* PopoverAction.m in Sources */ = {isa = PBXBuildFile; fileRef = B057A0571E013E180076287C /* PopoverAction.m */; }; |
| | | B057A05D1E013E180076287C /* PopoverView.m in Sources */ = {isa = PBXBuildFile; fileRef = B057A0591E013E180076287C /* PopoverView.m */; }; |
| | | B057A05E1E013E180076287C /* PopoverViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B057A05B1E013E180076287C /* PopoverViewCell.m */; }; |
| | | DEF76E691C3B863C00CC7AF9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DEF76E681C3B863C00CC7AF9 /* main.m */; }; |
| | | DEF76E6C1C3B863C00CC7AF9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DEF76E6B1C3B863C00CC7AF9 /* AppDelegate.m */; }; |
| | | DEF76E6F1C3B863C00CC7AF9 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DEF76E6E1C3B863C00CC7AF9 /* ViewController.m */; }; |
| | | DEF76E721C3B863C00CC7AF9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DEF76E701C3B863C00CC7AF9 /* Main.storyboard */; }; |
| | | DEF76E741C3B863C00CC7AF9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DEF76E731C3B863C00CC7AF9 /* Assets.xcassets */; }; |
| | | DEF76E771C3B863C00CC7AF9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DEF76E751C3B863C00CC7AF9 /* LaunchScreen.storyboard */; }; |
| | | /* End PBXBuildFile section */ |
| | | |
| | | /* Begin PBXFileReference section */ |
| | | B057A0561E013E180076287C /* PopoverAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopoverAction.h; sourceTree = "<group>"; }; |
| | | B057A0571E013E180076287C /* PopoverAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PopoverAction.m; sourceTree = "<group>"; }; |
| | | B057A0581E013E180076287C /* PopoverView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopoverView.h; sourceTree = "<group>"; }; |
| | | B057A0591E013E180076287C /* PopoverView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PopoverView.m; sourceTree = "<group>"; }; |
| | | B057A05A1E013E180076287C /* PopoverViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopoverViewCell.h; sourceTree = "<group>"; }; |
| | | B057A05B1E013E180076287C /* PopoverViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PopoverViewCell.m; sourceTree = "<group>"; }; |
| | | DEF76E641C3B863C00CC7AF9 /* Popover.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Popover.app; sourceTree = BUILT_PRODUCTS_DIR; }; |
| | | DEF76E681C3B863C00CC7AF9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; |
| | | DEF76E6A1C3B863C00CC7AF9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; |
| | | DEF76E6B1C3B863C00CC7AF9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; }; |
| | | DEF76E6D1C3B863C00CC7AF9 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; }; |
| | | DEF76E6E1C3B863C00CC7AF9 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; }; |
| | | DEF76E711C3B863C00CC7AF9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; |
| | | DEF76E731C3B863C00CC7AF9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; |
| | | DEF76E761C3B863C00CC7AF9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; |
| | | DEF76E781C3B863C00CC7AF9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; |
| | | /* End PBXFileReference section */ |
| | | |
| | | /* Begin PBXFrameworksBuildPhase section */ |
| | | DEF76E611C3B863C00CC7AF9 /* Frameworks */ = { |
| | | isa = PBXFrameworksBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | files = ( |
| | | ); |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | }; |
| | | /* End PBXFrameworksBuildPhase section */ |
| | | |
| | | /* Begin PBXGroup section */ |
| | | B057A0551E013E180076287C /* PopoverView */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | B057A0581E013E180076287C /* PopoverView.h */, |
| | | B057A0591E013E180076287C /* PopoverView.m */, |
| | | B057A05A1E013E180076287C /* PopoverViewCell.h */, |
| | | B057A05B1E013E180076287C /* PopoverViewCell.m */, |
| | | B057A0561E013E180076287C /* PopoverAction.h */, |
| | | B057A0571E013E180076287C /* PopoverAction.m */, |
| | | ); |
| | | path = PopoverView; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | DEF76E5B1C3B863C00CC7AF9 = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | DEF76E661C3B863C00CC7AF9 /* Popover */, |
| | | DEF76E651C3B863C00CC7AF9 /* Products */, |
| | | ); |
| | | sourceTree = "<group>"; |
| | | }; |
| | | DEF76E651C3B863C00CC7AF9 /* Products */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | DEF76E641C3B863C00CC7AF9 /* Popover.app */, |
| | | ); |
| | | name = Products; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | DEF76E661C3B863C00CC7AF9 /* Popover */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | B057A0551E013E180076287C /* PopoverView */, |
| | | DEF76E6A1C3B863C00CC7AF9 /* AppDelegate.h */, |
| | | DEF76E6B1C3B863C00CC7AF9 /* AppDelegate.m */, |
| | | DEF76E6D1C3B863C00CC7AF9 /* ViewController.h */, |
| | | DEF76E6E1C3B863C00CC7AF9 /* ViewController.m */, |
| | | DEF76E701C3B863C00CC7AF9 /* Main.storyboard */, |
| | | DEF76E731C3B863C00CC7AF9 /* Assets.xcassets */, |
| | | DEF76E751C3B863C00CC7AF9 /* LaunchScreen.storyboard */, |
| | | DEF76E781C3B863C00CC7AF9 /* Info.plist */, |
| | | DEF76E671C3B863C00CC7AF9 /* Supporting Files */, |
| | | ); |
| | | path = Popover; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | DEF76E671C3B863C00CC7AF9 /* Supporting Files */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | DEF76E681C3B863C00CC7AF9 /* main.m */, |
| | | ); |
| | | name = "Supporting Files"; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | /* End PBXGroup section */ |
| | | |
| | | /* Begin PBXNativeTarget section */ |
| | | DEF76E631C3B863C00CC7AF9 /* Popover */ = { |
| | | isa = PBXNativeTarget; |
| | | buildConfigurationList = DEF76E7B1C3B863C00CC7AF9 /* Build configuration list for PBXNativeTarget "Popover" */; |
| | | buildPhases = ( |
| | | DEF76E601C3B863C00CC7AF9 /* Sources */, |
| | | DEF76E611C3B863C00CC7AF9 /* Frameworks */, |
| | | DEF76E621C3B863C00CC7AF9 /* Resources */, |
| | | ); |
| | | buildRules = ( |
| | | ); |
| | | dependencies = ( |
| | | ); |
| | | name = Popover; |
| | | productName = Popover; |
| | | productReference = DEF76E641C3B863C00CC7AF9 /* Popover.app */; |
| | | productType = "com.apple.product-type.application"; |
| | | }; |
| | | /* End PBXNativeTarget section */ |
| | | |
| | | /* Begin PBXProject section */ |
| | | DEF76E5C1C3B863C00CC7AF9 /* Project object */ = { |
| | | isa = PBXProject; |
| | | attributes = { |
| | | LastUpgradeCheck = 0720; |
| | | ORGANIZATIONNAME = lifution; |
| | | TargetAttributes = { |
| | | DEF76E631C3B863C00CC7AF9 = { |
| | | CreatedOnToolsVersion = 7.2; |
| | | DevelopmentTeam = Q5668NKEBD; |
| | | ProvisioningStyle = Automatic; |
| | | }; |
| | | }; |
| | | }; |
| | | buildConfigurationList = DEF76E5F1C3B863C00CC7AF9 /* Build configuration list for PBXProject "Popover" */; |
| | | compatibilityVersion = "Xcode 3.2"; |
| | | developmentRegion = English; |
| | | hasScannedForEncodings = 0; |
| | | knownRegions = ( |
| | | en, |
| | | Base, |
| | | ); |
| | | mainGroup = DEF76E5B1C3B863C00CC7AF9; |
| | | productRefGroup = DEF76E651C3B863C00CC7AF9 /* Products */; |
| | | projectDirPath = ""; |
| | | projectRoot = ""; |
| | | targets = ( |
| | | DEF76E631C3B863C00CC7AF9 /* Popover */, |
| | | ); |
| | | }; |
| | | /* End PBXProject section */ |
| | | |
| | | /* Begin PBXResourcesBuildPhase section */ |
| | | DEF76E621C3B863C00CC7AF9 /* Resources */ = { |
| | | isa = PBXResourcesBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | files = ( |
| | | DEF76E771C3B863C00CC7AF9 /* LaunchScreen.storyboard in Resources */, |
| | | DEF76E741C3B863C00CC7AF9 /* Assets.xcassets in Resources */, |
| | | DEF76E721C3B863C00CC7AF9 /* Main.storyboard in Resources */, |
| | | ); |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | }; |
| | | /* End PBXResourcesBuildPhase section */ |
| | | |
| | | /* Begin PBXSourcesBuildPhase section */ |
| | | DEF76E601C3B863C00CC7AF9 /* Sources */ = { |
| | | isa = PBXSourcesBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | files = ( |
| | | B057A05E1E013E180076287C /* PopoverViewCell.m in Sources */, |
| | | DEF76E6F1C3B863C00CC7AF9 /* ViewController.m in Sources */, |
| | | B057A05D1E013E180076287C /* PopoverView.m in Sources */, |
| | | DEF76E6C1C3B863C00CC7AF9 /* AppDelegate.m in Sources */, |
| | | DEF76E691C3B863C00CC7AF9 /* main.m in Sources */, |
| | | B057A05C1E013E180076287C /* PopoverAction.m in Sources */, |
| | | ); |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | }; |
| | | /* End PBXSourcesBuildPhase section */ |
| | | |
| | | /* Begin PBXVariantGroup section */ |
| | | DEF76E701C3B863C00CC7AF9 /* Main.storyboard */ = { |
| | | isa = PBXVariantGroup; |
| | | children = ( |
| | | DEF76E711C3B863C00CC7AF9 /* Base */, |
| | | ); |
| | | name = Main.storyboard; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | DEF76E751C3B863C00CC7AF9 /* LaunchScreen.storyboard */ = { |
| | | isa = PBXVariantGroup; |
| | | children = ( |
| | | DEF76E761C3B863C00CC7AF9 /* Base */, |
| | | ); |
| | | name = LaunchScreen.storyboard; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | /* End PBXVariantGroup section */ |
| | | |
| | | /* Begin XCBuildConfiguration section */ |
| | | DEF76E791C3B863C00CC7AF9 /* Debug */ = { |
| | | isa = XCBuildConfiguration; |
| | | buildSettings = { |
| | | ALWAYS_SEARCH_USER_PATHS = NO; |
| | | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; |
| | | CLANG_CXX_LIBRARY = "libc++"; |
| | | CLANG_ENABLE_MODULES = YES; |
| | | CLANG_ENABLE_OBJC_ARC = YES; |
| | | CLANG_WARN_BOOL_CONVERSION = YES; |
| | | CLANG_WARN_CONSTANT_CONVERSION = YES; |
| | | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
| | | CLANG_WARN_EMPTY_BODY = YES; |
| | | CLANG_WARN_ENUM_CONVERSION = YES; |
| | | CLANG_WARN_INT_CONVERSION = YES; |
| | | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
| | | CLANG_WARN_UNREACHABLE_CODE = YES; |
| | | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; |
| | | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; |
| | | COPY_PHASE_STRIP = NO; |
| | | DEBUG_INFORMATION_FORMAT = dwarf; |
| | | ENABLE_STRICT_OBJC_MSGSEND = YES; |
| | | ENABLE_TESTABILITY = YES; |
| | | GCC_C_LANGUAGE_STANDARD = gnu99; |
| | | GCC_DYNAMIC_NO_PIC = NO; |
| | | GCC_NO_COMMON_BLOCKS = YES; |
| | | GCC_OPTIMIZATION_LEVEL = 0; |
| | | GCC_PREPROCESSOR_DEFINITIONS = ( |
| | | "DEBUG=1", |
| | | "$(inherited)", |
| | | ); |
| | | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
| | | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
| | | GCC_WARN_UNDECLARED_SELECTOR = YES; |
| | | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
| | | GCC_WARN_UNUSED_FUNCTION = YES; |
| | | GCC_WARN_UNUSED_VARIABLE = YES; |
| | | IPHONEOS_DEPLOYMENT_TARGET = 7.0; |
| | | MTL_ENABLE_DEBUG_INFO = YES; |
| | | ONLY_ACTIVE_ARCH = YES; |
| | | SDKROOT = iphoneos; |
| | | }; |
| | | name = Debug; |
| | | }; |
| | | DEF76E7A1C3B863C00CC7AF9 /* Release */ = { |
| | | isa = XCBuildConfiguration; |
| | | buildSettings = { |
| | | ALWAYS_SEARCH_USER_PATHS = NO; |
| | | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; |
| | | CLANG_CXX_LIBRARY = "libc++"; |
| | | CLANG_ENABLE_MODULES = YES; |
| | | CLANG_ENABLE_OBJC_ARC = YES; |
| | | CLANG_WARN_BOOL_CONVERSION = YES; |
| | | CLANG_WARN_CONSTANT_CONVERSION = YES; |
| | | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
| | | CLANG_WARN_EMPTY_BODY = YES; |
| | | CLANG_WARN_ENUM_CONVERSION = YES; |
| | | CLANG_WARN_INT_CONVERSION = YES; |
| | | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
| | | CLANG_WARN_UNREACHABLE_CODE = YES; |
| | | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; |
| | | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; |
| | | COPY_PHASE_STRIP = NO; |
| | | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
| | | ENABLE_NS_ASSERTIONS = NO; |
| | | ENABLE_STRICT_OBJC_MSGSEND = YES; |
| | | GCC_C_LANGUAGE_STANDARD = gnu99; |
| | | GCC_NO_COMMON_BLOCKS = YES; |
| | | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
| | | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
| | | GCC_WARN_UNDECLARED_SELECTOR = YES; |
| | | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
| | | GCC_WARN_UNUSED_FUNCTION = YES; |
| | | GCC_WARN_UNUSED_VARIABLE = YES; |
| | | IPHONEOS_DEPLOYMENT_TARGET = 7.0; |
| | | MTL_ENABLE_DEBUG_INFO = NO; |
| | | SDKROOT = iphoneos; |
| | | VALIDATE_PRODUCT = YES; |
| | | }; |
| | | name = Release; |
| | | }; |
| | | DEF76E7C1C3B863C00CC7AF9 /* Debug */ = { |
| | | isa = XCBuildConfiguration; |
| | | buildSettings = { |
| | | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| | | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; |
| | | DEVELOPMENT_TEAM = Q5668NKEBD; |
| | | INFOPLIST_FILE = Popover/Info.plist; |
| | | IPHONEOS_DEPLOYMENT_TARGET = 7.0; |
| | | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; |
| | | PRODUCT_BUNDLE_IDENTIFIER = com.lifution.Popover; |
| | | PRODUCT_NAME = "$(TARGET_NAME)"; |
| | | }; |
| | | name = Debug; |
| | | }; |
| | | DEF76E7D1C3B863C00CC7AF9 /* Release */ = { |
| | | isa = XCBuildConfiguration; |
| | | buildSettings = { |
| | | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| | | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; |
| | | DEVELOPMENT_TEAM = Q5668NKEBD; |
| | | INFOPLIST_FILE = Popover/Info.plist; |
| | | IPHONEOS_DEPLOYMENT_TARGET = 7.0; |
| | | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; |
| | | PRODUCT_BUNDLE_IDENTIFIER = com.lifution.Popover; |
| | | PRODUCT_NAME = "$(TARGET_NAME)"; |
| | | }; |
| | | name = Release; |
| | | }; |
| | | /* End XCBuildConfiguration section */ |
| | | |
| | | /* Begin XCConfigurationList section */ |
| | | DEF76E5F1C3B863C00CC7AF9 /* Build configuration list for PBXProject "Popover" */ = { |
| | | isa = XCConfigurationList; |
| | | buildConfigurations = ( |
| | | DEF76E791C3B863C00CC7AF9 /* Debug */, |
| | | DEF76E7A1C3B863C00CC7AF9 /* Release */, |
| | | ); |
| | | defaultConfigurationIsVisible = 0; |
| | | defaultConfigurationName = Release; |
| | | }; |
| | | DEF76E7B1C3B863C00CC7AF9 /* Build configuration list for PBXNativeTarget "Popover" */ = { |
| | | isa = XCConfigurationList; |
| | | buildConfigurations = ( |
| | | DEF76E7C1C3B863C00CC7AF9 /* Debug */, |
| | | DEF76E7D1C3B863C00CC7AF9 /* Release */, |
| | | ); |
| | | defaultConfigurationIsVisible = 0; |
| | | defaultConfigurationName = Release; |
| | | }; |
| | | /* End XCConfigurationList section */ |
| | | }; |
| | | rootObject = DEF76E5C1C3B863C00CC7AF9 /* Project object */; |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Workspace |
| | | version = "1.0"> |
| | | <FileRef |
| | | location = "self:Popover.xcodeproj"> |
| | | </FileRef> |
| | | </Workspace> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>BuildLocationStyle</key> |
| | | <string>UseAppPreferences</string> |
| | | <key>CustomBuildLocationType</key> |
| | | <string>RelativeToDerivedData</string> |
| | | <key>DerivedDataLocationStyle</key> |
| | | <string>Default</string> |
| | | <key>IssueFilterStyle</key> |
| | | <string>ShowActiveSchemeOnly</string> |
| | | <key>LiveSourceIssuesEnabled</key> |
| | | <true/> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Bucket |
| | | type = "1" |
| | | version = "2.0"> |
| | | <Breakpoints> |
| | | <BreakpointProxy |
| | | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> |
| | | <BreakpointContent |
| | | shouldBeEnabled = "Yes" |
| | | ignoreCount = "0" |
| | | continueAfterRunningActions = "No" |
| | | filePath = "Popover/ViewController.m" |
| | | timestampString = "504146319.593284" |
| | | startingColumnNumber = "9223372036854775807" |
| | | endingColumnNumber = "9223372036854775807" |
| | | startingLineNumber = "60" |
| | | endingLineNumber = "60" |
| | | landmarkName = "-leftBarItemAction:" |
| | | landmarkType = "7"> |
| | | </BreakpointContent> |
| | | </BreakpointProxy> |
| | | <BreakpointProxy |
| | | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> |
| | | <BreakpointContent |
| | | shouldBeEnabled = "Yes" |
| | | ignoreCount = "0" |
| | | continueAfterRunningActions = "No" |
| | | filePath = "Popover/ViewController.m" |
| | | timestampString = "504146324.272892" |
| | | startingColumnNumber = "9223372036854775807" |
| | | endingColumnNumber = "9223372036854775807" |
| | | startingLineNumber = "30" |
| | | endingLineNumber = "30" |
| | | landmarkName = "-QQActions" |
| | | landmarkType = "7"> |
| | | </BreakpointContent> |
| | | </BreakpointProxy> |
| | | <BreakpointProxy |
| | | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> |
| | | <BreakpointContent |
| | | shouldBeEnabled = "Yes" |
| | | ignoreCount = "0" |
| | | continueAfterRunningActions = "No" |
| | | filePath = "Popover/ViewController.m" |
| | | timestampString = "504146330.570631" |
| | | startingColumnNumber = "9223372036854775807" |
| | | endingColumnNumber = "9223372036854775807" |
| | | startingLineNumber = "87" |
| | | endingLineNumber = "87" |
| | | landmarkName = "-showWithoutImage:" |
| | | landmarkType = "7"> |
| | | </BreakpointContent> |
| | | </BreakpointProxy> |
| | | <BreakpointProxy |
| | | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> |
| | | <BreakpointContent |
| | | shouldBeEnabled = "Yes" |
| | | ignoreCount = "0" |
| | | continueAfterRunningActions = "No" |
| | | filePath = "Popover/ViewController.m" |
| | | timestampString = "504146335.428569" |
| | | startingColumnNumber = "9223372036854775807" |
| | | endingColumnNumber = "9223372036854775807" |
| | | startingLineNumber = "80" |
| | | endingLineNumber = "80" |
| | | landmarkName = "-rightButtonAction:" |
| | | landmarkType = "7"> |
| | | </BreakpointContent> |
| | | </BreakpointProxy> |
| | | <BreakpointProxy |
| | | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> |
| | | <BreakpointContent |
| | | shouldBeEnabled = "Yes" |
| | | ignoreCount = "0" |
| | | continueAfterRunningActions = "No" |
| | | filePath = "Popover/ViewController.m" |
| | | timestampString = "504146713.885408" |
| | | startingColumnNumber = "9223372036854775807" |
| | | endingColumnNumber = "9223372036854775807" |
| | | startingLineNumber = "56" |
| | | endingLineNumber = "56" |
| | | landmarkName = "-buttonAction:" |
| | | landmarkType = "7"> |
| | | </BreakpointContent> |
| | | </BreakpointProxy> |
| | | </Breakpoints> |
| | | </Bucket> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Scheme |
| | | LastUpgradeVersion = "0810" |
| | | version = "1.3"> |
| | | <BuildAction |
| | | parallelizeBuildables = "YES" |
| | | buildImplicitDependencies = "YES"> |
| | | <BuildActionEntries> |
| | | <BuildActionEntry |
| | | buildForTesting = "YES" |
| | | buildForRunning = "YES" |
| | | buildForProfiling = "YES" |
| | | buildForArchiving = "YES" |
| | | buildForAnalyzing = "YES"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildActionEntry> |
| | | </BuildActionEntries> |
| | | </BuildAction> |
| | | <TestAction |
| | | buildConfiguration = "Debug" |
| | | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
| | | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
| | | shouldUseLaunchSchemeArgsEnv = "YES"> |
| | | <Testables> |
| | | </Testables> |
| | | <MacroExpansion> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </MacroExpansion> |
| | | <AdditionalOptions> |
| | | </AdditionalOptions> |
| | | </TestAction> |
| | | <LaunchAction |
| | | buildConfiguration = "Debug" |
| | | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
| | | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
| | | launchStyle = "0" |
| | | useCustomWorkingDirectory = "NO" |
| | | ignoresPersistentStateOnLaunch = "NO" |
| | | debugDocumentVersioning = "YES" |
| | | debugServiceExtension = "internal" |
| | | allowLocationSimulation = "YES"> |
| | | <BuildableProductRunnable |
| | | runnableDebuggingMode = "0"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildableProductRunnable> |
| | | <AdditionalOptions> |
| | | </AdditionalOptions> |
| | | </LaunchAction> |
| | | <ProfileAction |
| | | buildConfiguration = "Release" |
| | | shouldUseLaunchSchemeArgsEnv = "YES" |
| | | savedToolIdentifier = "" |
| | | useCustomWorkingDirectory = "NO" |
| | | debugDocumentVersioning = "YES"> |
| | | <BuildableProductRunnable |
| | | runnableDebuggingMode = "0"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildableProductRunnable> |
| | | </ProfileAction> |
| | | <AnalyzeAction |
| | | buildConfiguration = "Debug"> |
| | | </AnalyzeAction> |
| | | <ArchiveAction |
| | | buildConfiguration = "Release" |
| | | revealArchiveInOrganizer = "YES"> |
| | | </ArchiveAction> |
| | | </Scheme> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>SchemeUserState</key> |
| | | <dict> |
| | | <key>Popover.xcscheme</key> |
| | | <dict> |
| | | <key>orderHint</key> |
| | | <integer>0</integer> |
| | | </dict> |
| | | </dict> |
| | | <key>SuppressBuildableAutocreation</key> |
| | | <dict> |
| | | <key>DEF76E631C3B863C00CC7AF9</key> |
| | | <dict> |
| | | <key>primary</key> |
| | | <true/> |
| | | </dict> |
| | | </dict> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Bucket |
| | | type = "1" |
| | | version = "2.0"> |
| | | </Bucket> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Scheme |
| | | LastUpgradeVersion = "0720" |
| | | version = "1.3"> |
| | | <BuildAction |
| | | parallelizeBuildables = "YES" |
| | | buildImplicitDependencies = "YES"> |
| | | <BuildActionEntries> |
| | | <BuildActionEntry |
| | | buildForTesting = "YES" |
| | | buildForRunning = "YES" |
| | | buildForProfiling = "YES" |
| | | buildForArchiving = "YES" |
| | | buildForAnalyzing = "YES"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildActionEntry> |
| | | </BuildActionEntries> |
| | | </BuildAction> |
| | | <TestAction |
| | | buildConfiguration = "Debug" |
| | | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
| | | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
| | | shouldUseLaunchSchemeArgsEnv = "YES"> |
| | | <Testables> |
| | | </Testables> |
| | | <MacroExpansion> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </MacroExpansion> |
| | | <AdditionalOptions> |
| | | </AdditionalOptions> |
| | | </TestAction> |
| | | <LaunchAction |
| | | buildConfiguration = "Debug" |
| | | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
| | | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
| | | launchStyle = "0" |
| | | useCustomWorkingDirectory = "NO" |
| | | ignoresPersistentStateOnLaunch = "NO" |
| | | debugDocumentVersioning = "YES" |
| | | debugServiceExtension = "internal" |
| | | allowLocationSimulation = "YES"> |
| | | <BuildableProductRunnable |
| | | runnableDebuggingMode = "0"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildableProductRunnable> |
| | | <AdditionalOptions> |
| | | </AdditionalOptions> |
| | | </LaunchAction> |
| | | <ProfileAction |
| | | buildConfiguration = "Release" |
| | | shouldUseLaunchSchemeArgsEnv = "YES" |
| | | savedToolIdentifier = "" |
| | | useCustomWorkingDirectory = "NO" |
| | | debugDocumentVersioning = "YES"> |
| | | <BuildableProductRunnable |
| | | runnableDebuggingMode = "0"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildableProductRunnable> |
| | | </ProfileAction> |
| | | <AnalyzeAction |
| | | buildConfiguration = "Debug"> |
| | | </AnalyzeAction> |
| | | <ArchiveAction |
| | | buildConfiguration = "Release" |
| | | revealArchiveInOrganizer = "YES"> |
| | | </ArchiveAction> |
| | | </Scheme> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>SchemeUserState</key> |
| | | <dict> |
| | | <key>Popover.xcscheme</key> |
| | | <dict> |
| | | <key>orderHint</key> |
| | | <integer>0</integer> |
| | | </dict> |
| | | </dict> |
| | | <key>SuppressBuildableAutocreation</key> |
| | | <dict> |
| | | <key>DEF76E631C3B863C00CC7AF9</key> |
| | | <dict> |
| | | <key>primary</key> |
| | | <true/> |
| | | </dict> |
| | | </dict> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Bucket |
| | | type = "1" |
| | | version = "2.0"> |
| | | </Bucket> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Scheme |
| | | LastUpgradeVersion = "0810" |
| | | version = "1.3"> |
| | | <BuildAction |
| | | parallelizeBuildables = "YES" |
| | | buildImplicitDependencies = "YES"> |
| | | <BuildActionEntries> |
| | | <BuildActionEntry |
| | | buildForTesting = "YES" |
| | | buildForRunning = "YES" |
| | | buildForProfiling = "YES" |
| | | buildForArchiving = "YES" |
| | | buildForAnalyzing = "YES"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildActionEntry> |
| | | </BuildActionEntries> |
| | | </BuildAction> |
| | | <TestAction |
| | | buildConfiguration = "Debug" |
| | | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
| | | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
| | | shouldUseLaunchSchemeArgsEnv = "YES"> |
| | | <Testables> |
| | | </Testables> |
| | | <MacroExpansion> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </MacroExpansion> |
| | | <AdditionalOptions> |
| | | </AdditionalOptions> |
| | | </TestAction> |
| | | <LaunchAction |
| | | buildConfiguration = "Debug" |
| | | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
| | | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
| | | launchStyle = "0" |
| | | useCustomWorkingDirectory = "NO" |
| | | ignoresPersistentStateOnLaunch = "NO" |
| | | debugDocumentVersioning = "YES" |
| | | debugServiceExtension = "internal" |
| | | allowLocationSimulation = "YES"> |
| | | <BuildableProductRunnable |
| | | runnableDebuggingMode = "0"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildableProductRunnable> |
| | | <AdditionalOptions> |
| | | </AdditionalOptions> |
| | | </LaunchAction> |
| | | <ProfileAction |
| | | buildConfiguration = "Release" |
| | | shouldUseLaunchSchemeArgsEnv = "YES" |
| | | savedToolIdentifier = "" |
| | | useCustomWorkingDirectory = "NO" |
| | | debugDocumentVersioning = "YES"> |
| | | <BuildableProductRunnable |
| | | runnableDebuggingMode = "0"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "DEF76E631C3B863C00CC7AF9" |
| | | BuildableName = "Popover.app" |
| | | BlueprintName = "Popover" |
| | | ReferencedContainer = "container:Popover.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildableProductRunnable> |
| | | </ProfileAction> |
| | | <AnalyzeAction |
| | | buildConfiguration = "Debug"> |
| | | </AnalyzeAction> |
| | | <ArchiveAction |
| | | buildConfiguration = "Release" |
| | | revealArchiveInOrganizer = "YES"> |
| | | </ArchiveAction> |
| | | </Scheme> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>SchemeUserState</key> |
| | | <dict> |
| | | <key>Popover.xcscheme</key> |
| | | <dict> |
| | | <key>orderHint</key> |
| | | <integer>0</integer> |
| | | </dict> |
| | | </dict> |
| | | <key>SuppressBuildableAutocreation</key> |
| | | <dict> |
| | | <key>DEF76E631C3B863C00CC7AF9</key> |
| | | <dict> |
| | | <key>primary</key> |
| | | <true/> |
| | | </dict> |
| | | </dict> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | // |
| | | // AppDelegate.h |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <UIKit/UIKit.h> |
| | | |
| | | @interface AppDelegate : UIResponder <UIApplicationDelegate> |
| | | |
| | | @property (strong, nonatomic) UIWindow *window; |
| | | |
| | | |
| | | @end |
| | | |
New file |
| | |
| | | // |
| | | // AppDelegate.m |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import "AppDelegate.h" |
| | | |
| | | @interface AppDelegate () |
| | | |
| | | @end |
| | | |
| | | @implementation AppDelegate |
| | | |
| | | |
| | | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
| | | // Override point for customization after application launch. |
| | | [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone]; |
| | | return YES; |
| | | } |
| | | |
| | | - (void)applicationWillResignActive:(UIApplication *)application { |
| | | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. |
| | | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. |
| | | } |
| | | |
| | | - (void)applicationDidEnterBackground:(UIApplication *)application { |
| | | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. |
| | | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. |
| | | } |
| | | |
| | | - (void)applicationWillEnterForeground:(UIApplication *)application { |
| | | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. |
| | | } |
| | | |
| | | - (void)applicationDidBecomeActive:(UIApplication *)application { |
| | | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. |
| | | } |
| | | |
| | | - (void)applicationWillTerminate:(UIApplication *)application { |
| | | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. |
| | | } |
| | | |
| | | @end |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "size" : "20x20", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-Notification@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "20x20", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-Notification@3x.png", |
| | | "scale" : "3x" |
| | | }, |
| | | { |
| | | "size" : "29x29", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-Small.png", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "size" : "29x29", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-Small@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "29x29", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-Small@3x.png", |
| | | "scale" : "3x" |
| | | }, |
| | | { |
| | | "size" : "40x40", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-Small-40@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "40x40", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-Small-40@3x.png", |
| | | "scale" : "3x" |
| | | }, |
| | | { |
| | | "size" : "57x57", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon.png", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "size" : "57x57", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "60x60", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-60@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "60x60", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-60@3x.png", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "contacts_add_friend@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "contacts_add_money@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "contacts_add_newmessage@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "contacts_add_scan@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "navigationItem_menu@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "right_menu_QR@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "right_menu_addFri@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "right_menu_facetoface@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "right_menu_multichat@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "right_menu_payMoney@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> |
| | | <device id="retina4_7" orientation="portrait"> |
| | | <adaptation id="fullscreen"/> |
| | | </device> |
| | | <dependencies> |
| | | <deployment identifier="iOS"/> |
| | | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/> |
| | | <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
| | | </dependencies> |
| | | <scenes> |
| | | <!--View Controller--> |
| | | <scene sceneID="EHf-IW-A2E"> |
| | | <objects> |
| | | <viewController id="01J-lp-oVM" sceneMemberID="viewController"> |
| | | <layoutGuides> |
| | | <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/> |
| | | <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/> |
| | | </layoutGuides> |
| | | <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> |
| | | <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> |
| | | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
| | | <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| | | </view> |
| | | </viewController> |
| | | <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> |
| | | </objects> |
| | | <point key="canvasLocation" x="53" y="375"/> |
| | | </scene> |
| | | </scenes> |
| | | </document> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="QBF-Rp-PB9"> |
| | | <device id="retina4_7" orientation="portrait"> |
| | | <adaptation id="fullscreen"/> |
| | | </device> |
| | | <dependencies> |
| | | <deployment identifier="iOS"/> |
| | | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/> |
| | | <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
| | | </dependencies> |
| | | <scenes> |
| | | <!--Navigation Controller--> |
| | | <scene sceneID="KFp-Vm-K4s"> |
| | | <objects> |
| | | <navigationController id="QBF-Rp-PB9" sceneMemberID="viewController"> |
| | | <navigationBar key="navigationBar" contentMode="scaleToFill" translucent="NO" id="Ozy-CH-Lu2"> |
| | | <rect key="frame" x="0.0" y="0.0" width="320" height="44"/> |
| | | <autoresizingMask key="autoresizingMask"/> |
| | | <color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
| | | <color key="barTintColor" red="0.1176470588" green="0.66666666669999997" blue="0.94509803920000002" alpha="1" colorSpace="calibratedRGB"/> |
| | | <textAttributes key="titleTextAttributes"> |
| | | <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
| | | </textAttributes> |
| | | </navigationBar> |
| | | <connections> |
| | | <segue destination="geS-fr-ReB" kind="relationship" relationship="rootViewController" id="EMz-iF-tU4"/> |
| | | </connections> |
| | | </navigationController> |
| | | <placeholder placeholderIdentifier="IBFirstResponder" id="avt-Ud-Iy2" userLabel="First Responder" sceneMemberID="firstResponder"/> |
| | | </objects> |
| | | <point key="canvasLocation" x="266" y="107"/> |
| | | </scene> |
| | | <!--Popover--> |
| | | <scene sceneID="DAI-sZ-Mja"> |
| | | <objects> |
| | | <viewController storyboardIdentifier="ViewController" id="geS-fr-ReB" customClass="ViewController" sceneMemberID="viewController"> |
| | | <layoutGuides> |
| | | <viewControllerLayoutGuide type="top" id="ixD-XH-j9U"/> |
| | | <viewControllerLayoutGuide type="bottom" id="Fy8-B8-FAY"/> |
| | | </layoutGuides> |
| | | <view key="view" contentMode="scaleToFill" id="4BN-3b-jmf"> |
| | | <rect key="frame" x="0.0" y="64" width="375" height="603"/> |
| | | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
| | | <subviews> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CC4-QJ-l9N"> |
| | | <rect key="frame" x="132.5" y="40" width="110" height="32"/> |
| | | <color key="backgroundColor" red="0.1176470588" green="0.66666666669999997" blue="0.94509803920000002" alpha="1" colorSpace="calibratedRGB"/> |
| | | <constraints> |
| | | <constraint firstAttribute="width" constant="110" id="8jt-SV-sGC"/> |
| | | <constraint firstAttribute="height" constant="32" id="nPy-0w-reU"/> |
| | | </constraints> |
| | | <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> |
| | | <state key="normal" title="showPopover"> |
| | | <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
| | | </state> |
| | | <userDefinedRuntimeAttributes> |
| | | <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> |
| | | <integer key="value" value="5"/> |
| | | </userDefinedRuntimeAttribute> |
| | | <userDefinedRuntimeAttribute type="boolean" keyPath="layer.masksToBounds" value="YES"/> |
| | | </userDefinedRuntimeAttributes> |
| | | <connections> |
| | | <action selector="buttonAction:" destination="geS-fr-ReB" eventType="touchUpInside" id="5Fb-xu-qiH"/> |
| | | </connections> |
| | | </button> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="A0b-Ah-o6l"> |
| | | <rect key="frame" x="10" y="531" width="110" height="32"/> |
| | | <color key="backgroundColor" red="1" green="0.50196081400000003" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> |
| | | <constraints> |
| | | <constraint firstAttribute="width" constant="110" id="3Y9-zp-TGA"/> |
| | | <constraint firstAttribute="height" constant="32" id="Lqd-NN-Sqw"/> |
| | | </constraints> |
| | | <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> |
| | | <state key="normal" title="showPopover"> |
| | | <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
| | | </state> |
| | | <userDefinedRuntimeAttributes> |
| | | <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> |
| | | <integer key="value" value="5"/> |
| | | </userDefinedRuntimeAttribute> |
| | | <userDefinedRuntimeAttribute type="boolean" keyPath="layer.masksToBounds" value="YES"/> |
| | | </userDefinedRuntimeAttributes> |
| | | <connections> |
| | | <action selector="buttonAction:" destination="geS-fr-ReB" eventType="touchUpInside" id="EPh-gE-xUy"/> |
| | | </connections> |
| | | </button> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qFV-Z6-rzD"> |
| | | <rect key="frame" x="255" y="531" width="110" height="32"/> |
| | | <color key="backgroundColor" red="0.0" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
| | | <constraints> |
| | | <constraint firstAttribute="height" constant="32" id="OtP-Ah-fdc"/> |
| | | <constraint firstAttribute="width" constant="110" id="xIG-PH-GXB"/> |
| | | </constraints> |
| | | <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> |
| | | <state key="normal" title="showPopover"> |
| | | <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/> |
| | | </state> |
| | | <userDefinedRuntimeAttributes> |
| | | <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> |
| | | <integer key="value" value="5"/> |
| | | </userDefinedRuntimeAttribute> |
| | | <userDefinedRuntimeAttribute type="boolean" keyPath="layer.masksToBounds" value="YES"/> |
| | | </userDefinedRuntimeAttributes> |
| | | <connections> |
| | | <action selector="buttonAction:" destination="geS-fr-ReB" eventType="touchUpInside" id="NsQ-gX-bTF"/> |
| | | </connections> |
| | | </button> |
| | | <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="你选择了" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1cc-Xs-eD0"> |
| | | <rect key="frame" x="154.5" y="292" width="65.5" height="19.5"/> |
| | | <fontDescription key="fontDescription" type="system" pointSize="16"/> |
| | | <nil key="textColor"/> |
| | | <nil key="highlightedColor"/> |
| | | </label> |
| | | <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="944-J4-LAc"> |
| | | <rect key="frame" x="187" y="321.5" width="0.0" height="0.0"/> |
| | | <fontDescription key="fontDescription" type="system" pointSize="16"/> |
| | | <color key="textColor" red="0.98823529409999999" green="0.0" blue="0.0039215686269999999" alpha="1" colorSpace="calibratedRGB"/> |
| | | <nil key="highlightedColor"/> |
| | | </label> |
| | | <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HGk-11-wXz"> |
| | | <rect key="frame" x="132" y="471" width="110" height="32"/> |
| | | <color key="backgroundColor" red="1" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/> |
| | | <constraints> |
| | | <constraint firstAttribute="width" constant="110" id="N4g-ZW-09w"/> |
| | | <constraint firstAttribute="height" constant="32" id="ude-Je-Gk3"/> |
| | | </constraints> |
| | | <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> |
| | | <state key="normal" title="showPopover"> |
| | | <color key="titleColor" red="0.0" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="calibratedRGB"/> |
| | | </state> |
| | | <userDefinedRuntimeAttributes> |
| | | <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius"> |
| | | <integer key="value" value="5"/> |
| | | </userDefinedRuntimeAttribute> |
| | | <userDefinedRuntimeAttribute type="boolean" keyPath="layer.masksToBounds" value="YES"/> |
| | | </userDefinedRuntimeAttributes> |
| | | <connections> |
| | | <action selector="showWithoutImage:" destination="geS-fr-ReB" eventType="touchUpInside" id="1EK-Wb-VAI"/> |
| | | </connections> |
| | | </button> |
| | | </subviews> |
| | | <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
| | | <constraints> |
| | | <constraint firstItem="CC4-QJ-l9N" firstAttribute="centerX" secondItem="4BN-3b-jmf" secondAttribute="centerX" id="4in-U8-RTN"/> |
| | | <constraint firstItem="1cc-Xs-eD0" firstAttribute="centerY" secondItem="4BN-3b-jmf" secondAttribute="centerY" id="Acf-fv-URZ"/> |
| | | <constraint firstItem="1cc-Xs-eD0" firstAttribute="centerX" secondItem="4BN-3b-jmf" secondAttribute="centerX" id="ED4-5N-nn1"/> |
| | | <constraint firstItem="944-J4-LAc" firstAttribute="centerX" secondItem="4BN-3b-jmf" secondAttribute="centerX" id="Esz-eK-vIz"/> |
| | | <constraint firstItem="CC4-QJ-l9N" firstAttribute="top" secondItem="ixD-XH-j9U" secondAttribute="bottom" constant="40" id="IrW-Yt-MNG"/> |
| | | <constraint firstItem="Fy8-B8-FAY" firstAttribute="top" secondItem="HGk-11-wXz" secondAttribute="bottom" constant="100" id="M3e-IM-osS"/> |
| | | <constraint firstItem="A0b-Ah-o6l" firstAttribute="leading" secondItem="4BN-3b-jmf" secondAttribute="leading" constant="10" id="UTc-Ff-sfV"/> |
| | | <constraint firstItem="944-J4-LAc" firstAttribute="top" secondItem="1cc-Xs-eD0" secondAttribute="bottom" constant="10" id="UrE-SB-p9x"/> |
| | | <constraint firstItem="Fy8-B8-FAY" firstAttribute="top" secondItem="qFV-Z6-rzD" secondAttribute="bottom" constant="40" id="WvE-4Z-Zy5"/> |
| | | <constraint firstAttribute="trailing" secondItem="qFV-Z6-rzD" secondAttribute="trailing" constant="10" id="bJJ-Jq-7I8"/> |
| | | <constraint firstItem="HGk-11-wXz" firstAttribute="centerX" secondItem="4BN-3b-jmf" secondAttribute="centerX" id="maw-7u-V55"/> |
| | | <constraint firstItem="Fy8-B8-FAY" firstAttribute="top" secondItem="A0b-Ah-o6l" secondAttribute="bottom" constant="40" id="y51-UC-69M"/> |
| | | </constraints> |
| | | </view> |
| | | <navigationItem key="navigationItem" title="Popover" id="xXS-78-Yrl"> |
| | | <barButtonItem key="leftBarButtonItem" image="navigationItem_menu" id="PKd-xW-kEH"> |
| | | <color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
| | | <connections> |
| | | <action selector="leftBarItemAction:" destination="geS-fr-ReB" id="CYo-d1-lzq"/> |
| | | </connections> |
| | | </barButtonItem> |
| | | <barButtonItem key="rightBarButtonItem" id="HkD-ni-VFq"> |
| | | <button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="yDx-1B-vCI"> |
| | | <rect key="frame" x="334" y="9" width="25" height="25"/> |
| | | <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> |
| | | <color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
| | | <state key="normal" image="navigationItem_menu"/> |
| | | <connections> |
| | | <action selector="rightButtonAction:" destination="geS-fr-ReB" eventType="touchUpInside" id="eVe-39-zS7"/> |
| | | </connections> |
| | | </button> |
| | | <color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
| | | </barButtonItem> |
| | | </navigationItem> |
| | | <connections> |
| | | <outlet property="noticeLabel" destination="944-J4-LAc" id="DfQ-z5-DtL"/> |
| | | </connections> |
| | | </viewController> |
| | | <placeholder placeholderIdentifier="IBFirstResponder" id="rCP-RK-tfJ" userLabel="First Responder" sceneMemberID="firstResponder"/> |
| | | </objects> |
| | | <point key="canvasLocation" x="974" y="107"/> |
| | | </scene> |
| | | </scenes> |
| | | <resources> |
| | | <image name="navigationItem_menu" width="20" height="20"/> |
| | | </resources> |
| | | </document> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>CFBundleDevelopmentRegion</key> |
| | | <string>en</string> |
| | | <key>CFBundleExecutable</key> |
| | | <string>$(EXECUTABLE_NAME)</string> |
| | | <key>CFBundleIdentifier</key> |
| | | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
| | | <key>CFBundleInfoDictionaryVersion</key> |
| | | <string>6.0</string> |
| | | <key>CFBundleName</key> |
| | | <string>$(PRODUCT_NAME)</string> |
| | | <key>CFBundlePackageType</key> |
| | | <string>APPL</string> |
| | | <key>CFBundleShortVersionString</key> |
| | | <string>1.0</string> |
| | | <key>CFBundleSignature</key> |
| | | <string>????</string> |
| | | <key>CFBundleVersion</key> |
| | | <string>1</string> |
| | | <key>LSRequiresIPhoneOS</key> |
| | | <true/> |
| | | <key>UILaunchStoryboardName</key> |
| | | <string>LaunchScreen</string> |
| | | <key>UIMainStoryboardFile</key> |
| | | <string>Main</string> |
| | | <key>UIRequiredDeviceCapabilities</key> |
| | | <array> |
| | | <string>armv7</string> |
| | | </array> |
| | | <key>UIStatusBarHidden</key> |
| | | <true/> |
| | | <key>UIStatusBarStyle</key> |
| | | <string>UIStatusBarStyleLightContent</string> |
| | | <key>UISupportedInterfaceOrientations</key> |
| | | <array> |
| | | <string>UIInterfaceOrientationPortrait</string> |
| | | </array> |
| | | <key>UIViewControllerBasedStatusBarAppearance</key> |
| | | <false/> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | // |
| | | // PopoverAction.h |
| | | // Popover |
| | | // |
| | | // Created by StevenLee on 2016/12/10. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <Foundation/Foundation.h> |
| | | #import <UIKit/UIKit.h> |
| | | |
| | | typedef NS_ENUM(NSUInteger, PopoverViewStyle) |
| | | { |
| | | PopoverViewStyleDefault = 0, // 默认风格, 白色 |
| | | PopoverViewStyleDark, // 黑色风格 |
| | | }; |
| | | |
| | | @interface PopoverAction : NSObject |
| | | |
| | | @property (nonatomic, strong, readonly) UIImage *image; ///< 图标 (建议使用 60pix*60pix 的图片) |
| | | @property (nonatomic, copy, readonly) NSString *title; ///< 标题 |
| | | @property (nonatomic, copy, readonly) void(^handler)(PopoverAction *action); ///< 选择回调, 该Block不会导致内存泄露, Block内代码无需刻意去设置弱引用. |
| | | |
| | | + (instancetype)actionWithTitle:(NSString *)title handler:(void (^)(PopoverAction *action))handler; |
| | | |
| | | + (instancetype)actionWithImage:(UIImage *)image title:(NSString *)title handler:(void (^)(PopoverAction *action))handler; |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // PopoverAction.m |
| | | // Popover |
| | | // |
| | | // Created by StevenLee on 2016/12/10. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import "PopoverAction.h" |
| | | |
| | | @interface PopoverAction () |
| | | |
| | | @property (nonatomic, strong, readwrite) UIImage *image; ///< 图标 |
| | | @property (nonatomic, copy, readwrite) NSString *title; ///< 风格 |
| | | @property (nonatomic, copy, readwrite) void(^handler)(PopoverAction *action); ///< 选择回调 |
| | | |
| | | @end |
| | | |
| | | @implementation PopoverAction |
| | | |
| | | + (instancetype)actionWithTitle:(NSString *)title handler:(void (^)(PopoverAction *action))handler { |
| | | return [self actionWithImage:nil title:title handler:handler]; |
| | | } |
| | | |
| | | + (instancetype)actionWithImage:(UIImage *)image title:(NSString *)title handler:(void (^)(PopoverAction *action))handler { |
| | | PopoverAction *action = [[self alloc] init]; |
| | | action.image = image; |
| | | action.title = title ? : @""; |
| | | action.handler = handler ? : NULL; |
| | | |
| | | return action; |
| | | } |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // PopoverView.h |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <UIKit/UIKit.h> |
| | | #import "PopoverAction.h" |
| | | |
| | | @interface PopoverView : UIView |
| | | |
| | | @property (nonatomic, assign) BOOL hideAfterTouchOutside; ///< 是否开启点击外部隐藏弹窗, 默认为YES. |
| | | @property (nonatomic, assign) BOOL showShade; ///< 是否显示阴影, 如果为YES则弹窗背景为半透明的阴影层, 否则为透明, 默认为NO. |
| | | @property (nonatomic, assign) PopoverViewStyle style; ///< 弹出窗风格, 默认为 PopoverViewStyleDefault(白色). |
| | | |
| | | + (instancetype)popoverView; |
| | | |
| | | /*! @brief 指向指定的View来显示弹窗 |
| | | * @param pointView 箭头指向的View |
| | | * @param actions 动作对象集合<PopoverAction> |
| | | */ |
| | | - (void)showToView:(UIView *)pointView withActions:(NSArray<PopoverAction *> *)actions; |
| | | |
| | | /*! @brief 指向指定的点来显示弹窗 |
| | | * @param toPoint 箭头指向的点(这个点的坐标需按照keyWindow的坐标为参照) |
| | | * @param actions 动作对象集合<PopoverAction> |
| | | */ |
| | | - (void)showToPoint:(CGPoint)toPoint withActions:(NSArray<PopoverAction *> *)actions; |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // PopoverView.m |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import "PopoverView.h" |
| | | #import "PopoverViewCell.h" |
| | | |
| | | static float const kPopoverViewMargin = 8.f; ///< 边距 |
| | | static float const kPopoverViewCellHeight = 40.f; ///< cell指定高度 |
| | | static float const kPopoverViewArrowHeight = 13.f; ///< 箭头高度 |
| | | |
| | | // convert degrees to radians |
| | | float DegreesToRadians(float angle) { |
| | | return angle*M_PI/180; |
| | | } |
| | | |
| | | @interface PopoverView () <UITableViewDelegate, UITableViewDataSource> |
| | | |
| | | #pragma mark - UI |
| | | @property (nonatomic, weak) UIWindow *keyWindow; ///< 当前窗口 |
| | | @property (nonatomic, strong) UITableView *tableView; |
| | | @property (nonatomic, strong) UIView *shadeView; ///< 遮罩层 |
| | | @property (nonatomic, weak) CAShapeLayer *borderLayer; ///< 边框Layer |
| | | @property (nonatomic, weak) UITapGestureRecognizer *tapGesture; ///< 点击背景阴影的手势 |
| | | |
| | | #pragma mark - Data |
| | | @property (nonatomic, copy) NSArray<PopoverAction *> *actions; |
| | | @property (nonatomic, assign) CGFloat windowWidth; ///< 窗口宽度 |
| | | @property (nonatomic, assign) CGFloat windowHeight; ///< 窗口高度 |
| | | @property (nonatomic, assign) BOOL isUpward; ///< 箭头指向, YES为向上, 反之为向下, 默认为YES. |
| | | |
| | | @end |
| | | |
| | | @implementation PopoverView |
| | | |
| | | #pragma mark - Lift Cycle |
| | | - (instancetype)initWithFrame:(CGRect)frame |
| | | { |
| | | if (!(self = [super initWithFrame:frame])) return nil; |
| | | [self initialize]; |
| | | |
| | | return self; |
| | | } |
| | | |
| | | - (void)awakeFromNib { |
| | | [super awakeFromNib]; |
| | | [self initialize]; |
| | | } |
| | | |
| | | - (void)layoutSubviews |
| | | { |
| | | [super layoutSubviews]; |
| | | |
| | | _tableView.frame = CGRectMake(0, _isUpward ? kPopoverViewArrowHeight : 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) - kPopoverViewArrowHeight); |
| | | } |
| | | |
| | | #pragma mark - Setter |
| | | - (void)setHideAfterTouchOutside:(BOOL)hideAfterTouchOutside |
| | | { |
| | | _hideAfterTouchOutside = hideAfterTouchOutside; |
| | | _tapGesture.enabled = _hideAfterTouchOutside; |
| | | } |
| | | |
| | | - (void)setShowShade:(BOOL)showShade |
| | | { |
| | | _showShade = showShade; |
| | | _shadeView.backgroundColor = _showShade ? [UIColor colorWithWhite:0.f alpha:0.18f] : [UIColor clearColor]; |
| | | if (_borderLayer) { |
| | | _borderLayer.strokeColor = _showShade ? [UIColor clearColor].CGColor : _tableView.separatorColor.CGColor; |
| | | } |
| | | } |
| | | |
| | | - (void)setStyle:(PopoverViewStyle)style |
| | | { |
| | | _style = style; |
| | | _tableView.separatorColor = [PopoverViewCell bottomLineColorForStyle:_style]; |
| | | if (_style == PopoverViewStyleDefault) |
| | | { |
| | | self.backgroundColor = [UIColor whiteColor]; |
| | | } |
| | | else |
| | | { |
| | | self.backgroundColor = [UIColor colorWithRed:0.29 green:0.29 blue:0.29 alpha:1.00]; |
| | | } |
| | | } |
| | | |
| | | #pragma mark - Private |
| | | /*! @brief 初始化相关 */ |
| | | - (void)initialize { |
| | | // data |
| | | _actions = @[]; |
| | | _isUpward = YES; |
| | | _style = PopoverViewStyleDefault; |
| | | |
| | | // current view |
| | | self.backgroundColor = [UIColor whiteColor]; |
| | | |
| | | // keyWindow |
| | | _keyWindow = [UIApplication sharedApplication].keyWindow; |
| | | _windowWidth = CGRectGetWidth(_keyWindow.bounds); |
| | | _windowHeight = CGRectGetHeight(_keyWindow.bounds); |
| | | |
| | | // shadeView |
| | | _shadeView = [[UIView alloc] initWithFrame:_keyWindow.bounds]; |
| | | [self setShowShade:NO]; |
| | | UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)]; |
| | | [_shadeView addGestureRecognizer:tapGesture]; |
| | | _tapGesture = tapGesture; |
| | | |
| | | // tableView |
| | | _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; |
| | | _tableView.delegate = self; |
| | | _tableView.dataSource = self; |
| | | _tableView.scrollEnabled = NO; |
| | | _tableView.showsVerticalScrollIndicator = NO; |
| | | _tableView.backgroundColor = [UIColor clearColor]; |
| | | _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; |
| | | _tableView.separatorColor = [PopoverViewCell bottomLineColorForStyle:_style]; |
| | | [self addSubview:_tableView]; |
| | | } |
| | | |
| | | /*! @brief 显示弹窗指向某个点, */ |
| | | - (void)showToPoint:(CGPoint)toPoint { |
| | | NSAssert(_actions.count > 0, @"actions must not be nil or empty !"); |
| | | |
| | | // 截取弹窗时相关数据 |
| | | float arrowWidth = 28; |
| | | float cornerRadius = 6.f; |
| | | float arrowCornerRadius = 2.5f; |
| | | float arrowBottomCornerRadius = 4.f; |
| | | |
| | | // 如果箭头指向的点过于偏左或者过于偏右则需要重新调整箭头 x 轴的坐标 |
| | | CGFloat minHorizontalEdge = kPopoverViewMargin + cornerRadius + arrowWidth/2 + 2; |
| | | if (toPoint.x < minHorizontalEdge) { |
| | | toPoint.x = minHorizontalEdge; |
| | | } |
| | | if (_windowWidth - toPoint.x < minHorizontalEdge) { |
| | | toPoint.x = _windowWidth - minHorizontalEdge; |
| | | } |
| | | |
| | | // 遮罩层 |
| | | _shadeView.alpha = 0.f; |
| | | [_keyWindow addSubview:_shadeView]; |
| | | |
| | | // 刷新数据以获取具体的ContentSize |
| | | [_tableView reloadData]; |
| | | // 根据刷新后的ContentSize和箭头指向方向来设置当前视图的frame |
| | | CGFloat currentW = [self calculateMaxWidth]; // 宽度通过计算获取最大值 |
| | | CGFloat currentH = _tableView.contentSize.height + kPopoverViewArrowHeight; |
| | | |
| | | // 限制最高高度, 免得选项太多时超出屏幕 |
| | | CGFloat maxHeight = _isUpward ? (_windowHeight - toPoint.y - kPopoverViewMargin) : (toPoint.y - CGRectGetHeight([UIApplication sharedApplication].statusBarFrame)); |
| | | if (currentH > maxHeight) { // 如果弹窗高度大于最大高度的话则限制弹窗高度等于最大高度并允许tableView滑动. |
| | | currentH = maxHeight; |
| | | _tableView.scrollEnabled = YES; |
| | | if (!_isUpward) { // 箭头指向下则移动到最后一行 |
| | | [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_actions.count - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO]; |
| | | } |
| | | } |
| | | |
| | | CGFloat currentX = toPoint.x - currentW/2, currentY = toPoint.y; |
| | | // x: 窗口靠左 |
| | | if (toPoint.x <= currentW/2 + kPopoverViewMargin) { |
| | | currentX = kPopoverViewMargin; |
| | | } |
| | | // x: 窗口靠右 |
| | | if (_windowWidth - toPoint.x <= currentW/2 + kPopoverViewMargin) { |
| | | currentX = _windowWidth - kPopoverViewMargin - currentW; |
| | | } |
| | | // y: 箭头向下 |
| | | if (!_isUpward) { |
| | | currentY = toPoint.y - currentH; |
| | | } |
| | | |
| | | self.frame = CGRectMake(currentX, currentY, currentW, currentH); |
| | | |
| | | // 截取箭头 |
| | | CGPoint arrowPoint = CGPointMake(toPoint.x - CGRectGetMinX(self.frame), _isUpward ? 0 : currentH); // 箭头顶点在当前视图的坐标 |
| | | CGFloat maskTop = _isUpward ? kPopoverViewArrowHeight : 0; // 顶部Y值 |
| | | CGFloat maskBottom = _isUpward ? currentH : currentH - kPopoverViewArrowHeight; // 底部Y值 |
| | | UIBezierPath *maskPath = [UIBezierPath bezierPath]; |
| | | // 左上圆角 |
| | | [maskPath moveToPoint:CGPointMake(0, cornerRadius + maskTop)]; |
| | | [maskPath addArcWithCenter:CGPointMake(cornerRadius, cornerRadius + maskTop) |
| | | radius:cornerRadius |
| | | startAngle:DegreesToRadians(180) |
| | | endAngle:DegreesToRadians(270) |
| | | clockwise:YES]; |
| | | // 箭头向上时的箭头位置 |
| | | if (_isUpward) { |
| | | [maskPath addLineToPoint:CGPointMake(arrowPoint.x - arrowWidth/2, kPopoverViewArrowHeight)]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x - arrowCornerRadius, arrowCornerRadius) |
| | | controlPoint:CGPointMake(arrowPoint.x - arrowWidth/2 + arrowBottomCornerRadius, kPopoverViewArrowHeight)]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x + arrowCornerRadius, arrowCornerRadius) |
| | | controlPoint:arrowPoint]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x + arrowWidth/2, kPopoverViewArrowHeight) |
| | | controlPoint:CGPointMake(arrowPoint.x + arrowWidth/2 - arrowBottomCornerRadius, kPopoverViewArrowHeight)]; |
| | | } |
| | | // 右上圆角 |
| | | [maskPath addLineToPoint:CGPointMake(currentW - cornerRadius, maskTop)]; |
| | | [maskPath addArcWithCenter:CGPointMake(currentW - cornerRadius, maskTop + cornerRadius) |
| | | radius:cornerRadius |
| | | startAngle:DegreesToRadians(270) |
| | | endAngle:DegreesToRadians(0) |
| | | clockwise:YES]; |
| | | // 右下圆角 |
| | | [maskPath addLineToPoint:CGPointMake(currentW, maskBottom - cornerRadius)]; |
| | | [maskPath addArcWithCenter:CGPointMake(currentW - cornerRadius, maskBottom - cornerRadius) |
| | | radius:cornerRadius |
| | | startAngle:DegreesToRadians(0) |
| | | endAngle:DegreesToRadians(90) |
| | | clockwise:YES]; |
| | | // 箭头向下时的箭头位置 |
| | | if (!_isUpward) { |
| | | [maskPath addLineToPoint:CGPointMake(arrowPoint.x + arrowWidth/2, currentH - kPopoverViewArrowHeight)]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x + arrowCornerRadius, currentH - arrowCornerRadius) |
| | | controlPoint:CGPointMake(arrowPoint.x + arrowWidth/2 - arrowBottomCornerRadius, currentH - kPopoverViewArrowHeight)]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x - arrowCornerRadius, currentH - arrowCornerRadius) |
| | | controlPoint:arrowPoint]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x - arrowWidth/2, currentH - kPopoverViewArrowHeight) |
| | | controlPoint:CGPointMake(arrowPoint.x - arrowWidth/2 + arrowBottomCornerRadius, currentH - kPopoverViewArrowHeight)]; |
| | | } |
| | | // 左下圆角 |
| | | [maskPath addLineToPoint:CGPointMake(cornerRadius, maskBottom)]; |
| | | [maskPath addArcWithCenter:CGPointMake(cornerRadius, maskBottom - cornerRadius) |
| | | radius:cornerRadius |
| | | startAngle:DegreesToRadians(90) |
| | | endAngle:DegreesToRadians(180) |
| | | clockwise:YES]; |
| | | [maskPath closePath]; |
| | | // 截取圆角和箭头 |
| | | CAShapeLayer *maskLayer = [CAShapeLayer layer]; |
| | | maskLayer.frame = self.bounds; |
| | | maskLayer.path = maskPath.CGPath; |
| | | self.layer.mask = maskLayer; |
| | | // 边框 (只有在不显示半透明阴影层时才设置边框线条) |
| | | if (!_showShade) { |
| | | CAShapeLayer *borderLayer = [CAShapeLayer layer]; |
| | | borderLayer.frame = self.bounds; |
| | | borderLayer.path = maskPath.CGPath; |
| | | borderLayer.lineWidth = 1; |
| | | borderLayer.fillColor = [UIColor clearColor].CGColor; |
| | | borderLayer.strokeColor = _tableView.separatorColor.CGColor; |
| | | [self.layer addSublayer:borderLayer]; |
| | | _borderLayer = borderLayer; |
| | | } |
| | | |
| | | [_keyWindow addSubview:self]; |
| | | |
| | | // 弹出动画 |
| | | CGRect oldFrame = self.frame; |
| | | self.layer.anchorPoint = CGPointMake(arrowPoint.x/currentW, _isUpward ? 0.f : 1.f); |
| | | self.frame = oldFrame; |
| | | self.transform = CGAffineTransformMakeScale(0.01f, 0.01f); |
| | | [UIView animateWithDuration:0.25f animations:^{ |
| | | self.transform = CGAffineTransformIdentity; |
| | | _shadeView.alpha = 1.f; |
| | | }]; |
| | | } |
| | | |
| | | /*! @brief 计算最大宽度 */ |
| | | - (CGFloat)calculateMaxWidth { |
| | | CGFloat maxWidth = 0.f, titleLeftEdge = 0.f, imageWidth = 0.f, imageMaxHeight = kPopoverViewCellHeight - PopoverViewCellVerticalMargin*2; |
| | | CGSize imageSize = CGSizeZero; |
| | | UIFont *titleFont = [PopoverViewCell titleFont]; |
| | | for (PopoverAction *action in _actions) { |
| | | imageWidth = 0.f; |
| | | titleLeftEdge = 0.f; |
| | | |
| | | if (action.image) { // 存在图片则根据图片size和图片最大高度来重新计算图片宽度 |
| | | titleLeftEdge = PopoverViewCellTitleLeftEdge; // 有图片时标题才有左边的边距 |
| | | imageSize = action.image.size; |
| | | if (imageSize.height > imageMaxHeight) { |
| | | imageWidth = imageMaxHeight*imageSize.width/imageSize.height; |
| | | } else { |
| | | imageWidth = imageSize.width; |
| | | } |
| | | } |
| | | |
| | | CGFloat titleWidth; |
| | | if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0) { // iOS7及往后版本 |
| | | titleWidth = [action.title sizeWithAttributes:@{NSFontAttributeName : titleFont}].width; |
| | | } else { // iOS6 |
| | | #pragma GCC diagnostic push |
| | | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
| | | titleWidth = [action.title sizeWithFont:titleFont].width; |
| | | #pragma GCC diagnostic pop |
| | | } |
| | | |
| | | CGFloat contentWidth = PopoverViewCellHorizontalMargin*2 + imageWidth + titleLeftEdge + titleWidth; |
| | | if (contentWidth > maxWidth) { |
| | | maxWidth = ceil(contentWidth); // 获取最大宽度时需使用进一取法, 否则Cell中没有图片时会可能导致标题显示不完整. |
| | | } |
| | | } |
| | | |
| | | // 如果最大宽度大于(窗口宽度 - kPopoverViewMargin*2)则限制最大宽度等于(窗口宽度 - kPopoverViewMargin*2) |
| | | if (maxWidth > CGRectGetWidth(_keyWindow.bounds) - kPopoverViewMargin*2) { |
| | | maxWidth = CGRectGetWidth(_keyWindow.bounds) - kPopoverViewMargin*2; |
| | | } |
| | | |
| | | return maxWidth; |
| | | } |
| | | |
| | | /*! @brief 点击外部隐藏弹窗 */ |
| | | - (void)hide { |
| | | [UIView animateWithDuration:0.25f animations:^{ |
| | | self.alpha = 0.f; |
| | | _shadeView.alpha = 0.f; |
| | | self.transform = CGAffineTransformMakeScale(0.01f, 0.01f); |
| | | } completion:^(BOOL finished) { |
| | | [_shadeView removeFromSuperview]; |
| | | [self removeFromSuperview]; |
| | | }]; |
| | | } |
| | | |
| | | #pragma mark - Public |
| | | + (instancetype)popoverView { |
| | | return [[self alloc] init]; |
| | | } |
| | | |
| | | /*! @brief 指向指定的View来显示弹窗 */ |
| | | - (void)showToView:(UIView *)pointView withActions:(NSArray<PopoverAction *> *)actions |
| | | { |
| | | // 判断 pointView 是偏上还是偏下 |
| | | CGRect pointViewRect = [pointView.superview convertRect:pointView.frame toView:_keyWindow]; |
| | | CGFloat pointViewUpLength = CGRectGetMinY(pointViewRect); |
| | | CGFloat pointViewDownLength = _windowHeight - CGRectGetMaxY(pointViewRect); |
| | | // 弹窗箭头指向的点 |
| | | CGPoint toPoint = CGPointMake(CGRectGetMidX(pointViewRect), 0); |
| | | // 弹窗在 pointView 顶部 |
| | | if (pointViewUpLength > pointViewDownLength) |
| | | { |
| | | toPoint.y = pointViewUpLength - 5; |
| | | } |
| | | // 弹窗在 pointView 底部 |
| | | else |
| | | { |
| | | toPoint.y = CGRectGetMaxY(pointViewRect) + 5; |
| | | } |
| | | |
| | | // 箭头指向方向 |
| | | _isUpward = pointViewUpLength <= pointViewDownLength; |
| | | _actions = [actions copy]; |
| | | [self showToPoint:toPoint]; |
| | | } |
| | | |
| | | /*! @brief 指向指定的点来显示弹窗 */ |
| | | - (void)showToPoint:(CGPoint)toPoint withActions:(NSArray<PopoverAction *> *)actions { |
| | | _actions = [actions copy]; |
| | | // 计算箭头指向方向 |
| | | _isUpward = toPoint.y <= _windowHeight - toPoint.y; |
| | | [self showToPoint:toPoint]; |
| | | } |
| | | |
| | | #pragma mark - UITableViewDelegate & UITableViewDataSource |
| | | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { |
| | | return _actions.count; |
| | | } |
| | | |
| | | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { |
| | | return kPopoverViewCellHeight; |
| | | } |
| | | |
| | | static NSString *kPopoverCellIdentifier = @"kPopoverCellIdentifier"; |
| | | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { |
| | | PopoverViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kPopoverCellIdentifier]; |
| | | if (!cell) |
| | | { |
| | | cell = [[PopoverViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kPopoverCellIdentifier]; |
| | | } |
| | | |
| | | [cell setAction:_actions[indexPath.row]]; |
| | | [cell showBottomLine: indexPath.row < _actions.count - 1]; |
| | | cell.style = _style; |
| | | |
| | | return cell; |
| | | } |
| | | |
| | | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath |
| | | { |
| | | [UIView animateWithDuration:0.25f animations:^{ |
| | | self.alpha = 0.f; |
| | | _shadeView.alpha = 0.f; |
| | | } completion:^(BOOL finished) { |
| | | PopoverAction *action = _actions[indexPath.row]; |
| | | action.handler ? action.handler(action) : NULL; |
| | | _actions = nil; |
| | | [_shadeView removeFromSuperview]; |
| | | [self removeFromSuperview]; |
| | | }]; |
| | | } |
| | | |
| | | @end |
| | | |
New file |
| | |
| | | // |
| | | // PopoverViewCell.h |
| | | // Popover |
| | | // |
| | | // Created by StevenLee on 2016/12/10. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <UIKit/UIKit.h> |
| | | #import "PopoverAction.h" |
| | | |
| | | UIKIT_EXTERN float const PopoverViewCellHorizontalMargin; ///< 水平间距边距 |
| | | UIKIT_EXTERN float const PopoverViewCellVerticalMargin; ///< 垂直边距 |
| | | UIKIT_EXTERN float const PopoverViewCellTitleLeftEdge; ///< 标题左边边距 |
| | | |
| | | @class PopoverAction; |
| | | |
| | | @interface PopoverViewCell : UITableViewCell |
| | | |
| | | @property (nonatomic, assign) PopoverViewStyle style; |
| | | |
| | | /*! @brief 标题字体 |
| | | */ |
| | | + (UIFont *)titleFont; |
| | | |
| | | /*! @brief 底部线条颜色 |
| | | */ |
| | | + (UIColor *)bottomLineColorForStyle:(PopoverViewStyle)style; |
| | | |
| | | - (void)setAction:(PopoverAction *)action; |
| | | |
| | | - (void)showBottomLine:(BOOL)show; |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // PopoverViewCell.m |
| | | // Popover |
| | | // |
| | | // Created by StevenLee on 2016/12/10. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import "PopoverViewCell.h" |
| | | |
| | | // extern |
| | | float const PopoverViewCellHorizontalMargin = 15.f; ///< 水平边距 |
| | | float const PopoverViewCellVerticalMargin = 3.f; ///< 垂直边距 |
| | | float const PopoverViewCellTitleLeftEdge = 8.f; ///< 标题左边边距 |
| | | |
| | | @interface PopoverViewCell () |
| | | |
| | | @property (nonatomic, strong) UIButton *button; |
| | | @property (nonatomic, weak) UIView *bottomLine; |
| | | |
| | | @end |
| | | |
| | | @implementation PopoverViewCell |
| | | |
| | | #pragma mark - Life Cycle |
| | | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { |
| | | if (!(self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) return nil; |
| | | self.backgroundColor = [UIColor clearColor]; |
| | | self.contentView.backgroundColor = self.backgroundColor; |
| | | self.selectionStyle = UITableViewCellSelectionStyleNone; |
| | | // initialize |
| | | [self initialize]; |
| | | |
| | | return self; |
| | | } |
| | | |
| | | - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { |
| | | [super setHighlighted:highlighted animated:animated]; |
| | | if (highlighted) { |
| | | self.backgroundColor = _style == PopoverViewStyleDefault ? [UIColor colorWithRed:0.90 green:0.90 blue:0.90 alpha:1.00] : [UIColor colorWithRed:0.23 green:0.23 blue:0.23 alpha:1.00]; |
| | | } else { |
| | | [UIView animateWithDuration:0.3f animations:^{ |
| | | self.backgroundColor = [UIColor clearColor]; |
| | | }]; |
| | | } |
| | | } |
| | | |
| | | #pragma mark - Setter |
| | | - (void)setStyle:(PopoverViewStyle)style { |
| | | _style = style; |
| | | _bottomLine.backgroundColor = [self.class bottomLineColorForStyle:style]; |
| | | if (_style == PopoverViewStyleDefault) { |
| | | [_button setTitleColor:UIColor.blackColor forState:UIControlStateNormal]; |
| | | } else { |
| | | [_button setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; |
| | | } |
| | | } |
| | | |
| | | #pragma mark - Private |
| | | // 初始化 |
| | | - (void)initialize { |
| | | // UI |
| | | _button = [UIButton buttonWithType:UIButtonTypeCustom]; |
| | | _button.userInteractionEnabled = NO; // has no use for UserInteraction. |
| | | _button.translatesAutoresizingMaskIntoConstraints = NO; |
| | | _button.titleLabel.font = [self.class titleFont]; |
| | | _button.backgroundColor = self.contentView.backgroundColor; |
| | | _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; |
| | | [_button setTitleColor:UIColor.blackColor forState:UIControlStateNormal]; |
| | | [self.contentView addSubview:_button]; |
| | | // Constraint |
| | | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-margin-[_button]-margin-|" options:kNilOptions metrics:@{@"margin" : @(PopoverViewCellHorizontalMargin)} views:NSDictionaryOfVariableBindings(_button)]]; |
| | | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-margin-[_button]-margin-|" options:kNilOptions metrics:@{@"margin" : @(PopoverViewCellVerticalMargin)} views:NSDictionaryOfVariableBindings(_button)]]; |
| | | // 底部线条 |
| | | UIView *bottomLine = [[UIView alloc] init]; |
| | | bottomLine.backgroundColor = [UIColor colorWithRed:0.75 green:0.75 blue:0.75 alpha:1.00]; |
| | | bottomLine.translatesAutoresizingMaskIntoConstraints = NO; |
| | | [self.contentView addSubview:bottomLine]; |
| | | _bottomLine = bottomLine; |
| | | // Constraint |
| | | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[bottomLine]|" options:kNilOptions metrics:nil views:NSDictionaryOfVariableBindings(bottomLine)]]; |
| | | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[bottomLine(lineHeight)]|" options:kNilOptions metrics:@{@"lineHeight" : @(1/[UIScreen mainScreen].scale)} views:NSDictionaryOfVariableBindings(bottomLine)]]; |
| | | } |
| | | |
| | | #pragma mark - Public |
| | | /*! @brief 标题字体 */ |
| | | + (UIFont *)titleFont |
| | | { |
| | | return [UIFont systemFontOfSize:15.f]; |
| | | } |
| | | |
| | | /*! @brief 底部线条颜色 */ |
| | | + (UIColor *)bottomLineColorForStyle:(PopoverViewStyle)style |
| | | { |
| | | return style == PopoverViewStyleDefault ? [UIColor colorWithRed:0.75 green:0.75 blue:0.75 alpha:1.00] : [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1.00]; |
| | | } |
| | | |
| | | - (void)setAction:(PopoverAction *)action |
| | | { |
| | | [_button setImage:action.image forState:UIControlStateNormal]; |
| | | [_button setTitle:action.title forState:UIControlStateNormal]; |
| | | _button.titleEdgeInsets = action.image ? UIEdgeInsetsMake(0, PopoverViewCellTitleLeftEdge, 0, -PopoverViewCellTitleLeftEdge) : UIEdgeInsetsZero; |
| | | } |
| | | |
| | | - (void)showBottomLine:(BOOL)show { |
| | | _bottomLine.hidden = !show; |
| | | } |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // ViewController.h |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <UIKit/UIKit.h> |
| | | |
| | | @interface ViewController : UIViewController |
| | | |
| | | |
| | | @end |
| | | |
New file |
| | |
| | | |
| | | |
| | | // |
| | | // ViewController.m |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import "ViewController.h" |
| | | #import "PopoverView.h" |
| | | |
| | | @interface ViewController () |
| | | |
| | | @property (weak, nonatomic) IBOutlet UILabel *noticeLabel; |
| | | |
| | | @end |
| | | |
| | | @implementation ViewController |
| | | |
| | | - (void)viewDidLoad { |
| | | [super viewDidLoad]; |
| | | |
| | | } |
| | | |
| | | - (NSArray<PopoverAction *> *)QQActions |
| | | { |
| | | // 发起多人聊天 action |
| | | PopoverAction *multichatAction = [PopoverAction actionWithImage:[UIImage imageNamed:@"right_menu_multichat"] title:@"发起多人聊天" handler:^(PopoverAction *action) { |
| | | #pragma mark - 该Block不会导致内存泄露, Block内代码无需刻意去设置弱引用. |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | // 加好友 action |
| | | PopoverAction *addFriAction = [PopoverAction actionWithImage:[UIImage imageNamed:@"right_menu_addFri"] title:@"加好友" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | // 扫一扫 action |
| | | PopoverAction *QRAction = [PopoverAction actionWithImage:[UIImage imageNamed:@"right_menu_QR"] title:@"扫一扫" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | // 面对面快传 action |
| | | PopoverAction *facetofaceAction = [PopoverAction actionWithImage:[UIImage imageNamed:@"right_menu_facetoface"] title:@"面对面快传" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | // 付款 action |
| | | PopoverAction *payMoneyAction = [PopoverAction actionWithImage:[UIImage imageNamed:@"right_menu_payMoney"] title:@"付款" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | |
| | | return @[multichatAction, addFriAction, QRAction, facetofaceAction, payMoneyAction]; |
| | | } |
| | | |
| | | - (IBAction)buttonAction:(UIButton *)sender { |
| | | PopoverView *popoverView = [PopoverView popoverView]; |
| | | [popoverView showToView:sender withActions:[self QQActions]]; |
| | | } |
| | | |
| | | - (IBAction)leftBarItemAction:(UIBarButtonItem *)sender { |
| | | PopoverAction *action1 = [PopoverAction actionWithImage:[UIImage imageNamed:@"contacts_add_newmessage"] title:@"发起群聊" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | PopoverAction *action2 = [PopoverAction actionWithImage:[UIImage imageNamed:@"contacts_add_friend"] title:@"添加朋友" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | PopoverAction *action3 = [PopoverAction actionWithImage:[UIImage imageNamed:@"contacts_add_scan"] title:@"扫一扫" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | PopoverAction *action4 = [PopoverAction actionWithImage:[UIImage imageNamed:@"contacts_add_money"] title:@"收付款" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | |
| | | PopoverView *popoverView = [PopoverView popoverView]; |
| | | popoverView.style = PopoverViewStyleDark; |
| | | // 在没有系统控件的情况下调用可以使用显示在指定的点坐标的方法弹出菜单控件. |
| | | [popoverView showToPoint:CGPointMake(20, 64) withActions:@[action1, action2, action3, action4]]; |
| | | } |
| | | |
| | | - (IBAction)rightButtonAction:(UIButton *)sender { |
| | | PopoverView *popoverView = [PopoverView popoverView]; |
| | | popoverView.showShade = YES; // 显示阴影背景 |
| | | [popoverView showToView:sender withActions:[self QQActions]]; |
| | | } |
| | | |
| | | - (IBAction)showWithoutImage:(UIButton *)sender { |
| | | // 不带图片 |
| | | PopoverAction *action1 = [PopoverAction actionWithTitle:@"加好友" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | PopoverAction *action2 = [PopoverAction actionWithTitle:@"扫一扫" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | PopoverAction *action3 = [PopoverAction actionWithTitle:@"发起聊天" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | PopoverAction *action4 = [PopoverAction actionWithTitle:@"发起群聊" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | PopoverAction *action5 = [PopoverAction actionWithTitle:@"查找群聊" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | PopoverAction *action6 = [PopoverAction actionWithTitle:@"我的群聊" handler:^(PopoverAction *action) { |
| | | _noticeLabel.text = action.title; |
| | | }]; |
| | | |
| | | PopoverView *popoverView = [PopoverView popoverView]; |
| | | popoverView.style = PopoverViewStyleDark; |
| | | popoverView.hideAfterTouchOutside = NO; // 点击外部时不允许隐藏 |
| | | [popoverView showToView:sender withActions:@[action1, action2, action3, action4, action5, action6]]; |
| | | } |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // main.m |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <UIKit/UIKit.h> |
| | | #import "AppDelegate.h" |
| | | |
| | | int main(int argc, char * argv[]) { |
| | | @autoreleasepool { |
| | | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); |
| | | } |
| | | } |
New file |
| | |
| | | // |
| | | // PopoverAction.h |
| | | // Popover |
| | | // |
| | | // Created by StevenLee on 2016/12/10. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <Foundation/Foundation.h> |
| | | #import <UIKit/UIKit.h> |
| | | |
| | | typedef NS_ENUM(NSUInteger, PopoverViewStyle) { |
| | | PopoverViewStyleDefault = 0, // 默认风格, 白色 |
| | | PopoverViewStyleDark, // 黑色风格 |
| | | }; |
| | | |
| | | @interface PopoverAction : NSObject |
| | | |
| | | @property (nonatomic, strong, readonly) UIImage *image; ///< 图标 (建议使用 60pix*60pix 的图片) |
| | | @property (nonatomic, copy, readonly) NSString *title; ///< 标题 |
| | | @property (nonatomic, copy, readonly) void(^handler)(PopoverAction *action); ///< 选择回调, 该Block不会导致内存泄露, Block内代码无需刻意去设置弱引用. |
| | | |
| | | + (instancetype)actionWithTitle:(NSString *)title handler:(void (^)(PopoverAction *action))handler; |
| | | |
| | | + (instancetype)actionWithImage:(UIImage *)image title:(NSString *)title handler:(void (^)(PopoverAction *action))handler; |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // PopoverAction.m |
| | | // Popover |
| | | // |
| | | // Created by StevenLee on 2016/12/10. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import "PopoverAction.h" |
| | | |
| | | @interface PopoverAction () |
| | | |
| | | @property (nonatomic, strong, readwrite) UIImage *image; ///< 图标 |
| | | @property (nonatomic, copy, readwrite) NSString *title; ///< 风格 |
| | | @property (nonatomic, copy, readwrite) void(^handler)(PopoverAction *action); ///< 选择回调 |
| | | |
| | | @end |
| | | |
| | | @implementation PopoverAction |
| | | |
| | | + (instancetype)actionWithTitle:(NSString *)title handler:(void (^)(PopoverAction *action))handler { |
| | | return [self actionWithImage:nil title:title handler:handler]; |
| | | } |
| | | |
| | | + (instancetype)actionWithImage:(UIImage *)image title:(NSString *)title handler:(void (^)(PopoverAction *action))handler { |
| | | PopoverAction *action = [[self alloc] init]; |
| | | action.image = image; |
| | | action.title = title ? : @""; |
| | | action.handler = handler ? : NULL; |
| | | |
| | | return action; |
| | | } |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // PopoverView.h |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <UIKit/UIKit.h> |
| | | #import "PopoverAction.h" |
| | | |
| | | @interface PopoverView : UIView |
| | | |
| | | @property (nonatomic, assign) BOOL hideAfterTouchOutside; ///< 是否开启点击外部隐藏弹窗, 默认为YES. |
| | | @property (nonatomic, assign) BOOL showShade; ///< 是否显示阴影, 如果为YES则弹窗背景为半透明的阴影层, 否则为透明, 默认为NO. |
| | | @property (nonatomic, assign) PopoverViewStyle style; ///< 弹出窗风格, 默认为 PopoverViewStyleDefault(白色). |
| | | |
| | | + (instancetype)popoverView; |
| | | |
| | | /*! @brief 指向指定的View来显示弹窗 |
| | | * @param pointView 箭头指向的View |
| | | * @param actions 动作对象集合<PopoverAction> |
| | | */ |
| | | - (void)showToView:(UIView *)pointView withActions:(NSArray<PopoverAction *> *)actions; |
| | | |
| | | /*! @brief 指向指定的点来显示弹窗 |
| | | * @param toPoint 箭头指向的点(这个点的坐标需按照keyWindow的坐标为参照) |
| | | * @param actions 动作对象集合<PopoverAction> |
| | | */ |
| | | - (void)showToPoint:(CGPoint)toPoint withActions:(NSArray<PopoverAction *> *)actions; |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // PopoverView.m |
| | | // Popover |
| | | // |
| | | // Created by lifution on 16/1/5. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import "PopoverView.h" |
| | | #import "PopoverViewCell.h" |
| | | |
| | | static float const kPopoverViewMargin = 8.f; ///< 边距 |
| | | static float const kPopoverViewCellHeight = 40.f; ///< cell指定高度 |
| | | static float const kPopoverViewArrowHeight = 13.f; ///< 箭头高度 |
| | | |
| | | // convert degrees to radians |
| | | float DegreesToRadians(float angle) { |
| | | return angle*M_PI/180; |
| | | } |
| | | |
| | | @interface PopoverView () <UITableViewDelegate, UITableViewDataSource> |
| | | |
| | | #pragma mark - UI |
| | | @property (nonatomic, weak) UIWindow *keyWindow; ///< 当前窗口 |
| | | @property (nonatomic, strong) UITableView *tableView; |
| | | @property (nonatomic, strong) UIView *shadeView; ///< 遮罩层 |
| | | @property (nonatomic, weak) CAShapeLayer *borderLayer; ///< 边框Layer |
| | | |
| | | #pragma mark - Data |
| | | @property (nonatomic, copy) NSArray<PopoverAction *> *actions; |
| | | @property (nonatomic, assign) CGFloat windowWidth; ///< 窗口宽度 |
| | | @property (nonatomic, assign) CGFloat windowHeight; ///< 窗口高度 |
| | | @property (nonatomic, assign) BOOL isUpward; ///< 箭头指向, YES为向上, 反之为向下, 默认为YES. |
| | | |
| | | @end |
| | | |
| | | @implementation PopoverView |
| | | |
| | | #pragma mark - Lift Cycle |
| | | - (instancetype)initWithFrame:(CGRect)frame { |
| | | if (!(self = [super initWithFrame:frame])) return nil; |
| | | [self initialize]; |
| | | |
| | | return self; |
| | | } |
| | | |
| | | - (void)awakeFromNib { |
| | | [super awakeFromNib]; |
| | | [self initialize]; |
| | | } |
| | | |
| | | - (void)layoutSubviews { |
| | | [super layoutSubviews]; |
| | | _tableView.frame = CGRectMake(0, _isUpward ? kPopoverViewArrowHeight : 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) - kPopoverViewArrowHeight); |
| | | } |
| | | |
| | | - (void)dealloc { |
| | | NSLog(@"PopoverView dealloced"); |
| | | } |
| | | |
| | | #pragma mark - Setter |
| | | - (void)setHideAfterTouchOutside:(BOOL)hideAfterTouchOutside { |
| | | _hideAfterTouchOutside = hideAfterTouchOutside; |
| | | _shadeView.userInteractionEnabled = _hideAfterTouchOutside; |
| | | } |
| | | |
| | | - (void)setShowShade:(BOOL)showShade { |
| | | _showShade = showShade; |
| | | _shadeView.backgroundColor = _showShade ? [UIColor colorWithWhite:0.f alpha:0.18f] : [UIColor clearColor]; |
| | | if (_borderLayer) { |
| | | _borderLayer.strokeColor = _showShade ? [UIColor clearColor].CGColor : _tableView.separatorColor.CGColor; |
| | | } |
| | | } |
| | | |
| | | - (void)setStyle:(PopoverViewStyle)style { |
| | | _style = style; |
| | | _tableView.separatorColor = [PopoverViewCell bottomLineColorForStyle:_style]; |
| | | if (_style == PopoverViewStyleDefault) { |
| | | self.backgroundColor = [UIColor whiteColor]; |
| | | } else { |
| | | self.backgroundColor = [UIColor colorWithRed:0.29 green:0.29 blue:0.29 alpha:1.00]; |
| | | } |
| | | } |
| | | |
| | | #pragma mark - Private |
| | | /*! @brief 初始化相关 */ |
| | | - (void)initialize { |
| | | // data |
| | | _actions = @[]; |
| | | _isUpward = YES; |
| | | _style = PopoverViewStyleDefault; |
| | | |
| | | // current view |
| | | self.backgroundColor = [UIColor whiteColor]; |
| | | |
| | | // keyWindow |
| | | _keyWindow = [UIApplication sharedApplication].keyWindow; |
| | | _windowWidth = CGRectGetWidth(_keyWindow.bounds); |
| | | _windowHeight = CGRectGetHeight(_keyWindow.bounds); |
| | | |
| | | // shadeView |
| | | _shadeView = [[UIView alloc] initWithFrame:_keyWindow.bounds]; |
| | | [_shadeView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)]]; |
| | | [self setShowShade:NO]; |
| | | |
| | | // tableView |
| | | _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; |
| | | _tableView.delegate = self; |
| | | _tableView.dataSource = self; |
| | | _tableView.scrollEnabled = NO; |
| | | _tableView.showsVerticalScrollIndicator = NO; |
| | | _tableView.backgroundColor = [UIColor clearColor]; |
| | | _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; |
| | | _tableView.separatorColor = [PopoverViewCell bottomLineColorForStyle:_style]; |
| | | [self addSubview:_tableView]; |
| | | } |
| | | |
| | | /*! @brief 显示弹窗指向某个点, */ |
| | | - (void)showToPoint:(CGPoint)toPoint { |
| | | NSAssert(_actions.count > 0, @"actions must not be nil or empty !"); |
| | | |
| | | // 截取弹窗时相关数据 |
| | | float arrowWidth = 28; |
| | | float cornerRadius = 6.f; |
| | | float arrowCornerRadius = 2.5f; |
| | | float arrowBottomCornerRadius = 4.f; |
| | | |
| | | // 如果箭头指向的点过于偏左或者过于偏右则需要重新调整箭头 x 轴的坐标 |
| | | CGFloat minHorizontalEdge = kPopoverViewMargin + cornerRadius + arrowWidth/2 + 2; |
| | | if (toPoint.x < minHorizontalEdge) { |
| | | toPoint.x = minHorizontalEdge; |
| | | } |
| | | if (_windowWidth - toPoint.x < minHorizontalEdge) { |
| | | toPoint.x = _windowWidth - minHorizontalEdge; |
| | | } |
| | | |
| | | // 遮罩层 |
| | | _shadeView.alpha = 0.f; |
| | | [_keyWindow addSubview:_shadeView]; |
| | | |
| | | // 刷新数据以获取具体的ContentSize |
| | | [_tableView reloadData]; |
| | | // 根据刷新后的ContentSize和箭头指向方向来设置当前视图的frame |
| | | CGFloat currentW = [self calculateMaxWidth]; // 宽度通过计算获取最大值 |
| | | CGFloat currentH = _tableView.contentSize.height + kPopoverViewArrowHeight; |
| | | |
| | | // 限制最高高度, 免得选项太多时超出屏幕 |
| | | CGFloat maxHeight = _isUpward ? (_windowHeight - toPoint.y - kPopoverViewMargin) : (toPoint.y - CGRectGetHeight([UIApplication sharedApplication].statusBarFrame)); |
| | | if (currentH > maxHeight) { // 如果弹窗高度大于最大高度的话则限制弹窗高度等于最大高度并允许tableView滑动. |
| | | currentH = maxHeight; |
| | | _tableView.scrollEnabled = YES; |
| | | if (!_isUpward) { // 箭头指向下则移动到最后一行 |
| | | [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_actions.count - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO]; |
| | | } |
| | | } |
| | | |
| | | CGFloat currentX = toPoint.x - currentW/2, currentY = toPoint.y; |
| | | // x: 窗口靠左 |
| | | if (toPoint.x <= currentW/2 + kPopoverViewMargin) { |
| | | currentX = kPopoverViewMargin; |
| | | } |
| | | // x: 窗口靠右 |
| | | if (_windowWidth - toPoint.x <= currentW/2 + kPopoverViewMargin) { |
| | | currentX = _windowWidth - kPopoverViewMargin - currentW; |
| | | } |
| | | // y: 箭头向下 |
| | | if (!_isUpward) { |
| | | currentY = toPoint.y - currentH; |
| | | } |
| | | |
| | | self.frame = CGRectMake(currentX, currentY, currentW, currentH); |
| | | |
| | | // 截取箭头 |
| | | CGPoint arrowPoint = CGPointMake(toPoint.x - CGRectGetMinX(self.frame), _isUpward ? 0 : currentH); // 箭头顶点在当前视图的坐标 |
| | | CGFloat maskTop = _isUpward ? kPopoverViewArrowHeight : 0; // 顶部Y值 |
| | | CGFloat maskBottom = _isUpward ? currentH : currentH - kPopoverViewArrowHeight; // 底部Y值 |
| | | UIBezierPath *maskPath = [UIBezierPath bezierPath]; |
| | | // 左上圆角 |
| | | [maskPath moveToPoint:CGPointMake(0, cornerRadius + maskTop)]; |
| | | [maskPath addArcWithCenter:CGPointMake(cornerRadius, cornerRadius + maskTop) |
| | | radius:cornerRadius |
| | | startAngle:DegreesToRadians(180) |
| | | endAngle:DegreesToRadians(270) |
| | | clockwise:YES]; |
| | | // 箭头向上时的箭头位置 |
| | | if (_isUpward) { |
| | | [maskPath addLineToPoint:CGPointMake(arrowPoint.x - arrowWidth/2, kPopoverViewArrowHeight)]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x - arrowCornerRadius, arrowCornerRadius) |
| | | controlPoint:CGPointMake(arrowPoint.x - arrowWidth/2 + arrowBottomCornerRadius, kPopoverViewArrowHeight)]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x + arrowCornerRadius, arrowCornerRadius) |
| | | controlPoint:arrowPoint]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x + arrowWidth/2, kPopoverViewArrowHeight) |
| | | controlPoint:CGPointMake(arrowPoint.x + arrowWidth/2 - arrowBottomCornerRadius, kPopoverViewArrowHeight)]; |
| | | } |
| | | // 右上圆角 |
| | | [maskPath addLineToPoint:CGPointMake(currentW - cornerRadius, maskTop)]; |
| | | [maskPath addArcWithCenter:CGPointMake(currentW - cornerRadius, maskTop + cornerRadius) |
| | | radius:cornerRadius |
| | | startAngle:DegreesToRadians(270) |
| | | endAngle:DegreesToRadians(0) |
| | | clockwise:YES]; |
| | | // 右下圆角 |
| | | [maskPath addLineToPoint:CGPointMake(currentW, maskBottom - cornerRadius)]; |
| | | [maskPath addArcWithCenter:CGPointMake(currentW - cornerRadius, maskBottom - cornerRadius) |
| | | radius:cornerRadius |
| | | startAngle:DegreesToRadians(0) |
| | | endAngle:DegreesToRadians(90) |
| | | clockwise:YES]; |
| | | // 箭头向下时的箭头位置 |
| | | if (!_isUpward) { |
| | | [maskPath addLineToPoint:CGPointMake(arrowPoint.x + arrowWidth/2, currentH - kPopoverViewArrowHeight)]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x + arrowCornerRadius, currentH - arrowCornerRadius) |
| | | controlPoint:CGPointMake(arrowPoint.x + arrowWidth/2 - arrowBottomCornerRadius, currentH - kPopoverViewArrowHeight)]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x - arrowCornerRadius, currentH - arrowCornerRadius) |
| | | controlPoint:arrowPoint]; |
| | | [maskPath addQuadCurveToPoint:CGPointMake(arrowPoint.x - arrowWidth/2, currentH - kPopoverViewArrowHeight) |
| | | controlPoint:CGPointMake(arrowPoint.x - arrowWidth/2 + arrowBottomCornerRadius, currentH - kPopoverViewArrowHeight)]; |
| | | } |
| | | // 左下圆角 |
| | | [maskPath addLineToPoint:CGPointMake(cornerRadius, maskBottom)]; |
| | | [maskPath addArcWithCenter:CGPointMake(cornerRadius, maskBottom - cornerRadius) |
| | | radius:cornerRadius |
| | | startAngle:DegreesToRadians(90) |
| | | endAngle:DegreesToRadians(180) |
| | | clockwise:YES]; |
| | | [maskPath closePath]; |
| | | // 截取圆角和箭头 |
| | | CAShapeLayer *maskLayer = [CAShapeLayer layer]; |
| | | maskLayer.frame = self.bounds; |
| | | maskLayer.path = maskPath.CGPath; |
| | | self.layer.mask = maskLayer; |
| | | // 边框 (只有在不显示半透明阴影层时才设置边框线条) |
| | | if (!_showShade) { |
| | | CAShapeLayer *borderLayer = [CAShapeLayer layer]; |
| | | borderLayer.frame = self.bounds; |
| | | borderLayer.path = maskPath.CGPath; |
| | | borderLayer.lineWidth = 1; |
| | | borderLayer.fillColor = [UIColor clearColor].CGColor; |
| | | borderLayer.strokeColor = _tableView.separatorColor.CGColor; |
| | | [self.layer addSublayer:borderLayer]; |
| | | _borderLayer = borderLayer; |
| | | } |
| | | |
| | | [_keyWindow addSubview:self]; |
| | | |
| | | // 弹出动画 |
| | | CGRect oldFrame = self.frame; |
| | | self.layer.anchorPoint = CGPointMake(arrowPoint.x/currentW, _isUpward ? 0.f : 1.f); |
| | | self.frame = oldFrame; |
| | | self.transform = CGAffineTransformMakeScale(0.01f, 0.01f); |
| | | [UIView animateWithDuration:0.25f animations:^{ |
| | | self.transform = CGAffineTransformIdentity; |
| | | _shadeView.alpha = 1.f; |
| | | }]; |
| | | } |
| | | |
| | | /*! @brief 计算最大宽度 */ |
| | | - (CGFloat)calculateMaxWidth { |
| | | CGFloat maxWidth = 0.f, titleLeftEdge = 0.f, imageWidth = 0.f, imageMaxHeight = kPopoverViewCellHeight - PopoverViewCellVerticalMargin*2; |
| | | CGSize imageSize = CGSizeZero; |
| | | UIFont *titleFont = [PopoverViewCell titleFont]; |
| | | for (PopoverAction *action in _actions) { |
| | | imageWidth = 0.f; |
| | | titleLeftEdge = 0.f; |
| | | |
| | | if (action.image) { // 存在图片则根据图片size和图片最大高度来重新计算图片宽度 |
| | | titleLeftEdge = PopoverViewCellTitleLeftEdge; // 有图片时标题才有左边的边距 |
| | | imageSize = action.image.size; |
| | | if (imageSize.height > imageMaxHeight) { |
| | | imageWidth = imageMaxHeight*imageSize.width/imageSize.height; |
| | | } else { |
| | | imageWidth = imageSize.width; |
| | | } |
| | | } |
| | | |
| | | CGFloat titleWidth; |
| | | if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0) { // iOS7及往后版本 |
| | | titleWidth = [action.title sizeWithAttributes:@{NSFontAttributeName : titleFont}].width; |
| | | } else { // iOS6 |
| | | #pragma GCC diagnostic push |
| | | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
| | | titleWidth = [action.title sizeWithFont:titleFont].width; |
| | | #pragma GCC diagnostic pop |
| | | } |
| | | |
| | | CGFloat contentWidth = PopoverViewCellHorizontalMargin*2 + imageWidth + titleLeftEdge + titleWidth; |
| | | if (contentWidth > maxWidth) { |
| | | maxWidth = ceil(contentWidth); // 获取最大宽度时需使用进一取法, 否则Cell中没有图片时会可能导致标题显示不完整. |
| | | } |
| | | } |
| | | |
| | | // 如果最大宽度大于(窗口宽度 - kPopoverViewMargin*2)则限制最大宽度等于(窗口宽度 - kPopoverViewMargin*2) |
| | | if (maxWidth > CGRectGetWidth(_keyWindow.bounds) - kPopoverViewMargin*2) { |
| | | maxWidth = CGRectGetWidth(_keyWindow.bounds) - kPopoverViewMargin*2; |
| | | } |
| | | |
| | | return maxWidth; |
| | | } |
| | | |
| | | /*! @brief 点击外部隐藏弹窗 */ |
| | | - (void)hide { |
| | | [UIView animateWithDuration:0.25f animations:^{ |
| | | self.alpha = 0.f; |
| | | _shadeView.alpha = 0.f; |
| | | self.transform = CGAffineTransformMakeScale(0.01f, 0.01f); |
| | | } completion:^(BOOL finished) { |
| | | [_shadeView removeFromSuperview]; |
| | | [self removeFromSuperview]; |
| | | }]; |
| | | } |
| | | |
| | | #pragma mark - Public |
| | | + (instancetype)popoverView { |
| | | return [[self alloc] init]; |
| | | } |
| | | |
| | | /*! @brief 指向指定的View来显示弹窗 */ |
| | | - (void)showToView:(UIView *)pointView withActions:(NSArray<PopoverAction *> *)actions { |
| | | // 判断 pointView 是偏上还是偏下 |
| | | CGRect pointViewRect = [pointView.superview convertRect:pointView.frame toView:_keyWindow]; |
| | | CGFloat pointViewUpLength = CGRectGetMinY(pointViewRect); |
| | | CGFloat pointViewDownLength = _windowHeight - CGRectGetMaxY(pointViewRect); |
| | | // 弹窗箭头指向的点 |
| | | CGPoint toPoint = CGPointMake(CGRectGetMidX(pointViewRect), 0); |
| | | // 弹窗在 pointView 顶部 |
| | | if (pointViewUpLength > pointViewDownLength) { |
| | | toPoint.y = pointViewUpLength - 5; |
| | | } |
| | | // 弹窗在 pointView 底部 |
| | | else { |
| | | toPoint.y = CGRectGetMaxY(pointViewRect) + 5; |
| | | } |
| | | |
| | | // 箭头指向方向 |
| | | _isUpward = pointViewUpLength <= pointViewDownLength; |
| | | _actions = [actions copy]; |
| | | [self showToPoint:toPoint]; |
| | | } |
| | | |
| | | /*! @brief 指向指定的点来显示弹窗 */ |
| | | - (void)showToPoint:(CGPoint)toPoint withActions:(NSArray<PopoverAction *> *)actions { |
| | | _actions = [actions copy]; |
| | | // 计算箭头指向方向 |
| | | _isUpward = toPoint.y <= _windowHeight - toPoint.y; |
| | | [self showToPoint:toPoint]; |
| | | } |
| | | |
| | | #pragma mark - UITableViewDelegate & UITableViewDataSource |
| | | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { |
| | | return _actions.count; |
| | | } |
| | | |
| | | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { |
| | | return kPopoverViewCellHeight; |
| | | } |
| | | |
| | | static NSString *kPopoverCellIdentifier = @"kPopoverCellIdentifier"; |
| | | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { |
| | | PopoverViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kPopoverCellIdentifier]; |
| | | if (!cell) { |
| | | cell = [[PopoverViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kPopoverCellIdentifier]; |
| | | } |
| | | |
| | | [cell setAction:_actions[indexPath.row]]; |
| | | [cell showBottomLine: indexPath.row < _actions.count - 1]; |
| | | cell.style = _style; |
| | | |
| | | return cell; |
| | | } |
| | | |
| | | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { |
| | | [UIView animateWithDuration:0.25f animations:^{ |
| | | self.alpha = 0.f; |
| | | _shadeView.alpha = 0.f; |
| | | } completion:^(BOOL finished) { |
| | | PopoverAction *action = _actions[indexPath.row]; |
| | | action.handler ? action.handler(action) : NULL; |
| | | _actions = nil; |
| | | [_shadeView removeFromSuperview]; |
| | | [self removeFromSuperview]; |
| | | }]; |
| | | } |
| | | |
| | | @end |
| | | |
New file |
| | |
| | | // |
| | | // PopoverViewCell.h |
| | | // Popover |
| | | // |
| | | // Created by StevenLee on 2016/12/10. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import <UIKit/UIKit.h> |
| | | #import "PopoverAction.h" |
| | | |
| | | UIKIT_EXTERN float const PopoverViewCellHorizontalMargin; ///< 水平间距边距 |
| | | UIKIT_EXTERN float const PopoverViewCellVerticalMargin; ///< 垂直边距 |
| | | UIKIT_EXTERN float const PopoverViewCellTitleLeftEdge; ///< 标题左边边距 |
| | | |
| | | @class PopoverAction; |
| | | |
| | | @interface PopoverViewCell : UITableViewCell |
| | | |
| | | @property (nonatomic, assign) PopoverViewStyle style; |
| | | |
| | | /*! @brief 标题字体 |
| | | */ |
| | | + (UIFont *)titleFont; |
| | | |
| | | /*! @brief 底部线条颜色 |
| | | */ |
| | | + (UIColor *)bottomLineColorForStyle:(PopoverViewStyle)style; |
| | | |
| | | - (void)setAction:(PopoverAction *)action; |
| | | |
| | | - (void)showBottomLine:(BOOL)show; |
| | | |
| | | @end |
New file |
| | |
| | | // |
| | | // PopoverViewCell.m |
| | | // Popover |
| | | // |
| | | // Created by StevenLee on 2016/12/10. |
| | | // Copyright © 2016年 lifution. All rights reserved. |
| | | // |
| | | |
| | | #import "PopoverViewCell.h" |
| | | |
| | | // extern |
| | | float const PopoverViewCellHorizontalMargin = 15.f; ///< 水平边距 |
| | | float const PopoverViewCellVerticalMargin = 3.f; ///< 垂直边距 |
| | | float const PopoverViewCellTitleLeftEdge = 8.f; ///< 标题左边边距 |
| | | |
| | | @interface PopoverViewCell () |
| | | |
| | | @property (nonatomic, strong) UIButton *button; |
| | | @property (nonatomic, weak) UIView *bottomLine; |
| | | |
| | | @end |
| | | |
| | | @implementation PopoverViewCell |
| | | |
| | | #pragma mark - Life Cycle |
| | | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { |
| | | if (!(self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) return nil; |
| | | self.backgroundColor = [UIColor clearColor]; |
| | | self.contentView.backgroundColor = self.backgroundColor; |
| | | self.selectionStyle = UITableViewCellSelectionStyleNone; |
| | | // initialize |
| | | [self initialize]; |
| | | |
| | | return self; |
| | | } |
| | | |
| | | - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { |
| | | [super setHighlighted:highlighted animated:animated]; |
| | | if (highlighted) { |
| | | self.backgroundColor = _style == PopoverViewStyleDefault ? [UIColor colorWithRed:0.90 green:0.90 blue:0.90 alpha:1.00] : [UIColor colorWithRed:0.23 green:0.23 blue:0.23 alpha:1.00]; |
| | | } else { |
| | | [UIView animateWithDuration:0.3f animations:^{ |
| | | self.backgroundColor = [UIColor clearColor]; |
| | | }]; |
| | | } |
| | | } |
| | | |
| | | #pragma mark - Setter |
| | | - (void)setStyle:(PopoverViewStyle)style { |
| | | _style = style; |
| | | _bottomLine.backgroundColor = [self.class bottomLineColorForStyle:style]; |
| | | if (_style == PopoverViewStyleDefault) { |
| | | [_button setTitleColor:UIColor.blackColor forState:UIControlStateNormal]; |
| | | } else { |
| | | [_button setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; |
| | | } |
| | | } |
| | | |
| | | #pragma mark - Private |
| | | // 初始化 |
| | | - (void)initialize { |
| | | // UI |
| | | _button = [UIButton buttonWithType:UIButtonTypeCustom]; |
| | | _button.userInteractionEnabled = NO; // has no use for UserInteraction. |
| | | _button.translatesAutoresizingMaskIntoConstraints = NO; |
| | | _button.titleLabel.font = [self.class titleFont]; |
| | | _button.backgroundColor = self.contentView.backgroundColor; |
| | | _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; |
| | | [_button setTitleColor:UIColor.blackColor forState:UIControlStateNormal]; |
| | | [self.contentView addSubview:_button]; |
| | | // Constraint |
| | | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-margin-[_button]-margin-|" options:kNilOptions metrics:@{@"margin" : @(PopoverViewCellHorizontalMargin)} views:NSDictionaryOfVariableBindings(_button)]]; |
| | | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-margin-[_button]-margin-|" options:kNilOptions metrics:@{@"margin" : @(PopoverViewCellVerticalMargin)} views:NSDictionaryOfVariableBindings(_button)]]; |
| | | // 底部线条 |
| | | UIView *bottomLine = [[UIView alloc] init]; |
| | | bottomLine.backgroundColor = [UIColor colorWithRed:0.75 green:0.75 blue:0.75 alpha:1.00]; |
| | | bottomLine.translatesAutoresizingMaskIntoConstraints = NO; |
| | | [self.contentView addSubview:bottomLine]; |
| | | _bottomLine = bottomLine; |
| | | // Constraint |
| | | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[bottomLine]|" options:kNilOptions metrics:nil views:NSDictionaryOfVariableBindings(bottomLine)]]; |
| | | [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[bottomLine(lineHeight)]|" options:kNilOptions metrics:@{@"lineHeight" : @(1/[UIScreen mainScreen].scale)} views:NSDictionaryOfVariableBindings(bottomLine)]]; |
| | | } |
| | | |
| | | #pragma mark - Public |
| | | /*! @brief 标题字体 */ |
| | | + (UIFont *)titleFont { |
| | | return [UIFont systemFontOfSize:15.f]; |
| | | } |
| | | |
| | | /*! @brief 底部线条颜色 */ |
| | | + (UIColor *)bottomLineColorForStyle:(PopoverViewStyle)style { |
| | | return style == PopoverViewStyleDefault ? [UIColor colorWithRed:0.75 green:0.75 blue:0.75 alpha:1.00] : [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1.00]; |
| | | } |
| | | |
| | | - (void)setAction:(PopoverAction *)action { |
| | | [_button setImage:action.image forState:UIControlStateNormal]; |
| | | [_button setTitle:action.title forState:UIControlStateNormal]; |
| | | _button.titleEdgeInsets = action.image ? UIEdgeInsetsMake(0, PopoverViewCellTitleLeftEdge, 0, -PopoverViewCellTitleLeftEdge) : UIEdgeInsetsZero; |
| | | } |
| | | |
| | | - (void)showBottomLine:(BOOL)show { |
| | | _bottomLine.hidden = !show; |
| | | } |
| | | |
| | | @end |
New file |
| | |
| | | # Popover |
| | | ###一款优雅好用的类似QQ和微信消息页面的右上角微型菜单弹窗, 最低支持iOS6<p> |
| | | 该弹窗控件有白色和黑色这两种风格, 使用方法也非常简单, 和系统的UIAlertController差不多的使用方法, 你只需要设置好对应的action和设定好弹窗箭头要指向的点(CGPoint)或者要指向的控件即可, 该弹窗控件会自动计算箭头指向和弹出位置<p> |
| | | 所有效果如下图:<p> |
| | | ![Alt text][image-5]<p> |
| | | 该弹窗有两种风格:<p> |
| | | 白色风格: `PopoverViewStyleDefault` (默认为此风格)<p> |
| | | ![Alt text][image-1]<p> |
| | | 黑色风格: `PopoverViewStyleDark`<p> |
| | | ![Alt text][image-2]<p> |
| | | 可以设置图片也可以不设置图片: |
| | | ```objc |
| | | - (IBAction)showWithoutImage:(UIButton *)sender { |
| | | PopoverAction *action1 = [PopoverAction actionWithTitle:@"Title" handler:^(PopoverAction *action) { |
| | | // 该Block不会导致内存泄露, Block内代码无需刻意去设置弱引用. |
| | | }]; |
| | | ... |
| | | PopoverView *popoverView = [PopoverView popoverView]; |
| | | popoverView.style = PopoverViewStyleDark; |
| | | [popoverView showToView:sender withActions:@[action1, ...]]; |
| | | } |
| | | ``` |
| | | ![Alt text][image-4]<p> |
| | | 也可以设置在弹出窗口时显示背景阴影层: |
| | | ```objc |
| | | - (IBAction)rightButtonAction:(UIButton *)sender { |
| | | PopoverView *popoverView = [PopoverView popoverView]; |
| | | popoverView.showShade = YES; // 显示阴影背景 |
| | | [popoverView showToView:sender withActions:@[...]]; |
| | | } |
| | | ``` |
| | | ![Alt text][image-3]<p> |
| | | 使用方法: (将PopoverView文件夹拖到你的项目中然后 `#import "PopoverView.h"` ) |
| | | ```objc |
| | | // 附带左边图标的 |
| | | PopoverAction *action1 = [PopoverAction actionWithImage:Image title:@"Title" handler:^(PopoverAction *action) { |
| | | // 该Block不会导致内存泄露, Block内代码无需刻意去设置弱引用. |
| | | }]; |
| | | // 纯标题的 |
| | | PopoverAction *action1 = [PopoverAction actionWithTitle:@"Title" handler:^(PopoverAction *action) { |
| | | // 该Block不会导致内存泄露, Block内代码无需刻意去设置弱引用. |
| | | }]; |
| | | ... |
| | | PopoverView *popoverView = [PopoverView popoverView]; |
| | | //popoverView.showShade = YES; // 显示阴影背景 |
| | | //popoverView.style = PopoverViewStyleDark; // 设置为黑色风格 |
| | | //popoverView.hideAfterTouchOutside = NO; // 点击外部时不允许隐藏 |
| | | // 有两种显示方法 |
| | | // 1. 显示在指定的控件 |
| | | [popoverView showToView:sender withActions:@[action1, ...]]; |
| | | // 2. 显示在指定的点(CGPoint), 该点的坐标是相对KeyWidnow的坐标. |
| | | [popoverView showToPoint:CGPointMake(20, 64) withActions:@[action1, ...]]; |
| | | ``` |
| | | ## LICENSE |
| | | PopoverView is available under the MIT license. See the LICENSE file for more info. |
| | | |
| | | [image-1]:http://oeysrv69b.bkt.clouddn.com/1.png |
| | | [image-2]:http://oeysrv69b.bkt.clouddn.com/2.png |
| | | [image-3]:http://oeysrv69b.bkt.clouddn.com/5.png |
| | | [image-4]:http://oeysrv69b.bkt.clouddn.com/4.png |
| | | [image-5]:http://oeysrv69b.bkt.clouddn.com/Popover.gif |
| | | |