Commit 3b6941d8 authored by 乔金柱's avatar 乔金柱

Merge branch 'lym/text' into 'master'

Lym/text

See merge request !21
parents 4a4ba4ae 9e91ae10
......@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
04393781246AA49D00EAE014 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04393780246AA49D00EAE014 /* File.swift */; };
0AB11836BD16E7A177F2CBDF /* Pods_GMBase_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6E1B1FCE1B7696F7DE8B8E9 /* Pods_GMBase_Example.framework */; };
29C10D9EC61CDA2F6F466BD4 /* Pods_GMBase_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E15FCB251AFC31B335265AF /* Pods_GMBase_Tests.framework */; };
6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
......@@ -40,6 +41,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
04393780246AA49D00EAE014 /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
6003F58A195388D20070C39A /* GMBase_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GMBase_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
......@@ -150,6 +152,7 @@
D32ECC461D33946600AEF0D0 /* GMListViewController.h */,
D32ECC471D33946600AEF0D0 /* GMListViewController.m */,
D3EB0CC21D33968300EEDD8B /* GMListViewModel.h */,
04393780246AA49D00EAE014 /* File.swift */,
D3EB0CC31D33968300EEDD8B /* GMListViewModel.m */,
D32ECC411D33840600AEF0D0 /* GMDetailController.h */,
D32ECC421D33840600AEF0D0 /* GMDetailController.m */,
......@@ -225,6 +228,7 @@
6003F587195388D20070C39A /* Frameworks */,
6003F588195388D20070C39A /* Resources */,
20C43A9AD7543F1CB63A4FB9 /* [CP] Embed Pods Frameworks */,
9EF5C8615510ED2B25E84552 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
......@@ -275,6 +279,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
......@@ -320,34 +325,50 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GMBase_Example/Pods-GMBase_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework",
"${BUILT_PRODUCTS_DIR}/GMBase/GMBase.framework",
"${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework",
"${BUILT_PRODUCTS_DIR}/EVReflection/EVReflection.framework",
"${BUILT_PRODUCTS_DIR}/GM-Swift-Observable/GM_Swift_Observable.framework",
"${BUILT_PRODUCTS_DIR}/GMCache/GMCache.framework",
"${BUILT_PRODUCTS_DIR}/GMFoundation/GMFoundation.framework",
"${BUILT_PRODUCTS_DIR}/GMHud/GMHud.framework",
"${BUILT_PRODUCTS_DIR}/GMJSONModel/GMJSONModel.framework",
"${BUILT_PRODUCTS_DIR}/GMKit/GMKit.framework",
"${BUILT_PRODUCTS_DIR}/GMNetService/GMNetService.framework",
"${BUILT_PRODUCTS_DIR}/GMNetworking/GMNetworking.framework",
"${BUILT_PRODUCTS_DIR}/GMPhobos/GMPhobos.framework",
"${BUILT_PRODUCTS_DIR}/GMRefresh/GMRefresh.framework",
"${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework",
"${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework",
"${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework",
"${BUILT_PRODUCTS_DIR}/MagicalRecord/MagicalRecord.framework",
"${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework",
"${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework",
"${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework",
"${BUILT_PRODUCTS_DIR}/TMCache/TMCache.framework",
"${BUILT_PRODUCTS_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMBase.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EVReflection.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GM_Swift_Observable.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMCache.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMFoundation.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMHud.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMJSONModel.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMNetService.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMNetworking.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMPhobos.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMRefresh.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MagicalRecord.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TMCache.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/UITableView_FDTemplateLayoutCell.framework",
);
......@@ -374,6 +395,24 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9EF5C8615510ED2B25E84552 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GMBase_Example/Pods-GMBase_Example-resources.sh",
"${PODS_ROOT}/Weibo_SDK/libWeiboSDK/WeiboSDK.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/WeiboSDK.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-GMBase_Example/Pods-GMBase_Example-resources.sh\"\n";
showEnvVarsInLog = 0;
};
E11DAE1A31A4A404D5D11E70 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
......@@ -401,6 +440,7 @@
files = (
D32ECC481D33946600AEF0D0 /* GMListViewController.m in Sources */,
6003F59E195388D20070C39A /* GMAppDelegate.m in Sources */,
04393781246AA49D00EAE014 /* File.swift in Sources */,
6003F5A7195388D20070C39A /* GMViewController.m in Sources */,
D32ECC431D33840600AEF0D0 /* GMDetailController.m in Sources */,
D3EB0CC41D33968300EEDD8B /* GMListViewModel.m in Sources */,
......@@ -535,7 +575,9 @@
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "GMBase/GMBase_Example-Bridging-Header.h";
SWIFT_OBJC_INTERFACE_HEADER_NAME = "$GMBase-Swift.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
WRAPPER_EXTENSION = app;
};
name = Debug;
......@@ -556,6 +598,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "GMBase/GMBase_Example-Bridging-Header.h";
SWIFT_OBJC_INTERFACE_HEADER_NAME = "$GMBase-Swift.h";
SWIFT_VERSION = 4.2;
WRAPPER_EXTENSION = app;
};
name = Release;
......@@ -564,6 +608,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = E10ABE29C983D16788B32755 /* Pods-GMBase_Tests.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
......@@ -588,6 +633,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 78552CB3DCC72D38AB9DD053 /* Pods-GMBase_Tests.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
......
//
// File.swift
// GMBase_Example
//
// Created by Q14 on 2020/5/12.
// Copyright © 2020 wangyang. All rights reserved.
//
import Foundation
......@@ -6,7 +6,7 @@
// Copyright © 2016年 wangyang. All rights reserved.
//
@import GMBase;
//@import GMBase;
#import "GMListViewModel.h"
@interface GMListViewController : WMBaseListViewController
......
use_frameworks!
inhibit_all_warnings!
platform :ios, '8.0'
platform :ios, '9.0'
#open source
source 'https://github.com/CocoaPods/Specs.git'
#our company
......@@ -8,7 +8,11 @@ source 'git@git.wanmeizhensuo.com:gengmeiios/GMSpecs.git'
target 'GMBase_Example' do
pod 'GMBase', :path => '../'
pod 'SnapKit', '4.2.0'
pod 'GMShareSDK', '0.2.1'
pod 'GMBaseSwift', :path => '../../GMBaseSwift'
pod 'GMPhobos', :git => 'git@git.wanmeizhensuo.com:gengmeiios/GMPhobos.git', :commit => '7e58199898627699373ad6a9f87b875ab04b0927'
target 'GMBase_Tests' do
inherit! :search_paths
......
......@@ -14,110 +14,202 @@ PODS:
- AFNetworking/Serialization (3.1.0)
- AFNetworking/UIKit (3.1.0):
- AFNetworking/NSURLSession
- Alamofire (4.7.0)
- BDOpenSDKKit (1.0.0)
- DouyinOpenSDK (1.4.1):
- BDOpenSDKKit (~> 1.0.0)
- EVReflection (5.10.0):
- EVReflection/Core (= 5.10.0)
- EVReflection/Core (5.10.0)
- GM-Swift-Observable (4.0.1)
- GMBase (1.1.5):
- GMBaseSwift
- GMHud
- GMJSONModel
- GMKit
- GMNetService
- GMNetworking
- GMPhobos
- GMRefresh
- GMShareSDK
- MBProgressHUD
- SDWebImage
- "UITableView+FDTemplateLayoutCell (= 1.4)"
- GMBaseSwift (3.4.1):
- EVReflection (= 5.10.0)
- GM-Swift-Observable
- GMHud
- GMKit
- GMNetworking
- GMPhobos
- GMRefresh
- SnapKit (= 4.2.0)
- GMCache (1.0.1):
- TMCache (= 2.1.0)
- GMHud (1.0.2):
- GMFoundation (1.0.8)
- GMHud (1.0.3):
- MBProgressHUD (= 0.9.2)
- GMJSONModel (1.7.4)
- GMKit (1.1.4):
- GMKit/Category (= 1.1.4)
- GMKit/Color (= 1.1.4)
- GMKit/Constant (= 1.1.4)
- GMKit/FDFullscreenPopGesture (= 1.1.4)
- GMKit/Kit (= 1.1.4)
- GMKit/Protocol (= 1.1.4)
- GMKit (1.2.6):
- GMKit/Category (= 1.2.6)
- GMKit/Color (= 1.2.6)
- GMKit/Constant (= 1.2.6)
- GMKit/FDFullscreenPopGesture (= 1.2.6)
- GMKit/Kit (= 1.2.6)
- GMKit/Protocol (= 1.2.6)
- Masonry
- SDWebImage
- GMKit/Category (1.1.4):
- GMKit/Color (= 1.1.4)
- GMKit/Constant (= 1.1.4)
- GMKit/Protocol (= 1.1.4)
- SnapKit
- GMKit/Category (1.2.6):
- GMKit/Color (= 1.2.6)
- GMKit/Constant (= 1.2.6)
- GMKit/Protocol (= 1.2.6)
- Masonry
- SDWebImage
- GMKit/Color (1.1.4):
- SnapKit
- GMKit/Color (1.2.6):
- Masonry
- SDWebImage
- GMKit/Constant (1.1.4):
- SnapKit
- GMKit/Constant (1.2.6):
- Masonry
- SDWebImage
- GMKit/FDFullscreenPopGesture (1.1.4):
- SnapKit
- GMKit/FDFullscreenPopGesture (1.2.6):
- Masonry
- SDWebImage
- GMKit/Kit (1.1.4):
- GMKit/Category (= 1.1.4)
- GMKit/Color (= 1.1.4)
- GMKit/Constant (= 1.1.4)
- GMKit/Protocol (= 1.1.4)
- SnapKit
- GMKit/Kit (1.2.6):
- GMKit/Category (= 1.2.6)
- GMKit/Color (= 1.2.6)
- GMKit/Constant (= 1.2.6)
- GMKit/Protocol (= 1.2.6)
- Masonry
- SDWebImage
- GMKit/Protocol (1.1.4):
- SnapKit
- GMKit/Protocol (1.2.6):
- Masonry
- SDWebImage
- SnapKit
- GMNetService (1.0.2):
- AFNetworking (= 3.1.0)
- GMPhobos (1.3.5):
- GMNetworking (4.0.7):
- Alamofire (= 4.7.0)
- GMPhobos (2.0.4):
- GMCache
- MagicalRecord
- MJExtension
- GMRefresh (1.0.4):
- GMPhobos
- MJRefresh
- GMShareSDK (0.2.1):
- DouyinOpenSDK (= 1.4.1)
- GMFoundation
- GMJSONModel
- GMKit
- GMRefresh (1.0.2):
- GMPhobos
- Masonry
- MBProgressHUD (= 0.9.2)
- WechatOpenSDK (= 1.8.6.2)
- Weibo_SDK (= 3.2.7)
- MagicalRecord (2.3.2):
- MagicalRecord/Core (= 2.3.2)
- MagicalRecord/Core (2.3.2)
- Masonry (1.1.0)
- MBProgressHUD (0.9.2)
- SDWebImage (5.1.1):
- SDWebImage/Core (= 5.1.1)
- SDWebImage/Core (5.1.1)
- MJExtension (3.2.1)
- MJRefresh (3.4.3)
- SDWebImage (5.8.0):
- SDWebImage/Core (= 5.8.0)
- SDWebImage/Core (5.8.0)
- SnapKit (4.2.0)
- TMCache (2.1.0)
- "UITableView+FDTemplateLayoutCell (1.4)"
- WechatOpenSDK (1.8.6.2)
- Weibo_SDK (3.2.7)
DEPENDENCIES:
- GMBase (from `../`)
- GMBaseSwift (from `../../GMBaseSwift`)
- "GMPhobos (from `git@git.wanmeizhensuo.com:gengmeiios/GMPhobos.git`, commit `7e58199898627699373ad6a9f87b875ab04b0927`)"
- GMShareSDK (= 0.2.1)
- SnapKit (= 4.2.0)
SPEC REPOS:
"git@git.wanmeizhensuo.com:gengmeiios/GMSpecs.git":
- GM-Swift-Observable
- GMCache
- GMFoundation
- GMHud
- GMJSONModel
- GMKit
- GMNetService
- GMPhobos
- GMNetworking
- GMRefresh
- GMShareSDK
https://github.com/CocoaPods/Specs.git:
- AFNetworking
- Alamofire
- BDOpenSDKKit
- DouyinOpenSDK
- EVReflection
- MagicalRecord
- Masonry
- MBProgressHUD
- MJExtension
- MJRefresh
- SDWebImage
- SnapKit
- TMCache
- "UITableView+FDTemplateLayoutCell"
- WechatOpenSDK
- Weibo_SDK
EXTERNAL SOURCES:
GMBase:
:path: "../"
GMBaseSwift:
:path: "../../GMBaseSwift"
GMPhobos:
:commit: 7e58199898627699373ad6a9f87b875ab04b0927
:git: "git@git.wanmeizhensuo.com:gengmeiios/GMPhobos.git"
CHECKOUT OPTIONS:
GMPhobos:
:commit: 7e58199898627699373ad6a9f87b875ab04b0927
:git: "git@git.wanmeizhensuo.com:gengmeiios/GMPhobos.git"
SPEC CHECKSUMS:
AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67
GMBase: b747cd3ecd7a5109469113cf48ce04ae6d16cdbe
Alamofire: 907e0a98eb68cdb7f9d1f541a563d6ac5dc77b25
BDOpenSDKKit: 3fb530ce73f85a7d6ee69e7fd3d9158444c5bd09
DouyinOpenSDK: 5ba83de22963ba7a3ba70c8ff11dfcb2885ecc2b
EVReflection: 1abc1a81927ab0d30170238cf9b79bff489e9728
GM-Swift-Observable: 756d8fc13638b9faa68cb10266b2ffb47a911595
GMBase: 358e72062cb0f64a57ff34ec181b20ad9973d79b
GMBaseSwift: 8f327883b33ac24d0dcdb648ac3f9d6c57949ad5
GMCache: b78d8e46db864405e91d226ce640cc80d966c611
GMHud: 45aa755b72a65f89d810430336803086359c0fb1
GMFoundation: e9f7fd9c6e5f133e09009b0ee5de4fce60ac5682
GMHud: 18d41f4900a204f27be14e9504fcee2060ae3b2c
GMJSONModel: 5e81a98de668e9f93cf6ff77869f77b0d1a806be
GMKit: 11c9ab9a317f381a05b0e1e577dd95a495625edf
GMKit: ff2a77a9b85e13b4de333ec5eeb10b1ffef09756
GMNetService: 7c69e7981b4fac29657fad5fc86a0c453196b862
GMPhobos: 1e2d68c456b69bf156276d7242877498107474db
GMRefresh: 9d2c521e3d49b68d3c736fb138a87fae4adb05f9
GMNetworking: 592b9b71f2a7d92203483276158ce3139ac789d2
GMPhobos: c09920b4a726363b902c2f14ba64e1ee1620d0e2
GMRefresh: c01ff8de5ada92e1362602fb6991f99124b7dbe3
GMShareSDK: a0725e2848d043aec84e787f6d233ac1546c1661
MagicalRecord: 53bed74b4323b930992a725be713e53b37d19755
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
MBProgressHUD: 1569cf7ace17a8bac47aabfbb8580a49690386d1
SDWebImage: 96d7f03415ccb28d299d765f93557ff8a617abd8
MJExtension: 635f2c663dcb1bf76fa4b715b2570a5710aec545
MJRefresh: 53e3e3219f204425ee6d3e62e8733d3295944cd6
SDWebImage: 84000f962cbfa70c07f19d2234cbfcf5d779b5dc
SnapKit: fe8a619752f3f27075cc9a90244d75c6c3f27e2a
TMCache: 95ebcc9b3c7e90fb5fd8fc3036cba3aa781c9bed
"UITableView+FDTemplateLayoutCell": 234e1582bcc4e18461af91155123bb96538ed030
WechatOpenSDK: 8b3ba4239193d1112205c139c94e21934e8f369a
Weibo_SDK: 5a4d08f7e1fedbb635435e4585c8c0439c7da089
PODFILE CHECKSUM: b9c24bb8fb1ea50b58c59e079b456b4ca1d9b998
PODFILE CHECKSUM: db60bbf458f56874386142fa246e256c5fa92944
COCOAPODS: 1.9.1
......@@ -18,4 +18,15 @@ Pod::Spec.new do |s|
s.dependency 'GMHud'
s.dependency 'GMKit'
s.dependency 'SDWebImage'
# s.dependency 'SnapKit', '4.0.0'
s.dependency 'GMShareSDK'
s.dependency 'GMNetworking'
# s.dependency 'PLMediaStreamingKit'
# s.dependency 'PLPlayerKit'
# s.dependency 'GMAlbum'
# SnapKit 4.2.0
# s.dependency 'SnapKit', '4.2.0'
s.dependency 'GMBaseSwift'
s.swift_version = '4.2'
s.static_framework = true
end
//
// GMAddressManager.h
// Gengmei
//
// Created by 翟国钧 on 16/9/28.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import <GMBase/GMObject.h>
//@import GMBase;
typedef void (^AddressBookGetOnePersonBlock) (NSDictionary *result);
@interface GMAddressManager : GMObject
@property(nonatomic, copy) AddressBookGetOnePersonBlock getOneContactPersonBlock;
/**
获取通讯录联系人的授权方法
@author zhaiguojun 16-09-28 in 6.4.1
@return return value description
*/
- (void)getAddressBookAuthorization;
/**
获取一个用户选择的通讯录联系人
@author zhaiguojun 16-09-28 in 6.4.1
@return return value description
*/
- (void)chooseContactPersonAddressBookJsonString;
@end
//
// GMAddressManager.m
// Gengmei
//
// Created by 翟国钧 on 16/9/28.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import <Contacts/Contacts.h>
#import <ContactsUI/ContactsUI.h>
#import <GMHud/GMHudModule.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/ABPeoplePickerNavigationController.h>
#import <AddressBook/ABPerson.h>
#import <AddressBookUI/ABPersonViewController.h>
#import "GMBaseTool.h"
#import <GMKit/GMSafeValue.h>
#import "GMAddressManager.h"
#import <GMFoundation/GMFoundation-umbrella.h>
//#import <GMNetworking/GM>
@import GMNetworking;
@interface GMAddressManager ()<ABPeoplePickerNavigationControllerDelegate, CNContactPickerDelegate>
@end
@implementation GMAddressManager
- (instancetype)init
{
self = [super init];
if (self) {
}
return self;
}
- (void)getAddressBookAuthorization {
__weak __typeof(self)weakSelf = self;
if ([[[UIDevice currentDevice] systemVersion] compare:@"9.0" options:NSNumericSearch] == NSOrderedAscending)
{
[self checkAddressBookAuthorization:^(bool isAuthorized) {
if (isAuthorized) {
[weakSelf getAllAddress];
}
}];
} else {
[self checkAddressBookIos9:^(bool isAuthorized) {
if (isAuthorized) {
[weakSelf getAllAddress];
}
}];
}
}
- (void)getAllAddress {
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];
if (([[[UIDevice currentDevice] systemVersion] compare:@"9.0" options:NSNumericSearch] == NSOrderedAscending)
) {
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
// 2.如果是已经授权,才能获取联系人
if (status != kABAuthorizationStatusAuthorized) {
[GMHudModule toast:@"获取通讯录失败,请在设置中打开通讯录权限。"];
return ;
}
// 3.创建通信录对象
ABAddressBookRef addressBook = ABAddressBookCreate();
// 4.获取所有的联系人
CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex peopleCount = CFArrayGetCount(peopleArray);
// 5.遍历所有的联系人
for (int i = 0; i < peopleCount; i++) {
// 5.1.获取某一个联系人
ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);
// 5.2.获取联系人的姓名
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty) ?:@"";
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty) ?:@"";
NSString *fullName = [NSString stringWithFormat:@"%@%@", lastName, firstName];
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, 0) ?:@"";
[array addObject:@{@"name":fullName,@"phone":phoneValue}];
CFRelease(phones);
}
CFRelease(addressBook);
CFRelease(peopleArray);
[self sendData:[NSString convertToPrettyPrintedJsonString:array]];
} else {
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status != CNAuthorizationStatusAuthorized) {
[GMHudModule toast:@"获取通讯录失败,请在设置中打开通讯录权限。"];
return ;
}
CNContactStore *contactStore = [[CNContactStore alloc] init];
NSArray *keys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
[contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
NSString *lastName = contact.familyName ?:@"";
NSString *firstName = contact.givenName ?:@"";
NSString *fullName = [NSString stringWithFormat:@"%@%@",lastName , firstName];
CNLabeledValue *phones = contact.phoneNumbers.firstObject;
NSString *phoneValue = @"";
if (phones != nil) {
CNPhoneNumber *phoneNumer = phones.value;
phoneValue = phoneNumer.stringValue ?:@"";
}
[array addObject:@{@"name":fullName,@"phone":phoneValue}];
}];
[self sendData:[NSString convertToPrettyPrintedJsonString:array]];
}
}
- (void)sendData:(NSString *)addressStr {
// 仅仅发送,不给用户任何反馈
[GMNetworking requestOCWithApi:@"/api/addressbook/upload" method:GMHTTPMethodPost parameters:@{@"address":addressStr} completion:nil];
}
- (void)chooseContactPersonAddressBookJsonString {
if ([[[UIDevice currentDevice] systemVersion] compare:@"9.0" options:NSNumericSearch] == NSOrderedAscending) {
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status != kABAuthorizationStatusAuthorized) {
[GMHudModule toast:@"获取通讯录失败,请在设置中打开通讯录权限。"];
return ;
}
ABPeoplePickerNavigationController *nav = [[ABPeoplePickerNavigationController alloc] init];
nav.peoplePickerDelegate = self;
nav.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];
[[GMBaseTool getNavigation] pushViewController:nav animated:YES];
} else {
[self checkAddressBookIos9:^(bool isAuthorized) {
if (!isAuthorized) {
[GMHudModule toast:@"获取通讯录失败,请在设置中打开通讯录权限。"];
return ;
}
}];
CNContactPickerViewController *nav = [[CNContactPickerViewController alloc] init];
nav.delegate = self;
[[GMBaseTool getNavigation] pushViewController:nav animated:YES];
}
}
#pragma -mark ABPeoplePickerNavigationControllerDelegate method
/**
获取一个用户选择的通讯录联系人成功的回调
@author zhaiguojun 16-09-28 in 6.4.1
@param peoplePicker peoplePicker description
@param person person description
@param property property description
@param identifier identifier description
*/
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
NSString *fullName = CFBridgingRelease(ABRecordCopyCompositeName(person)) ?:@"";
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSString *phoneNum = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, 0)) ?:@"";
phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"-" withString:@""];
//释放CF对象.如果没有纪录电话,phone是nil,不能释放。
if (phones != nil) {
CFRelease(phones);
}
if (self.getOneContactPersonBlock) {
self.getOneContactPersonBlock(@{@"name":fullName, @"phone":phoneNum});
}
}
/**
取消获取电话
@author zhaiguojun 16-09-28 in 6.4.0
@param peoplePicker
@since 6.4.1
*/
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
[peoplePicker dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - CNContactPickerDelegate method
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact {
// 1.获取联系人的姓名
NSString *firstname = contact.givenName;
// 2.获取联系人的电话号码
NSArray *phoneNums = contact.phoneNumbers;
CNLabeledValue *labeledValue = phoneNums.firstObject;
// 2.2.获取电话号码
CNPhoneNumber *phoneNumer = labeledValue.value;
NSString *phoneValue = phoneNumer.stringValue;
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"-" withString:@""];
if (self.getOneContactPersonBlock) {
self.getOneContactPersonBlock(@{@"name":SafeValue(firstname), @"phone": SafeValue(phoneValue)});
}
}
- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker{
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (void)checkAddressBookAuthorization:(void (^)(bool isAuthorized))block {
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
if (authStatus != kABAuthorizationStatusAuthorized) {
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"Error: %@", (__bridge NSError *)error);
} else if (!granted) {
block(NO);
} else {
block(YES);
}
});
});
} else {
block(YES);
}
CFRelease(addressBook);
}
- (void)checkAddressBookIos9:(void (^)(bool isAuthorized))block {
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusNotDetermined) {
[[[CNContactStore alloc]init] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (error) {
NSLog(@"Error:something run error!");
} else if (!granted) {
block(NO);
} else {
block(YES);
}
}];
}else if (status == CNAuthorizationStatusAuthorized){
block(YES);
}else {
block(NO);
}
}
@end
//
// GMBaseTool.h
// GMBase
//
// Created by 卢悦明 on 2020/5/13.
//
#import <Foundation/Foundation.h>
#import <GMbase/GMNavigationController.h>
NS_ASSUME_NONNULL_BEGIN
@interface GMBaseTool : NSObject
/// 获取当前控制器
+ (UIViewController *)getCurrentViewController;
/// 获取window
+ (UIWindow *)mainWindow;
/// 获取导航控制器
+ (GMNavigationController *)getNavigation;
+ (void)userIsAllowPush:(void (^)(BOOL))isOpenPushBlock;
@end
NS_ASSUME_NONNULL_END
//
// GMBaseTool.m
// GMBase
//
// Created by 卢悦明 on 2020/5/13.
//
#import "GMBaseTool.h"
#import <UserNotifications/UserNotifications.h>
@implementation GMBaseTool
+ (UIViewController *)getRootViewController{
UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
return window.rootViewController;
}
+ (UIViewController *)getCurrentViewController{
UIViewController* currentViewController = [self getRootViewController];
BOOL runLoopFind = YES;
while (runLoopFind) {
if (currentViewController.presentedViewController) {
currentViewController = currentViewController.presentedViewController;
} else if ([currentViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController* )currentViewController;
currentViewController = [navigationController.childViewControllers lastObject];
} else if ([currentViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController* )currentViewController;
currentViewController = tabBarController.selectedViewController;
} else {
NSUInteger childViewControllerCount = currentViewController.childViewControllers.count;
if (childViewControllerCount > 0) {
currentViewController = currentViewController.childViewControllers.lastObject;
return currentViewController;
} else {
return currentViewController;
}
}
}
return currentViewController;
}
//获取当前window
+ (UIWindow *)mainWindow
{
UIApplication *app = [UIApplication sharedApplication];
if ([app.delegate respondsToSelector:@selector(window)]) {
return [app.delegate window];
} else {
return [app keyWindow];
}
}
+ (GMNavigationController *)getNavigation {
UIViewController* rootVC = [self getRootViewController];
if ([rootVC isKindOfClass:[GMNavigationController class]]) {
return (GMNavigationController *)rootVC;
} else {
return nil;
}
}
#pragma mark - 判断用户是否允许推送
+ (void)userIsAllowPush:(void (^)(BOOL))isOpenPushBlock {
if (@available(iOS 10.0, *)) {
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
dispatch_async(dispatch_get_main_queue(), ^{
if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined){
//未选择---没有选择允许或者不允许,按不允许处理
isOpenPushBlock(NO);
} else if (settings.authorizationStatus == UNAuthorizationStatusDenied){
//未授权--不允许推送
isOpenPushBlock(NO);
} else if (settings.authorizationStatus == UNAuthorizationStatusAuthorized){
//已授权--允许推送
isOpenPushBlock(YES);
}
});
}];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings];
BOOL isAllow = (settings.types != UIUserNotificationTypeNone);
isOpenPushBlock(isAllow);
});
}
}
@end
//
// GMCalendarEventManager.swift
// Gengmei
//
// Created by 汪俊 on 16/7/4.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
import UIKit
//import GMBaseSwift
import EventKit
public typealias CalendarAuthorizationAllowedBlock = () -> Void
@objcMembers
public class GMCalendarEventManager: NSObject {
public var authorizationAllowed: CalendarAuthorizationAllowedBlock?
public var eventStore = EKEventStore()
public override init() {
super.init()
//请求授权
let status = EKEventStore.authorizationStatus(for: .event)
if status == .notDetermined {
eventStore.requestAccess(to: .event, completion: { (allowed, _) in
if allowed {
print("allowed")
if self.authorizationAllowed != nil {
self.authorizationAllowed!()
}
} else {
print("not allowed")
}
})
} else if status == .restricted || status == .denied {
showAlertcontrolle()
}
}
/**
添加日历事件
- author: wangjun 07-07-2016 in 6.1.0
- parameter title: 事件的标题
- parameter startDate: 开始时间
- parameter endDate: 结束时间`
- parameter triggerTime: 提醒事件
- parameter url: 跳转到美购详情页面的地址
*/
public func addEvent(_ title: String = "", startDate: TimeInterval, endDate: TimeInterval, serviceId: String, url: String) {
let timeZone = TimeZone.current
let deltaTime = timeZone.secondsFromGMT()
let event = EKEvent(eventStore: eventStore)
let gengmeiTitle = "更美App秒杀: " + title
event.title = gengmeiTitle
event.startDate = Date(timeIntervalSince1970: startDate - TimeInterval(deltaTime))
event.endDate = Date(timeIntervalSince1970: endDate - TimeInterval(deltaTime))
event.calendar = eventStore.defaultCalendarForNewEvents
event.notes = url
//计算出秒杀提醒时间,开始前3分钟
var triggerTime = Date(timeIntervalSince1970: startDate)
triggerTime = triggerTime.addingTimeInterval(-180 - TimeInterval(deltaTime))
let alarm = EKAlarm(absoluteDate: triggerTime)
event.addAlarm(alarm)
do {
try eventStore.save(event, span: .thisEvent)
//将event的id 保存到本地
UserDefaults.standard.set(event.eventIdentifier, forKey: serviceId)
UserDefaults.standard.synchronize()
} catch {
print("error show")
}
}
/**
通过标题删除日历事件
- author: wangjun 07-07-2016 in 6.1.0
- parameter title: 事件的标题
*/
public func removeEvent(_ serviceId: String) {
//取出对应的event eventId
guard let eventId = (UserDefaults.standard.object(forKey: serviceId)) as? String else {
return
}
let event = eventStore.event(withIdentifier: eventId)
do {
if event != nil {
try eventStore.remove(event!, span: .thisEvent)
}
} catch {
print("error")
}
}
/**
判断用户是够开启日历服务
- author: wangjun
- date: 16-07-04 18:07:22 07-04-2016 in 6.1.0
*/
public func checkAuthorized() -> Bool {
return EKEventStore.authorizationStatus(for: .event) == .authorized
}
/**
提醒用户开启日历服务的alert
- author: wangjun 07-07-2016 in 6.1.0
*/
public func showAlertcontrolle() {
let status = EKEventStore.authorizationStatus(for: .event)
if status == .authorized {
return
} else {
let alert = UIAlertController(title: "", message: "未授权日历权限,可能导致无法成功提醒哟,快去开启设置吧", preferredStyle: .alert)
let actionA = UIAlertAction(title: "取消", style: .cancel) { (_) in}
alert.addAction(actionA)
let actionB = UIAlertAction(title: "去设置", style: .default) { (_) in
if #available(iOS 10.0, *) {
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(URL(string: UIApplication.openSettingsURLString)!)
}
}
alert.addAction(actionB)
GMBaseTool.getCurrentViewController().present(alert, animated: true, completion: nil)
}
}
}
//
// GMFloatWindow.h
// Gengmei
//
// Created by licong on 2018/1/25.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface GMFloatWindow : UIView <UIGestureRecognizerDelegate>
//标记当前直播/回放页面是否是浮窗状态还是全屏状态, true -> 全屏, false -> 浮窗
@property (nonatomic, assign) BOOL isExpanded;
@property (nonatomic, assign) BOOL isShowingAnimation;
@property (nonatomic, strong) UITapGestureRecognizer *tapGesture;
- (void)showController:(UIViewController *)controller;
- (void)hide;
- (void)hideWithNoAnimation;
- (void)zoomToSmall;
- (void)videoZoomToSmall;
- (void)expandAction:(UITapGestureRecognizer *)tapGesture;
@end
//
// GMFloatWindow.m
// Gengmei
//
// Created by licong on 2018/1/25.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMFloatWindow.h"
//#import "GMLoginManager.h"
//#import "UITabBar+ViewConstant.h"
#import "GMFloatWindowProtocol.h"
#import "GMBaseTool.h"
@import GMKit;
@interface GMFloatWindow()<CAAnimationDelegate> {
UIViewController *_controller;
}
@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;
@end
@implementation GMFloatWindow
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:[UIScreen mainScreen].bounds];
if (self) {
self.clipsToBounds = YES;
self.backgroundColor = [UIColor clearColor];
_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(expandAction:)];
_tapGesture.delegate = self;
_panGesture =[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panAction:)];
_panGesture.minimumNumberOfTouches = 1;
_panGesture.maximumNumberOfTouches = 1;
_panGesture.delegate = self;
self.isExpanded = YES;
}
return self;
}
- (void)showController:(UIViewController *)controller {
if (self.superview == nil) {
[[UIApplication sharedApplication].keyWindow addSubview:self];
// [[AppDelegate shareInstance].window addSubview:self];
}
_controller = controller;
[self addSubview:controller.view];
self.isShowingAnimation = YES;
if (_isExpanded) {
//当前没有小浮窗
//transform 要设置在前面因为它会印象frame
self.transform = CGAffineTransformMakeScale(1, 1);
self.frame = CGRectMake(0, MAINSCREEN_HEIGHT, MAINSCREEN_WIDTH, MAINSCREEN_HEIGHT);
self.layer.cornerRadius = 0;
self.hidden = NO;
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.top = 0;
} completion:^(BOOL finished) {
self.isShowingAnimation = NO;
}];
}else {
//当前已经有小浮窗,需要关闭当前小浮窗,在打开新的浮窗,具体实现其实是换了window的rootCtroller
//先移除手势
[self addGestureRecognizer:self.tapGesture];
[self addGestureRecognizer:self.panGesture];
//去掉圆角
self.layer.cornerRadius = 0;
//window大小还原,将window刚好放在屏幕下面
self.transform = CGAffineTransformMakeScale(1, 1);
self.frame = CGRectMake(0, MAINSCREEN_HEIGHT, MAINSCREEN_WIDTH, MAINSCREEN_HEIGHT);
[UIView animateWithDuration:0.25 delay:0.1 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.top = 0;
} completion:^(BOOL finished) {
self.isShowingAnimation = NO;
}];
}
}
- (void)hideWithNoAnimation{
self.hidden = YES;
//恢复成默认值
self.isExpanded = YES;
}
- (void)hide {
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.top = MAINSCREEN_HEIGHT;
} completion:^(BOOL finished) {
[self hideWithNoAnimation];
_controller = nil;
}];
}
- (void)expandAction:(UITapGestureRecognizer *)tapGesture{
[[GMBaseTool getCurrentViewController].view endEditing:YES];
self.layer.cornerRadius = 0;
self.hidden = NO;
[UIView animateWithDuration:0.25f animations:^{
self.transform = CGAffineTransformMakeScale(1, 1);
self.frame = CGRectMake(0, 0, MAINSCREEN_WIDTH, MAINSCREEN_HEIGHT);
} completion:^(BOOL finished) {
[self removeGestureRecognizer:self.tapGesture];
[self removeGestureRecognizer:self.panGesture];
}];
[(id<GMFloatWindowProtocol>)_controller showOtherViews];
_isExpanded = YES;
}
-(void)panAction:(UIPanGestureRecognizer *)recognizer {
UIWindow *window = [UIApplication sharedApplication].keyWindow;
CGPoint translatedPoint = [recognizer translationInView:window];
switch (recognizer.state) {
case UIGestureRecognizerStateBegan:
{
break;
}
case UIGestureRecognizerStateChanged:
{
CGFloat x = recognizer.view.center.x + translatedPoint.x;
CGFloat y = recognizer.view.center.y + translatedPoint.y;
if (x < recognizer.view.width / 2.0) {
x = recognizer.view.width / 2.0;
} else if (x + recognizer.view.width / 2.0 > MAINSCREEN_WIDTH) {
x = MAINSCREEN_WIDTH - recognizer.view.width / 2.0;
}
if (y < recognizer.view.height / 2.0) {
y = recognizer.view.height / 2.0;
} else if (y + recognizer.view.height / 2.0> MAINSCREEN_HEIGHT) {
y = MAINSCREEN_HEIGHT - recognizer.view.height / 2.0;
}
recognizer.view.center = CGPointMake(x, y);
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[recognizer setTranslation:CGPointMake(0, 0) inView:window];
break;
}
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded:
default:
break;
}
}
- (void)zoomToSmall {
if (_controller == nil) {
return;
}
[(id<GMFloatWindowProtocol>)_controller hideOtherViews];
self.layer.cornerRadius = 18;
_isExpanded = NO;
[UIView animateWithDuration:0.25f animations:^{
self.transform = CGAffineTransformMakeScale(0.35, 0.35);
self.frame = CGRectMake(MAINSCREEN_WIDTH * 0.65, 85, MAINSCREEN_WIDTH * 0.35, MAINSCREEN_HEIGHT * 0.35);
} completion:^(BOOL finished) {
[self addGestureRecognizer:self.tapGesture];
[self addGestureRecognizer:self.panGesture];
}];
}
// 视频缩小,宽是屏幕1/4,宽高比3:5
- (void)videoZoomToSmall {
if (_controller == nil) {
return;
}
[(id<GMFloatWindowProtocol>)_controller hideOtherViews];
self.layer.cornerRadius = 28;
_isExpanded = NO;
[UIView animateWithDuration:0.25f animations:^{
self.transform = CGAffineTransformMakeScale(0.35, 0.35);
self.frame = CGRectMake(MAINSCREEN_WIDTH * 0.75, MAINSCREEN_HEIGHT * 0.16, MAINSCREEN_WIDTH * 0.25, MAINSCREEN_WIDTH * 0.417);
} completion:^(BOOL finished) {
[self addGestureRecognizer:self.tapGesture];
[self addGestureRecognizer:self.panGesture];
}];
}
#pragma mark- Gesture Delagate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
@end
//
// GMFloatWindowProtocol.h
// Gengmei
//
// Created by wangyang on 2018/5/2.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol GMFloatWindowProtocol <NSObject>
/**
GMFloatWindow 由全屏模式到小窗口模式,会调用此方法
*/
- (void)hideOtherViews;
/**
GMFloatWindow 由小窗口模式到全屏模式,会调用此方法
*/
- (void)showOtherViews;
@end
//
// GMLiveLikeView.h
// Gengmei
//
// Created by licong on 2017/1/6.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
//直播点赞按钮
typedef void(^LiveLikeClickedBlock)(void);
@interface GMLiveLikeView : UIView
@property (nonatomic, copy) LiveLikeClickedBlock liveLikeClickedBlock;
@end
//
// GMLiveLikeView.m
// Gengmei
//
// Created by licong on 2017/1/6.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMLiveLikeView.h"
#import "GMButton.h"
@import GMKit;
@interface GMLiveLikeView ()
@property (strong ,nonatomic) GMButton *button;
@end
@implementation GMLiveLikeView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)setup{
_button = [GMButton buttonWithType:UIButtonTypeCustom];
_button.frame = self.bounds;
_button.enableAdaptive = YES;
_button.adjustsImageWhenHighlighted = NO;
[_button setImage:[UIImage imageNamed:@"live_heart_nor"] forState:UIControlStateNormal];
[_button addTarget:self action:@selector(likeButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_button];
}
- (void)layoutSubviews{
[super layoutSubviews];
_button.frame = self.bounds;
}
- (void)likeButtonClicked{
UIView * gradientView = [[UIView alloc]
initWithFrame:self.bounds];
gradientView.frame = self.bounds;
gradientView.layer.cornerRadius = self.frame.size.height/2;
gradientView.userInteractionEnabled = NO;
gradientView.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
gradientView.layer.cornerRadius = self.frame.size.height/2;
gradientView.backgroundColor = RGBCOLOR_HEX(0xFF7690);
gradientView.hidden = YES;
[self addSubview:gradientView];
gradientView.alpha = 1;
gradientView.hidden = NO;
gradientView.transform = CGAffineTransformMakeScale(1, 1);
[_button setImage:[UIImage imageNamed:@"live_heart_pre"] forState:UIControlStateNormal];
[UIView animateWithDuration:0.3
animations:^{
gradientView.alpha = 0.3;
gradientView.transform = CGAffineTransformMakeScale(2, 2);
}completion:^(BOOL finish){
[gradientView removeFromSuperview];
[_button setImage:[UIImage imageNamed:@"live_heart_nor"] forState:UIControlStateNormal];
}];
if (self.liveLikeClickedBlock) {
self.liveLikeClickedBlock();
}
}
@end
//
// WMLocationManager.h
// Gengmei
//
// Created by wangyang on 5/6/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#define kLastLocation @"lastLocation"
typedef void(^LocationFinishBlock)(CLLocation *location);
/**
保证新用户在有网络的情况下弹出 授权框 不然调不起地理位置弹框
*/
//typedef void(^RequestLocationAuthorization)();
@interface GMLocationManager : NSObject <CLLocationManagerDelegate>
@property (nonatomic, readonly) CLLocation *location;
@property (nonatomic, assign, readonly) NSInteger statusWhenAppBackground;
+ (instancetype)shareInstance;
/**
* @author wangyang, 16-03-11 17:03:21
*
* @brief 定位成功的回调
* @since 5.9.2
*/
- (void)addBlock:(LocationFinishBlock)block;
/**
* @author wangyang, 16-03-11 17:03:31
*
* @brief 在dealloc时需要手动移除先前添加的block
* @since 5.9.2
*/
- (void)removeLast;
/**
* @author wangyang, 16-02-24 15:02:11
*
* @brief 尝试使用定位功能。如果没有权限会有提示,如果有权限直接重新定位
* @since 5.9.1
*/
- (void)tryLocationService;
//@property (nonatomic, copy) RequestLocationAuthorization *authorizationBlock;
/**
保证有网络的l时候调用 不然那会失败
*/
-(void)notDeterminedShowLocationAuthorize;
/**
尝试使用定位功能。如果没有权限会有提示,并只提示一次
@param key 如果key不为nil,那么该key下的无权限提示只会展示一次,直到app删除。
如果key为nil,相当于调用tryLocationService
*/
- (void)tryLocationServiceForKey:(NSString *)key;
/**
* @author wangyang, 16-03-10 14:03:57
*
* @brief 静默的尝试重新定位,而不会有任何提示
* @since 5.9.2
*/
- (void)updateLocation;
/**
* @author wangyang, 16-03-10 12:03:57
*
* @brief 会判断是否允许定位服务
* @return YES表示允许
* @since 5.9.2
*/
+ (BOOL)hasOpenLocationService;
/**
* @author wangyang, 16-03-10 18:03:03
*
* @brief 跳转到定位服务的系统设置页
* @since 5.9.2
*/
+ (void)jumpToSettings;
/**
* @author wangyang, 16-03-10 12:03:21
*
* @brief 会判断是否允许定位服务,如果不允许会弹出alert
* @since 5.9.2
*/
+ (void)showAlertIfNotAllowed;
@end
This diff is collapsed.
//
// GMRountClassManager.h
// GMBase
//
// Created by 卢悦明 on 2020/5/12.
//
#import <Foundation/Foundation.h>
@interface GMRountClassManager : NSObject
/// 通过key找到对应的方法,回调想要的值
/// @param key
- (id)getMassge:(NSString *)key;
/// 调用方法
- (void)sendCladdMethod:(NSString *)key;
@end
//
// GMRountClassManager.m
// GMBase
//
// Created by 卢悦明 on 2020/5/12.
//
#import "GMRountClassManager.h"
@implementation GMRountClassManager
@end
//
// GMWelfareServiceObject.h
// GMBase
//
// Created by 卢悦明 on 2020/5/12.
//
#import <GMBase/GMObject.h>
#import "GMWelfareVideObject.h"
typedef NS_ENUM(NSUInteger, GMWelfareDetailServiceType) {
GMWelfareDetailServiceTypeDefault = 1,// 其他(后端也不知道1, 2啥意思, 旗舰店之前客户端没用到)
GMWelfareDetailServiceTypeFlagShip = 3,// 旗舰店(新加类型)
};
NS_ASSUME_NONNULL_BEGIN
@protocol GMWelfareServiceObject @end
@interface GMWelfareServiceObject : GMObject
@property (nonatomic, strong) NSString *serviceId;
@property (nonatomic, strong) NSString *serviceName;
@property (nonatomic, strong) NSString *shortDescription;
@property (nonatomic, strong) NSString *doctorName;
@property (nonatomic, assign) BOOL doctorRecommend;
@property (nonatomic, strong) NSString *pic;
@property (nonatomic, strong) NSString *picSmall;
/** 划线价(7745开始,未选中sku时,会传一个价格区间), 不需要展示的,original_price会传空字符串 */
@property (nonatomic, strong) NSString *originalPrice;
@property (nonatomic, strong) NSString *gengmeiPrice;
@property (nonatomic, strong) NSString *picNum;
@property (nonatomic, assign) NSInteger sellAmount;
@property (nonatomic, strong) NSString *city;
@property (nonatomic, strong) NSString *url;
@property (nonatomic, strong) NSString *specialInfo;
@property (nonatomic, strong) NSString *specialId;
@property (nonatomic, strong) NSString *specialInfoUrl;
@property (nonatomic, assign) NSInteger saleLimit;
@property (nonatomic, strong) NSNumber *commentRate;
@property (nonatomic, strong) NSArray <GMWelfareVideObject> *headerPic;
@property (nonatomic, strong) NSString *distance;
/** 添加提问按钮 的列表问题 从AI过来的时候, 会有这个字段 by add 7.22.0*/
@property (nonatomic, copy) NSString *projectTag;
/** 美购类型, 先判断旗舰店, 否则就是其他 */
@property (nonatomic, assign) GMWelfareDetailServiceType serviceType;
@property (nonatomic, copy) NSString *image;
@end
NS_ASSUME_NONNULL_END
//
// GMWelfareServiceObject.m
// GMBase
//
// Created by 卢悦明 on 2020/5/12.
//
#import "GMWelfareServiceObject.h"
@implementation GMWelfareServiceObject
@end
//
// GMWelfareVideObject.h
// GMBase
//
// Created by 卢悦明 on 2020/5/12.
//
#import <GMBase/GMObject.h>
NS_ASSUME_NONNULL_BEGIN
@protocol GMWelfareVideObject @end
@interface GMWelfareVideObject : GMObject
@property (nonatomic, strong) NSString *pic;
@property (nonatomic, strong) NSString *videoUrl;
@end
NS_ASSUME_NONNULL_END
//
// GMWelfareVideObject.m
// GMBase
//
// Created by 卢悦明 on 2020/5/12.
//
#import "GMWelfareVideObject.h"
@implementation GMWelfareVideObject
@end
//
// GMZoneTagsObject.h
// Gengmei
//
// Created by 卢悦明 on 2020/5/12.
// Copyright © 2020 更美互动信息科技有限公司. All rights reserved.
//
#import <GMBase/GMObject.h>
NS_ASSUME_NONNULL_BEGIN
@protocol GMZoneTagsObject @end
@interface GMZoneTagsObject : GMObject
@property (nonatomic, assign) NSInteger id;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *tagType;
/** 是否是新标签 */
@property (nonatomic, assign) BOOL isNew;
@end
NS_ASSUME_NONNULL_END
//
// GMZoneTagsObject.m
// Gengmei
//
// Created by 卢悦明 on 2020/5/12.
// Copyright © 2020 更美互动信息科技有限公司. All rights reserved.
//
#import "GMZoneTagsObject.h"
@implementation GMZoneTagsObject
@end
//
// JZLocationConverter.h
// Gengmei
//
// Created by wangyang on 2017/8/15.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
@interface JZLocationConverter : NSObject
/**
* @brief 世界标准地理坐标(WGS-84) 转换成 中国国测局地理坐标(GCJ-02)<火星坐标>
*
* ####只在中国大陆的范围的坐标有效,以外直接返回世界标准坐标
*
* @param location 世界标准地理坐标(WGS-84)
*
* @return 中国国测局地理坐标(GCJ-02)<火星坐标>
*/
+ (CLLocationCoordinate2D)wgs84ToGcj02:(CLLocationCoordinate2D)location;
/**
* @brief 中国国测局地理坐标(GCJ-02) 转换成 世界标准地理坐标(WGS-84)
*
* ####此接口有1-2米左右的误差,需要精确定位情景慎用
*
* @param location 中国国测局地理坐标(GCJ-02)
*
* @return 世界标准地理坐标(WGS-84)
*/
+ (CLLocationCoordinate2D)gcj02ToWgs84:(CLLocationCoordinate2D)location;
/**
* @brief 世界标准地理坐标(WGS-84) 转换成 百度地理坐标(BD-09)
*
* @param location 世界标准地理坐标(WGS-84)
*
* @return 百度地理坐标(BD-09)
*/
+ (CLLocationCoordinate2D)wgs84ToBd09:(CLLocationCoordinate2D)location;
/**
* @brief 中国国测局地理坐标(GCJ-02)<火星坐标> 转换成 百度地理坐标(BD-09)
*
* @param location 中国国测局地理坐标(GCJ-02)<火星坐标>
*
* @return 百度地理坐标(BD-09)
*/
+ (CLLocationCoordinate2D)gcj02ToBd09:(CLLocationCoordinate2D)location;
/**
* @brief 百度地理坐标(BD-09) 转换成 中国国测局地理坐标(GCJ-02)<火星坐标>
*
* @param location 百度地理坐标(BD-09)
*
* @return 中国国测局地理坐标(GCJ-02)<火星坐标>
*/
+ (CLLocationCoordinate2D)bd09ToGcj02:(CLLocationCoordinate2D)location;
/**
* @brief 百度地理坐标(BD-09) 转换成 世界标准地理坐标(WGS-84)
*
* ####此接口有1-2米左右的误差,需要精确定位情景慎用
*
* @param location 百度地理坐标(BD-09)
*
* @return 世界标准地理坐标(WGS-84)
*/
+ (CLLocationCoordinate2D)bd09ToWgs84:(CLLocationCoordinate2D)location;
@end
//
// JZLocationConverter.m
// Gengmei
//
// Created by wangyang on 2017/8/15.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "JZLocationConverter.h"
@implementation JZLocationConverter
#define LAT_OFFSET_0(x,y) -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x))
#define LAT_OFFSET_1 (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0
#define LAT_OFFSET_2 (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0
#define LAT_OFFSET_3 (160.0 * sin(y / 12.0 * M_PI) + 320 * sin(y * M_PI / 30.0)) * 2.0 / 3.0
#define LON_OFFSET_0(x,y) 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x))
#define LON_OFFSET_1 (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0
#define LON_OFFSET_2 (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0
#define LON_OFFSET_3 (150.0 * sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0 * M_PI)) * 2.0 / 3.0
#define X_PI ((M_PI * 3000.0) / 180.0)
#define RANGE_LON_MAX 137.8347
#define RANGE_LON_MIN 72.004
#define RANGE_LAT_MAX 55.8271
#define RANGE_LAT_MIN 0.8293
// jzA = 6378245.0, 1/f = 298.3
// b = a * (1 - f)
// ee = (a^2 - b^2) / a^2;
#define jzA 6378245.0
#define jzEE 0.00669342162296594323
+ (double)transformLat:(double)x bdLon:(double)y
{
double ret = LAT_OFFSET_0(x, y);
ret += LAT_OFFSET_1;
ret += LAT_OFFSET_2;
ret += LAT_OFFSET_3;
return ret;
}
+ (double)transformLon:(double)x bdLon:(double)y
{
double ret = LON_OFFSET_0(x, y);
ret += LON_OFFSET_1;
ret += LON_OFFSET_2;
ret += LON_OFFSET_3;
return ret;
}
+ (BOOL)outOfChina:(double)lat bdLon:(double)lon
{
if (lon < RANGE_LON_MIN || lon > RANGE_LON_MAX)
return true;
if (lat < RANGE_LAT_MIN || lat > RANGE_LAT_MAX)
return true;
return false;
}
+ (CLLocationCoordinate2D)gcj02Encrypt:(double)ggLat bdLon:(double)ggLon
{
CLLocationCoordinate2D resPoint;
double mgLat;
double mgLon;
if ([self outOfChina:ggLat bdLon:ggLon]) {
resPoint.latitude = ggLat;
resPoint.longitude = ggLon;
return resPoint;
}
double dLat = [self transformLat:(ggLon - 105.0)bdLon:(ggLat - 35.0)];
double dLon = [self transformLon:(ggLon - 105.0) bdLon:(ggLat - 35.0)];
double radLat = ggLat / 180.0 * M_PI;
double magic = sin(radLat);
magic = 1 - jzEE * magic * magic;
double sqrtMagic = sqrt(magic);
dLat = (dLat * 180.0) / ((jzA * (1 - jzEE)) / (magic * sqrtMagic) * M_PI);
dLon = (dLon * 180.0) / (jzA / sqrtMagic * cos(radLat) * M_PI);
mgLat = ggLat + dLat;
mgLon = ggLon + dLon;
resPoint.latitude = mgLat;
resPoint.longitude = mgLon;
return resPoint;
}
+ (CLLocationCoordinate2D)gcj02Decrypt:(double)gjLat gjLon:(double)gjLon {
CLLocationCoordinate2D gPt = [self gcj02Encrypt:gjLat bdLon:gjLon];
double dLon = gPt.longitude - gjLon;
double dLat = gPt.latitude - gjLat;
CLLocationCoordinate2D pt;
pt.latitude = gjLat - dLat;
pt.longitude = gjLon - dLon;
return pt;
}
+ (CLLocationCoordinate2D)bd09Decrypt:(double)bdLat bdLon:(double)bdLon
{
CLLocationCoordinate2D gcjPt;
double x = bdLon - 0.0065, y = bdLat - 0.006;
double z = sqrt(x * x + y * y) - 0.00002 * sin(y * X_PI);
double theta = atan2(y, x) - 0.000003 * cos(x * X_PI);
gcjPt.longitude = z * cos(theta);
gcjPt.latitude = z * sin(theta);
return gcjPt;
}
+(CLLocationCoordinate2D)bd09Encrypt:(double)ggLat bdLon:(double)ggLon
{
CLLocationCoordinate2D bdPt;
double x = ggLon, y = ggLat;
double z = sqrt(x * x + y * y) + 0.00002 * sin(y * X_PI);
double theta = atan2(y, x) + 0.000003 * cos(x * X_PI);
bdPt.longitude = z * cos(theta) + 0.0065;
bdPt.latitude = z * sin(theta) + 0.006;
return bdPt;
}
+ (CLLocationCoordinate2D)wgs84ToGcj02:(CLLocationCoordinate2D)location
{
return [self gcj02Encrypt:location.latitude bdLon:location.longitude];
}
+ (CLLocationCoordinate2D)gcj02ToWgs84:(CLLocationCoordinate2D)location
{
return [self gcj02Decrypt:location.latitude gjLon:location.longitude];
}
+ (CLLocationCoordinate2D)wgs84ToBd09:(CLLocationCoordinate2D)location
{
CLLocationCoordinate2D gcj02Pt = [self gcj02Encrypt:location.latitude
bdLon:location.longitude];
return [self bd09Encrypt:gcj02Pt.latitude bdLon:gcj02Pt.longitude] ;
}
+ (CLLocationCoordinate2D)gcj02ToBd09:(CLLocationCoordinate2D)location
{
return [self bd09Encrypt:location.latitude bdLon:location.longitude];
}
+ (CLLocationCoordinate2D)bd09ToGcj02:(CLLocationCoordinate2D)location
{
return [self bd09Decrypt:location.latitude bdLon:location.longitude];
}
+ (CLLocationCoordinate2D)bd09ToWgs84:(CLLocationCoordinate2D)location
{
CLLocationCoordinate2D gcj02 = [self bd09ToGcj02:location];
return [self gcj02Decrypt:gcj02.latitude gjLon:gcj02.longitude];
}
@end
//
// NSString+CalculateSize.h
// Gengmei
//
// Created by Q14 on 2019/8/27.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (CalculateSize)
/**
* 计算文字高度,可以处理计算带行间距的
*/
- (CGSize)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing;
/**
* 计算最大行数文字高度,可以处理计算带行间距的
*/
- (CGFloat)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing maxLines:(NSInteger)maxLines;
/**
* 计算是否超过一行 用于给Label 赋值attribute text的时候 超过一行设置lineSpace
*/
- (BOOL)isMoreThanOneLineWithSize:(CGSize)size font:(UIFont *)font lineSpaceing:(CGFloat)lineSpacing;
@end
NS_ASSUME_NONNULL_END
//
// NSString+CalculateSize.m
// Gengmei
//
// Created by Q14 on 2019/8/27.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "NSString+CalculateSize.h"
@implementation NSString (CalculateSize)
/**
* 计算文字高度,可以处理计算带行间距的
*/
- (CGSize)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing {
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:self];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = lineSpacing;
[attributeString addAttribute:NSParagraphStyleAttributeName
value:paragraphStyle
range:NSMakeRange(0, self.length)];
[attributeString addAttribute:NSFontAttributeName
value:font
range:NSMakeRange(0, self.length)];
NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading;
CGRect rect = [attributeString boundingRectWithSize:size
options:options
context:nil];
//文本的高度减去字体高度小于等于行间距,判断为当前只有1行
if ((rect.size.height - font.lineHeight) <= paragraphStyle.lineSpacing) {
if ([self containChinese:self]) { //如果包含中文
rect = CGRectMake(rect.origin.x,
rect.origin.y,
rect.size.width,
rect.size.height-paragraphStyle.lineSpacing);
}
}
return rect.size;
}
//判断如果包含中文
- (BOOL)containChinese:(NSString *)str {
for(int i = 0; i < [str length]; i++) {
int a = [str characterAtIndex:i];
if(a > 0x4e00 && a < 0x9fff) {
return YES;
}
}
return NO;
}
/**
* 计算最大行数文字高度,可以处理计算带行间距的
*/
- (CGFloat)boundingRectWithSize:(CGSize)size font:(UIFont*)font lineSpacing:(CGFloat)lineSpacing maxLines:(NSInteger)maxLines {
if (maxLines <= 0) {
return 0;
}
CGFloat maxHeight = font.lineHeight * maxLines + lineSpacing * (maxLines - 1);
CGSize orginalSize = [self boundingRectWithSize:size
font:font
lineSpacing:lineSpacing];
if (orginalSize.height >= maxHeight) {
return maxHeight;
} else {
return orginalSize.height;
}
}
/**
* 计算是否超过一行 用于给Label 赋值attribute text的时候 超过一行设置lineSpace
*/
- (BOOL)isMoreThanOneLineWithSize:(CGSize)size font:(UIFont *)font lineSpaceing:(CGFloat)lineSpacing {
if ([self boundingRectWithSize:size font:font lineSpacing:lineSpacing].height > font.lineHeight) {
return YES;
} else {
return NO;
}
}
@end
//
// UIView+GMGradient.h
// Gengmei
//
// Created by zhouLiang on 2020/2/23.
// Copyright © 2020 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (GMGradient)
@property(nullable, copy) NSArray *colors;
@property(nullable, copy) NSArray<NSNumber *> *locations;
@property CGPoint startPoint;
@property CGPoint endPoint;
+ (UIView *_Nullable)gradientViewWithColors:(NSArray<UIColor *> *_Nullable)colors locations:(NSArray<NSNumber *> *_Nullable)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint;
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors locations:(NSArray<NSNumber *> *_Nullable)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint;
@end
NS_ASSUME_NONNULL_END
//
// UIView+GMGradient.m
// Gengmei
//
// Created by zhouLiang on 2020/2/23.
// Copyright © 2020 更美互动信息科技有限公司. All rights reserved.
//
#import "UIView+GMGradient.h"
@implementation UIView (GMGradient)
+ (Class)layerClass {
return [CAGradientLayer class];
}
+ (UIView *)gradientViewWithColors:(NSArray<UIColor *> *)colors locations:(NSArray<NSNumber *> *)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
UIView *view = [[self alloc] init];
[view setGradientBackgroundWithColors:colors locations:locations startPoint:startPoint endPoint:endPoint];
return view;
}
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *)colors locations:(NSArray<NSNumber *> *)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
self.colors = [colorsM copy];
self.locations = locations;
self.startPoint = startPoint;
self.endPoint = endPoint;
}
@end
//UIView+AZGradient.m
//
// UIView+Gradient.h
// Gengmei
//
// Created by Terminator on 2018/8/15.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (Gradient)
@property(nullable, copy) NSArray *colors;
@property(nullable, copy) NSArray<NSNumber *> *locations;
@property CGPoint startPoint;
@property CGPoint endPoint;
+ (UIView *_Nullable)gradientViewWithColors:(NSArray<UIColor *> *_Nullable)colors locations:(NSArray<NSNumber *> *_Nullable)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint;
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *_Nullable)colors locations:(NSArray<NSNumber *> *_Nullable)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint;
/**
从一个颜色变化到另一个颜色
@param beginColor 开始颜色
@param endColor 结束颜色
@param percent 百分比
*/
- (void)getColorWithColor:(UIColor *_Nullable)beginColor endColor:(UIColor *_Nullable)endColor percent:(double)percent;
@end
//
// UIView+Gradient.m
// Gengmei
//
// Created by Terminator on 2018/8/15.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import "UIView+Gradient.h"
#import <objc/runtime.h>
@implementation UIView (Gradient)
+ (Class)layerClass {
return [CAGradientLayer class];
}
+ (UIView *)gradientViewWithColors:(NSArray<UIColor *> *)colors locations:(NSArray<NSNumber *> *)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
UIView *view = [[self alloc] init];
[view setGradientBackgroundWithColors:colors locations:locations startPoint:startPoint endPoint:endPoint];
return view;
}
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *)colors locations:(NSArray<NSNumber *> *)locations startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
self.colors = [colorsM copy];
self.locations = locations;
self.startPoint = startPoint;
self.endPoint = endPoint;
}
- (NSArray *)getRGBDictionaryByColor:(UIColor *)originColor {
CGFloat r = 0,g = 0,b = 0,a = 0;
if ([self respondsToSelector:@selector(getRed:green:blue:alpha:)]) {
[originColor getRed:&r green:&g blue:&b alpha:&a];
} else {
const CGFloat *components = CGColorGetComponents(originColor.CGColor);
r = components[0];
g = components[1];
b = components[2];
a = components[3];
}
return @[@(r),@(g),@(b)];
}
- (NSArray *)transColorBeginColor:(UIColor *)beginColor andEndColor:(UIColor *)endColor {
NSArray<NSNumber *> *beginColorArr = [self getRGBDictionaryByColor:beginColor];
NSArray<NSNumber *> *endColorArr = [self getRGBDictionaryByColor:endColor];
return @[@([endColorArr[0] doubleValue] - [beginColorArr[0] doubleValue]),@([endColorArr[1] doubleValue] - [beginColorArr[1] doubleValue]),@([endColorArr[2] doubleValue] - [beginColorArr[2] doubleValue])];
}
- (void)getColorWithColor:(UIColor *)beginColor endColor:(UIColor *)endColor percent:(double)percent {
NSArray *colorArray = [self transColorBeginColor:beginColor andEndColor:endColor];
NSArray *beginColorArr = [self getRGBDictionaryByColor:beginColor];
double red = [beginColorArr[0] doubleValue] + percent * [colorArray[0] doubleValue];
double green = [beginColorArr[1] doubleValue]+ percent * [colorArray[1] doubleValue];
double blue = [beginColorArr[2] doubleValue] + percent * [colorArray[2] doubleValue];
self.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1];
}
#pragma mark - Getter&Setter
- (NSArray *)colors {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setColors:(NSArray *)colors {
objc_setAssociatedObject(self, @selector(colors), colors, OBJC_ASSOCIATION_COPY_NONATOMIC);
if ([self.layer isKindOfClass:[CAGradientLayer class]]) {
[(CAGradientLayer*)self.layer setColors:self.colors];
}
}
- (NSArray<NSNumber *> *)locations {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setLocations:(NSArray<NSNumber *> *)locations {
objc_setAssociatedObject(self, @selector(locations), locations, OBJC_ASSOCIATION_COPY_NONATOMIC);
if ([self.layer isKindOfClass:[CAGradientLayer class]]) {
[((CAGradientLayer *)self.layer) setLocations:self.locations];
}
}
- (CGPoint)startPoint {
return [objc_getAssociatedObject(self, _cmd) CGPointValue];
}
- (void)setStartPoint:(CGPoint)startPoint {
objc_setAssociatedObject(self, @selector(startPoint), [NSValue valueWithCGPoint:startPoint], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if ([self.layer isKindOfClass:[CAGradientLayer class]]) {
[((CAGradientLayer *)self.layer) setStartPoint:self.startPoint];
}
}
- (CGPoint)endPoint {
return [objc_getAssociatedObject(self, _cmd) CGPointValue];
}
- (void)setEndPoint:(CGPoint)endPoint {
objc_setAssociatedObject(self, @selector(endPoint), [NSValue valueWithCGPoint:endPoint], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if ([self.layer isKindOfClass:[CAGradientLayer class]]) {
[((CAGradientLayer *)self.layer) setEndPoint:self.endPoint];
}
}
@end
//
// WMAlertParameterObject.h
// Gengmei
//
// Created by Sean Lee on 9/8/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <GMBase/GMObject.h>
/**
* @author licong, 15-11-27 15:11:44
*
* H5执行OC方法时候,传过来的参数
*
*/
@interface WMAlertParameterObject : GMObject
@property (nonatomic, strong) NSString * title;
@property (nonatomic, strong) NSString * content;
@property (nonatomic, strong) NSString * confirmText;
@property (nonatomic, strong) NSString * cancelText;
@property (nonatomic, strong) NSString * confirmCallback;
@property (nonatomic, strong) NSString * cancelCallback;
@end
@interface WMToastParameterObject : GMObject
@property (nonatomic, strong) NSString * text;
@property (nonatomic, assign) NSInteger duration;
@end
\ No newline at end of file
//
// WMAlertParameterObject.m
// Gengmei
//
// Created by Sean Lee on 9/8/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "WMAlertParameterObject.h"
@implementation WMAlertParameterObject
@end
@implementation WMToastParameterObject
@end
\ No newline at end of file
//
// WMTagObject.h
// Gengmei
//
// Created by Sean Lee on 1/21/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <GMBase/GMObject.h>
@class GMZoneTagsObject;
@protocol WMTagObject @end
/**
* @brief 创建日记本时使用
*/
@interface WMTagObject : GMObject
/** @brief tag名称 name*/
@property (nonatomic, strong) NSString *name;
/** @brief tagId概念一样,服务器返回来的是int */
@property (nonatomic, assign) NSInteger tagId;
/*** @brief 是否选中 在3级选择项目页使用*/
@property (nonatomic, assign) BOOL isSelected;
@property (nonatomic, assign) BOOL freeToAdd;
@property (nonatomic, assign) BOOL isShowImg;
/** 活动标签tag, 7770 */
@property (nonatomic, assign) BOOL isActivityTags;
#pragma mark - since 7110
/** 热度分 */
@property (nonatomic, copy) NSString *hotScore;
/** 标签样式 */
@property (nonatomic, copy) NSString *style;
/** 标签对应图片 */
@property (nonatomic, copy) NSString *styleImageUrl;
/** 高亮 */
@property (nonatomic, copy) NSString *highlight;
/** 标签点击来源 */
@property (nonatomic, copy) NSString *tagSource;
@property (nonatomic,copy) NSString *isNewTag;
+ (WMTagObject *)constructionModel:(GMZoneTagsObject *)zoneObject;
@end
//
// WMTagObject.m
// Gengmei
//
// Created by Sean Lee on 1/21/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "WMTagObject.h"
#import "GMZoneTagsObject.h"
@implementation WMTagObject
+ (WMTagObject *)constructionModel:(GMZoneTagsObject *)zoneObject {
WMTagObject *tagObject = [[WMTagObject alloc] init];
tagObject.tagId = zoneObject.id;
tagObject.name = zoneObject.name;
tagObject.style = zoneObject.tagType;
return tagObject;
}
@end
//
// GMSegmentViewWithRedBadge.h
// Gengmei
//
// Created by 汪俊 on 2016/11/15.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
@import GMKit;
/**
带小红点的segmentView
*/
@interface GMSegmentViewWithRedBadge : WYSegmentView
- (void)showBadge:(BOOL)isShow atIndex:(NSInteger)index NS_SWIFT_NAME(show(badge:at:));
- (BOOL)isShowBadgeAtIndex:(NSInteger)index;
@end
//
// GMSegmentViewWithRedBadge.m
// Gengmei
//
// Created by 汪俊 on 2016/11/15.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMSegmentViewWithRedBadge.h"
@implementation GMSegmentViewWithRedBadge {
NSArray<UIImageView *> *_badgeViews;
}
- (void)setup {
[super setup];
self.frame = CGRectMake(0, 0, MAINSCREEN_WIDTH, 40);
self.backgroundColor = [UIColor whiteColor];
self.titleTextAttributes = @{NSFontAttributeName:[UIFont gmFont:15],
NSForegroundColorAttributeName:UIColor.auxiliaryTextDark};
self.selectedTitleTextAttributes = @{NSFontAttributeName:[UIFont gmBoldFont:15],
NSForegroundColorAttributeName:UIColor.headlineText};
self.showIndicator = YES;
self.widthStyle = WYSegmentViewWidthStyleEqual;
self.indicatorColor = UIColor.auxiliaryTextGreen;
}
- (void)layoutSegments {
[super layoutSegments];
NSMutableArray *badges = [NSMutableArray array];
//添加小红点
for (UIView *subview in self.scrollView.subviews) {
for (UIView *view in subview.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
UIImageView *redBadge = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"red_badge"]];
redBadge.hidden = YES;
UIButton *button = (UIButton *)view;
[button.titleLabel addSubview:redBadge];
[redBadge mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(-1);
make.left.mas_equalTo(button.titleLabel.width);
}];
[badges addObject:redBadge];
}
}
}
_badgeViews = badges;
}
- (void)showBadge:(BOOL)isShow atIndex: (NSInteger)index {
UIImageView *badgeView = _badgeViews[index];
badgeView.hidden = !isShow;
}
- (BOOL)isShowBadgeAtIndex:(NSInteger)index {
return !_badgeViews[index].hidden;
}
@end
//
// WYSegmentView+Factory.h
// Gengmei
//
// Created by wangyang on 16/2/17.
// Copyright © 2016年 Wanmeichuangyi. All rights reserved.
//
#import <GMKit/WYSegmentView.h>
NS_ASSUME_NONNULL_BEGIN
@interface WYSegmentView (Factory)
/**
提供一个基础的,字体大小、颜色符合UI规范的segment。
*/
+ (WYSegmentView *)baseThemeSegment;
/**
* @author wangyang, 16-02-18 15:02:23
*
* @brief 用于多个标题,segment可以滑动的设计
* @since 5.9.1
*/
+ (WYSegmentView *)dynamicSegment;
/**
* @author wangyang, 16-02-18 15:02:49
*
* @brief 用于标题个数固定,segment宽度一样的设计
* @since 5.9.1
*/
+ (WYSegmentView *)fullWidthSegment;
/**
* @author wangyang, 16-02-18 16:02:51
*
* @brief 用于我的订单页的segment
* @since 5.9.1
*/
+ (WYSegmentView *)myOrderListSegment;
@end
NS_ASSUME_NONNULL_END
//
// WYSegmentView+Factory.m
// Gengmei
//
// Created by wangyang on 16/2/17.
// Copyright © 2016年 Wanmeichuangyi. All rights reserved.
//
#import "WYSegmentView+Factory.h"
@import GMKit;
@implementation WYSegmentView (Factory)
+ (WYSegmentView *)baseThemeSegment {
WYSegmentView *segment = [[WYSegmentView alloc] initWithFrame:CGRectMake(0, 0, MAINSCREEN_WIDTH, 40)];
segment.backgroundColor = [UIColor whiteColor];
segment.showIndicator = YES;
return segment;
}
+ (WYSegmentView *)dynamicSegment {
WYSegmentView *segment = [self baseThemeSegment];
segment.titleTextAttributes = @{NSFontAttributeName:[UIFont gmFont:15],
NSForegroundColorAttributeName:UIColor.auxiliaryTextDark};
segment.selectedTitleTextAttributes = @{NSFontAttributeName:[UIFont gmBoldFont:15],
NSForegroundColorAttributeName:UIColor.headlineText};
segment.scrollView.contentInset = UIEdgeInsetsMake(0, 6, 0, 6);
segment.widthStyle = WYSegmentViewWidthStyleDynamic;
segment.itemHorizonalPadding = 14;
return segment;
}
+ (WYSegmentView *)fullWidthSegment {
WYSegmentView *segment = [self baseThemeSegment];
segment.titleTextAttributes = @{NSFontAttributeName:[UIFont gmFont:15],
NSForegroundColorAttributeName:UIColor.auxiliaryTextDark};
segment.selectedTitleTextAttributes = @{NSFontAttributeName:[UIFont gmBoldFont:15],
NSForegroundColorAttributeName:UIColor.headlineText};
segment.widthStyle = WYSegmentViewWidthStyleEqual;
return segment;
}
+ (WYSegmentView *)myOrderListSegment {
WYSegmentView *segment = [self baseThemeSegment];
segment.titleTextAttributes = @{NSFontAttributeName:[UIFont gmFont:15],
NSForegroundColorAttributeName:UIColor.auxiliaryTextDark};
segment.selectedTitleTextAttributes = @{NSFontAttributeName:[UIFont gmBoldFont:15],
NSForegroundColorAttributeName:UIColor.headlineText};
segment.widthStyle = WYSegmentViewWidthStyleEqual;
return segment;
}
@end
//
// GMInstallmentView.h
// Gengmei
//
// Created by Terminator on 16/10/23.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMView.h"
#import "GMImageView.h"
#import "GMHighlightLabel.h"
@interface GMInstallmentView : GMView
@property (nonatomic, strong) GMHighlightLabel *promoteLabel;
@property (nonatomic, strong) GMImageView *icon;
@end
//
// GMInstallmentView.m
// Gengmei
//
// Created by Terminator on 16/10/23.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMInstallmentView.h"
#import <GMKit/GMFont.h>
#import <GMKit/UIColor+GMTheme.h>
#import <GMKit/UIView+LineWithAutolayout.h>
@interface GMInstallmentView()
@property (nonatomic, strong) GMView *installView;
@end
@implementation GMInstallmentView
- (void)setup {
[super setup];
_installView = [[GMView alloc] init];
[_installView addTopLineWithLeft:15 right:-15];
[self addSubview:_installView];
[_installView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.right.mas_equalTo(0);
make.top.mas_equalTo(0);
make.height.mas_equalTo(45);
}];
_icon = [[GMImageView alloc] init];
_icon.image = [UIImage imageNamed:@"installment_icon"];
[_installView addSubview:_icon];
[_icon mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(15);
make.centerY.mas_equalTo(0);
}];
_promoteLabel = [[GMHighlightLabel alloc] init];
[_promoteLabel setContentHuggingPriority:100 forAxis:UILayoutConstraintAxisHorizontal];
[_promoteLabel setContentCompressionResistancePriority:1000 forAxis:UILayoutConstraintAxisHorizontal];
_promoteLabel.hightlightColor = UIColor.secondaryVisual;
_promoteLabel.normalColor = UIColor.bodyText ;
_promoteLabel.textColor = UIColor.bodyText;
_promoteLabel.font = [UIFont gmFont:11];
_promoteLabel.hightlightFont = [UIFont gmBoldFont:11];
[_installView addSubview:_promoteLabel];
[_promoteLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_icon.mas_right).offset(10);
make.right.mas_lessThanOrEqualTo(-15);
make.centerY.equalTo(_icon.mas_centerY);
}];
}
@end
//
// GMInsuranceView.h
// Gengmei
//
// Created by 翟国钧 on 2017/2/13.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMView.h"
#import "GMLabel.h"
@interface GMInsuranceView : GMView
@property (nonatomic, strong) GMLabel *insuranceLabel;
@end
//
// GMInsuranceView.m
// Gengmei
//
// Created by 翟国钧 on 2017/2/13.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMInsuranceView.h"
#import "GMImageView.h"
#import <GMKit/UIColor+GMTheme.h>
#import <GMKit/UIView+LineWithAutolayout.h>
@interface GMInsuranceView()
@property (nonatomic, strong) GMView *installView;
@property (nonatomic, strong) GMImageView *icon;
@end
@implementation GMInsuranceView
- (void)setup {
[super setup];
_installView = [[GMView alloc] init];
[_installView addTopLineWithLeft:15 right:-15];
[self addSubview:_installView];
[_installView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.right.mas_equalTo(0);
make.top.mas_equalTo(0);
make.height.mas_equalTo(45);
}];
_icon = [[GMImageView alloc] init];
_icon.image = [UIImage imageNamed:@"welfare_insurance"];
[_installView addSubview:_icon];
[_icon mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(15);
make.centerY.mas_equalTo(0);
}];
_insuranceLabel = [GMLabel labelWithTextColor:UIColor.bodyText fontSize:11];
[_installView addSubview:_insuranceLabel];
[_insuranceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_icon.mas_right).offset(10);
make.centerY.equalTo(_icon.mas_centerY);
}];
}
@end
//
// GMLiveWelfareView.h
// Gengmei
//
// Created by 汪俊 on 2017/3/30.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMImageView.h"
#import "GMInstallmentView.h"
#import "GMInsuranceView.h"
//#import "Gengmei-Swift.h"
@class AllLayoutButton;
@class GMLiveWelfareView;
@class GMAdLabel;
@protocol GMLiveWelfareViewDelegate <NSObject>
- (void)didSelectedWelfareView:(GMLiveWelfareView *)welFareView;
- (void)didClickedHospitalDetailButton:(AllLayoutButton *)button;
@end
/**
直播和回放页面的美购
*/
@interface GMLiveWelfareView : GMView
@property (nonatomic , strong) GMView *welfareContainer;
/** @brief 美购大图片 */
@property (nonatomic , strong) GMImageView *bigIconImage;
/** @brief 预付价 */
@property (nonatomic , strong) GMImageView *yufuImage;
/** @brief 已售完 */
@property (nonatomic , strong) GMImageView *sallOutImage;
/** @brief 美购标题 */
@property (nonatomic , strong) GMLabel *welfareTitle;
/** @brief 美购简介 */
@property (nonatomic , strong) GMAdLabel *welfareContent;
/** @brief 更美价 */
@property (nonatomic , strong) GMLabel *gengmeiPrice;
/** @brief 市场价 */
@property (nonatomic , strong) GMLabel *marketPrice;
/** @brief 删除线 */
@property (nonatomic , strong) GMLabel *deleteLabel;
/** @brief 人民币(元/元起) */
@property (nonatomic , strong) GMLabel *yuanLabel;
/** @brief 预付款标签 */
@property (nonatomic , strong) GMLabel *yufuLabel;
/** @brief 申请数 */
@property (nonatomic , strong) GMLabel *applyNumber;
/** @brief 剩余多少个*/
@property (nonatomic , strong) GMLabel *surplusLabel;
/** @brief 城市 */
@property (nonatomic , strong) GMLabel *cityLabel;
/** @brief 医生 */
@property (nonatomic , strong) GMLabel *doctorLabel;
/** @brief 机构 */
@property (nonatomic , strong) GMLabel *hospitalLabel;
/**状态栏背景*/
@property (nonatomic, strong) GMView *statusBG;
/** @brief */
@property (nonatomic , strong) UIView *surplusBG;
/** @brief 秒杀价图片*/
@property (nonatomic , strong) GMImageView *seckillIcon;
/** seckill是否隐藏*/
@property (nonatomic, assign) BOOL isSeckillHidden;
/**
展示推广label
@author wangjun 16-08-01 in 6.3.0
*/
@property (nonatomic, assign) BOOL showPromotion;
/**
分期提示
*/
//@property (nonatomic, strong) GMInstallmentView *installmentView;
/**
保险提示
*/
//@property (nonatomic, strong) GMInsuranceView *insuranceView;
/**
是否展示推分期
*/
//@property (nonatomic, assign) BOOL showInstallment;
/**
是否展示保险
*/
//@property (nonatomic, assign) BOOL showInsurance;
@property (nonatomic , strong) UIImageView *hospitalBg;
@property (nonatomic, weak) id<GMLiveWelfareViewDelegate> delegate;
- (void)show;
- (void)hide;
@end
This diff is collapsed.
//
// GMWebViewModel.h
// Gengmei
//
// Created by MoMo on 2019/12/12.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "WMFetchDataViewModel.h"
/** webView 相关数据 */
NS_ASSUME_NONNULL_BEGIN
@interface GMWebViewModel : WMFetchDataViewModel
/// 问题页,置顶回答id
@property (nonatomic, copy) NSString *top_answer_id;
/** 回复问题id */
@property (nonatomic, copy) NSString *questionId;
/** 视频Token */
@property (nonatomic, copy) NSString *videoToken;
@end
NS_ASSUME_NONNULL_END
//
// GMWebViewModel.m
// Gengmei
//
// Created by MoMo on 2019/12/12.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "GMWebViewModel.h"
@implementation GMWebViewModel
@end
//
// UIViewController+UrlScheme.h
// Gengmei
//
// Created by Thierry on 4/21/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIViewController (UrlScheme)
/**
区域埋点字段
*/
@property (nonatomic, strong) NSDictionary *referDict;
@end
NS_ASSUME_NONNULL_END
//
// UIViewController+UrlScheme.m
// Gengmei
//
// Created by Thierry on 4/21/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <objc/runtime.h>
#import "UIViewController+UrlScheme.h"
@implementation UIViewController (UrlScheme)
#pragma mark -------------------
- (void)setReferDict:(NSDictionary *)referDict {
objc_setAssociatedObject(self, @selector(referDict), referDict, OBJC_ASSOCIATION_RETAIN);
}
- (NSDictionary *)referDict {
return objc_getAssociatedObject(self, @selector(referDict));
}
@end
//
// WMBaseViewController+FadeNavigation.h
// Gengmei
//
// Created by wangyang on 2017/6/6.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "WMBaseViewController.h"
@interface WMBaseViewController (FadeNavigation)
@property(nonatomic, assign) CGFloat animationDistance;
// 考虑到如果scrollview y偏移量为负数, 添加次当做scrollView最初的Y偏移量
@property (nonatomic, assign) CGFloat contentOffsetY;
// 返回当前的alpha值
- (CGFloat)animationBar:(OCNavigationBar *)bar withScrollView:(UIScrollView *)scrollView;
@end
//
// WMBaseViewController+FadeNavigation.m
// Gengmei
//
// Created by wangyang on 2017/6/6.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "WMBaseViewController+FadeNavigation.h"
#import <objc/runtime.h>
@implementation WMBaseViewController (FadeNavigation)
- (void)setAnimationDistance:(CGFloat)animationDistance {
objc_setAssociatedObject(self, @selector(animationDistance), @(animationDistance), OBJC_ASSOCIATION_RETAIN);
}
- (CGFloat)animationDistance {
NSNumber *_animationDistance = objc_getAssociatedObject(self, _cmd);
if (_animationDistance == nil) {
return 0;
} else {
return [_animationDistance doubleValue];
}
}
- (void)setContentOffsetY:(CGFloat)contentOffsetY {
objc_setAssociatedObject(self, @selector(contentOffsetY), @(contentOffsetY), OBJC_ASSOCIATION_RETAIN);
}
- (CGFloat)contentOffsetY {
NSNumber *_contentOffsetY = objc_getAssociatedObject(self, _cmd);
if (_contentOffsetY == nil) {
return 0;
}
return _contentOffsetY.doubleValue;
}
- (CGFloat)animationBar:(OCNavigationBar *)bar withScrollView:(UIScrollView *)scrollView {
CGFloat offsetY = scrollView.contentOffset.y;
if (self.contentOffsetY > 0) {
offsetY = self.contentOffsetY;
}
CGFloat alpha = MIN(1.0, offsetY / self.animationDistance);
if (offsetY > self.animationDistance) {
// 导航栏不透明
bar.backgroundColor = [UIColor colorWithWhite:1 alpha:alpha];
bar.titleLabel.textColor = [UIColor colorWithWhite:0 alpha:alpha];
bar.isShowShadow = YES;
} else {
// 导航栏渐变到透明
bar.backgroundColor = [UIColor colorWithWhite:1 alpha:alpha];
bar.titleLabel.textColor = [UIColor colorWithWhite:0 alpha:alpha];
bar.isShowShadow = NO;
}
self.navigationBar.titleLabel.hidden = alpha == 0;
return alpha;
}
@end
//
// WMBaseViewController+OCNavigationBar.h
// Gengmei
//
// Created by wangyang on 16/7/8.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import "WMBaseViewController.h"
/*** @brief 右按钮的 按钮类型 */
typedef NS_ENUM(NSUInteger, OCBarButtonImageType){
/*** @brief 默认没有右按钮*/
OCBarButtonImageTypeDefault = 0,
/*** @brief 图片分享按钮 */
OCBarButtonImageTypeShare = 1,
/*** @brief 写新日记 */
OCBarButtonImageTypeDiary,
/*** @brief 搜索按钮。如果是继承于WMBaseViewController,这个option的action不需要单独实现,在base中已经实现了 */
OCBarButtonImageTypeSearch,
/*** @brief 分享返现,具体方法没有实现,请在子类中实现*/
OCBarButtonImageTypeShareCashback,
/*** @brief 客服,请在子类中实现*/
OCBarButtonImageTypeCustomerServices,
};
@interface WMBaseViewController (OCNavigationBar)
/**
* @brief 设置导航栏 左边默认是返回按钮
*
* @param title 导航tilte
* @param rightTitle 右边文字型的按钮
*/
- (void)setNavigateTitle:(NSString *)title rightButtonTitle:(NSString *)rightButtonTitle;
/**
* @brief 设置导航栏 左边默认是返回按钮
*
* @param title 导航tilte
* @param rightButton 右边是图片型的按钮
*/
- (void)setNavigateTitle:(NSString *)title rightButtonOption:(OCBarButtonImageType)rightButtonOption;
/**
* @brief 当右侧是标题按钮时,设置右侧标题按钮不同状态下的色值
* @param normalColor 常态下色值
* @param highlightColor 高亮下色值
* @param disableColor 失效下色值
*/
- (void)setRightTitleNormalColor:(UIColor *)normalColor highlightColor:(UIColor *)highlightColor disableColor:(UIColor *)disableColor;
/**
* @author wangyang
*
* 通过此方法可以返回一个rightButton图片名,用于navigationBar.rightIcon
*/
- (NSString *)navigationBarIconFromType:(OCBarButtonImageType)type;
@end
//
// WMBaseViewController+OCNavigationBar.m
// Gengmei
//
// Created by wangyang on 16/7/8.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import "WMBaseViewController.h"
#import "WMBaseViewController+OCNavigationBar.h"
@implementation WMBaseViewController (OCNavigationBar)
- (void)setNavigateTitle:(NSString *)title rightButtonTitle:(NSString *)rightButtonTitle{
self.navigationBar.title = title;
self.navigationBar.rightTitle = rightButtonTitle;
}
- (void)setNavigateTitle:(NSString *)title rightButtonOption:(OCBarButtonImageType)rightButtonOption{
self.navigationBar.title = title;
self.navigationBar.rightIcon = [self navigationBarIconFromType:rightButtonOption];
}
- (NSString *)navigationBarIconFromType:(OCBarButtonImageType)type {
switch (type) {
case OCBarButtonImageTypeShare:
return @"share";
case OCBarButtonImageTypeDiary:
return @"write";
case OCBarButtonImageTypeSearch:
return @"search_green";
case OCBarButtonImageTypeShareCashback:
return @"share_cashback";
case OCBarButtonImageTypeCustomerServices:
return @"customer_service";
default:
return @"";
}
}
- (void)setRightTitleNormalColor:(UIColor *)normalColor highlightColor:(UIColor *)highlightColor disableColor:(UIColor *)disableColor{
if (normalColor) {
[self.navigationBar.rightButton setTitleColor:normalColor forState:UIControlStateNormal];
}
if (highlightColor) {
[self.navigationBar.rightButton setTitleColor:normalColor forState:UIControlStateHighlighted];
}
if (disableColor) {
[self.navigationBar.rightButton setTitleColor:normalColor forState:UIControlStateDisabled];
}
}
@end
......@@ -9,9 +9,8 @@
#import "GMNavigationController.h"
#import "UIViewController+PushType.h"
#import "GMPresentAnimation.h"
@import GMKit;
#import "GMCustomNavigationAnimationProtocol.h"
@import GMKit;
@interface GMNavigationController ()<UINavigationControllerDelegate>
......@@ -22,7 +21,7 @@
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = self;
self.fd_viewControllerBasedNavigationBarAppearanceEnabled = NO;
// self.fd_viewControllerBasedNavigationBarAppearanceEnabled = NO;
}
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
......
//
// JXCategoryBaseCell.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXCategoryBaseCellModel.h"
@interface JXCategoryBaseCell : UICollectionViewCell
@property (nonatomic, strong) JXCategoryBaseCellModel *cellModel;
- (void)initializeViews NS_REQUIRES_SUPER;
- (void)reloadData:(JXCategoryBaseCellModel *)cellModel NS_REQUIRES_SUPER;
@end
//
// JXCategoryBaseCell.m
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryBaseCell.h"
@interface JXCategoryBaseCell ()
@end
@implementation JXCategoryBaseCell
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initializeViews];
}
return self;
}
- (void)initializeViews
{
}
- (void)reloadData:(JXCategoryBaseCellModel *)cellModel {
self.cellModel = cellModel;
}
@end
//
// JXCategoryBaseCellModel.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface JXCategoryBaseCellModel : NSObject
@property (nonatomic, assign) NSUInteger index;
@property (nonatomic, assign) BOOL selected;
@property (nonatomic, assign) CGFloat cellWidth;
@property (nonatomic, assign) CGFloat cellSpacing;
@property (nonatomic, assign) BOOL cellWidthZoomEnabled;
@property (nonatomic, assign) CGFloat cellWidthZoomScale;
@end
//
// JXCategoryBaseCellModel.m
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryBaseCellModel.h"
@implementation JXCategoryBaseCellModel
- (CGFloat)cellWidth {
if (_cellWidthZoomEnabled) {
return _cellWidth * _cellWidthZoomScale;
}
return _cellWidth;
}
@end
//
// JXCategoryView.h
// UI系列测试
//
// Created by jiaxin on 2018/3/15.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXCategoryBaseCell.h"
#import "JXCategoryBaseCellModel.h"
#import "JXCategoryCollectionView.h"
#import "JXCategoryViewDefines.h"
@class JXCategoryBaseView;
@protocol JXCategoryViewDelegate <NSObject>
@optional
//为什么会把选中代理分为三个,因为有时候只关心点击选中的,有时候只关心滚动选中的,有时候只关心选中。所以具体情况,使用对应方法。
/**
点击选择或者滚动选中都会调用该方法,如果外部不关心具体是点击还是滚动选中的,只关心选中这个事件,就实现该方法。
@param categoryView categoryView description
@param index 选中的index
*/
- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index;
/**
点击选中的情况才会调用该方法
@param categoryView categoryView description
@param index 选中的index
*/
- (void)categoryView:(JXCategoryBaseView *)categoryView didClickSelectedItemAtIndex:(NSInteger)index;
/**
滚动选中的情况才会调用该方法
@param categoryView categoryView description
@param index 选中的index
*/
- (void)categoryView:(JXCategoryBaseView *)categoryView didScrollSelectedItemAtIndex:(NSInteger)index;
/**
只有点击的切换才会调用!!!
因为用户点击,contentScrollView即将过渡到目标index的配置。内部默认实现`[self.contentScrollView setContentOffset:CGPointMake(targetIndex*self.contentScrollView.bounds.size.width, 0) animated:YES];`。如果实现该代理方法,以自定义实现为准。比如将animated设置为NO,点击切换时无需滚动效果。类似于今日头条APP。
@param categoryView categoryView description
@param index index description
*/
- (void)categoryView:(JXCategoryBaseView *)categoryView didClickedItemContentScrollViewTransitionToIndex:(NSInteger)index;
/**
正在滚动中的回调
@param categoryView categoryView description
@param leftIndex 正在滚动中,相对位置处于左边的index
@param rightIndex 正在滚动中,相对位置处于右边的index
@param ratio 百分比
*/
- (void)categoryView:(JXCategoryBaseView *)categoryView scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio;
@end
@interface JXCategoryBaseView : UIView
@property (nonatomic, strong) JXCategoryCollectionView *collectionView;
@property (nonatomic, strong) NSArray <JXCategoryBaseCellModel *>*dataSource;
@property (nonatomic, weak) id<JXCategoryViewDelegate>delegate;
@property (nonatomic, strong) UIScrollView *contentScrollView; //需要关联的contentScrollView
@property (nonatomic, assign) NSInteger defaultSelectedIndex; //修改初始化的时候默认选择的index
@property (nonatomic, assign, readonly) NSInteger selectedIndex;
@property (nonatomic, assign) CGFloat contentEdgeInsetLeft; //整体内容的左边距,默认JXCategoryViewAutomaticDimension(等于cellSpacing)
@property (nonatomic, assign) CGFloat contentEdgeInsetRight; //整体内容的右边距,默认JXCategoryViewAutomaticDimension(等于cellSpacing)
@property (nonatomic, assign) CGFloat cellWidth; //默认JXCategoryViewAutomaticDimension
@property (nonatomic, assign) CGFloat cellWidthIncrement; //cell宽度补偿。默认:0
@property (nonatomic, assign) CGFloat cellSpacing; //cell之间的间距,默认20
@property (nonatomic, assign) BOOL averageCellSpacingEnabled; //当item内容总宽度小于JXCategoryBaseView的宽度,是否将cellSpacing均分。默认为YES。
//----------------------cellWidthZoomEnabled-----------------------//
//cell宽度的缩放主要是为了腾讯视频、汽车之家效果打造的,一般情况下慎用,不太好控制。
@property (nonatomic, assign) BOOL cellWidthZoomEnabled; //默认为NO
@property (nonatomic, assign) BOOL cellWidthZoomScrollGradientEnabled; //手势滚动中,是否需要更新状态。默认为YES
@property (nonatomic, assign) CGFloat cellWidthZoomScale; //默认1.2,cellWidthZoomEnabled为YES才生效
/**
代码调用选中了目标index的item
@param index 目标index
*/
- (void)selectItemAtIndex:(NSInteger)index;
/**
初始化的时候无需调用。初始化之后更新其他配置属性,需要调用该方法,进行刷新。
*/
- (void)reloadData;
/**
刷新指定的index的cell
@param index 指定cell的index
*/
- (void)reloadCellAtIndex:(NSInteger)index;
#pragma mark - Subclass use
- (CGRect)getTargetCellFrame:(NSInteger)targetIndex;
#pragma mark - Subclass Override
- (void)initializeData NS_REQUIRES_SUPER;
- (void)initializeViews NS_REQUIRES_SUPER;
/**
reloadData方法调用,重新生成数据源赋值到self.dataSource
*/
- (void)refreshDataSource;
/**
reloadData方法调用,根据数据源重新刷新状态;
*/
- (void)refreshState NS_REQUIRES_SUPER;
/**
用户点击了某个item,刷新选中与取消选中的cellModel
@param selectedCellModel 选中的cellModel
@param unselectedCellModel 取消选中的cellModel
*/
- (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel NS_REQUIRES_SUPER;
/**
关联的contentScrollView的contentOffset发生了改变
@param contentOffset 偏移量
*/
- (void)contentOffsetOfContentScrollViewDidChanged:(CGPoint)contentOffset NS_REQUIRES_SUPER;
/**
该方法用于子类重载,如果外部要选中某个index,请使用`- (void)selectItemAtIndex:(NSUInteger)index;`
点击某一个item,或者contentScrollView滚动到某一个item的时候调用。根据selectIndex刷新选中状态。
@param index 选中的index
@param isClicked YES:点击选中;NO:滚动选中。
@return 返回值为NO,表示触发内部某些判断(点击了同一个cell),子类无需后续操作。
*/
- (BOOL)selectCellAtIndex:(NSInteger)index isClicked:(BOOL)isClicked NS_REQUIRES_SUPER;
/**
reloadData时,返回每个cell的宽度
@param index 目标index
@return cellWidth
*/
- (CGFloat)preferredCellWidthAtIndex:(NSInteger)index;
/**
返回自定义cell的class
@return cell class
*/
- (Class)preferredCellClass;
/**
refreshState时调用,重置cellModel的状态
@param cellModel 待重置的cellModel
@param index 目标index
*/
- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index;
@end
//
// JXCategoryCollectionView.h
// UI系列测试
//
// Created by jiaxin on 2018/3/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "JXCategoryIndicatorProtocol.h"
@interface JXCategoryCollectionView : UICollectionView
@property (nonatomic, strong) NSArray <UIView<JXCategoryIndicatorProtocol> *> *indicators;
@end
//
// JXCategoryCollectionView.m
// UI系列测试
//
// Created by jiaxin on 2018/3/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryCollectionView.h"
@implementation JXCategoryCollectionView
- (void)layoutSubviews
{
[super layoutSubviews];
for (UIView<JXCategoryIndicatorProtocol> *view in self.indicators) {
[self sendSubviewToBack:view];
}
}
@end
//
// JXCategoryFactory.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface JXCategoryFactory : NSObject
+ (CGFloat)interpolationFrom:(CGFloat)from to:(CGFloat)to percent:(CGFloat)percent;
+ (UIColor *)interpolationColorFrom:(UIColor *)fromColor to:(UIColor *)toColor percent:(CGFloat)percent;
@end
//
// JXCategoryFactory.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryFactory.h"
#import "UIColor+JXAdd.h"
@implementation JXCategoryFactory
+ (CGFloat)interpolationFrom:(CGFloat)from to:(CGFloat)to percent:(CGFloat)percent
{
percent = MAX(0, MIN(1, percent));
NSLog(@"percent---%.2f", percent);
NSLog(@"from + (to - from)*---%.2f", (from + (to - from)*percent));
return from + (to - from)*percent;
}
+ (UIColor *)interpolationColorFrom:(UIColor *)fromColor to:(UIColor *)toColor percent:(CGFloat)percent
{
CGFloat red = [self interpolationFrom:fromColor.jx_red to:toColor.jx_red percent:percent];
CGFloat green = [self interpolationFrom:fromColor.jx_green to:toColor.jx_green percent:percent];
CGFloat blue = [self interpolationFrom:fromColor.jx_blue to:toColor.jx_blue percent:percent];
CGFloat alpha = [self interpolationFrom:fromColor.jx_alpha to:toColor.jx_alpha percent:percent];
return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}
@end
//
// JXCategoryIndicatorParamsModel.h
// JXCategoryView
//
// Created by jiaxin on 2018/12/13.
// Copyright © 2018 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/**
指示器不同情况处理时传递的数据模型,不同情况会对不同的属性赋值,根据不同情况的api说明确认。
为什么会通过model传递数据,因为指示器处理逻辑以后会扩展不同的使用场景,会新增参数,如果不通过model传递,就会在api新增参数,一旦修改api该的地方就特别多了,而且会影响到之前自定义实现的开发者。
*/
@interface JXCategoryIndicatorParamsModel : NSObject
@property (nonatomic, assign) NSInteger selectedIndex; //当前选中的index
@property (nonatomic, assign) CGRect selectedCellFrame; //当前选中的cellFrame
@property (nonatomic, assign) NSInteger leftIndex; //正在过渡中的两个cell,相对位置在左边的cell的index
@property (nonatomic, assign) CGRect leftCellFrame; //正在过渡中的两个cell,相对位置在左边的cell的frame
@property (nonatomic, assign) NSInteger rightIndex; //正在过渡中的两个cell,相对位置在右边的cell的index
@property (nonatomic, assign) CGRect rightCellFrame; //正在过渡中的两个cell,相对位置在右边的cell的frame
@property (nonatomic, assign) CGFloat percent; //正在过渡中的两个cell,从左到右的百分比
@property (nonatomic, assign) NSInteger lastSelectedIndex; //之前选中的index
@property (nonatomic, assign) BOOL isClicked; //YES:通过点击选中;NO:通过滚动选中
@end
//
// JXCategoryIndicatorParamsModel.m
// JXCategoryView
//
// Created by jiaxin on 2018/12/13.
// Copyright © 2018 jiaxin. All rights reserved.
//
#import "JXCategoryIndicatorParamsModel.h"
@implementation JXCategoryIndicatorParamsModel
@end
//
// JXCategoryIndicatorProtocol.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "JXCategoryViewDefines.h"
#import "JXCategoryIndicatorParamsModel.h"
@protocol JXCategoryIndicatorProtocol <NSObject>
/**
视图重置状态时调用
param selectedIndex 当前选中的index
param selectedCellFrame 当前选中的cellFrame
@param model 数据模型
*/
- (void)jx_refreshState:(JXCategoryIndicatorParamsModel *)model;
/**
contentScrollView在进行手势滑动时,处理指示器跟随手势变化UI逻辑;
param selectedIndex 当前选中的index
param leftIndex 正在过渡中的两个cell,相对位置在左边的cell的index
param leftCellFrame 正在过渡中的两个cell,相对位置在左边的cell的frame
param rightIndex 正在过渡中的两个cell,相对位置在右边的cell的index
param rightCellFrame 正在过渡中的两个cell,相对位置在右边的cell的frame
param percent 过渡百分比
@param model 数据模型
*/
- (void)jx_contentScrollViewDidScroll:(JXCategoryIndicatorParamsModel *)model;
/**
点击选中了某一个cell
param lastSelectedIndex 之前选中的index
param selectedIndex 选中的index
param selectedCellFrame 选中的cellFrame
param isClicked YES:点击选中;NO:滚动选中。
@param model 数据模型
*/
- (void)jx_selectedCell:(JXCategoryIndicatorParamsModel *)model;
@end
//
// JXCategoryListScrollView.h
// JXCategoryView
//
// Created by jiaxin on 2018/9/12.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
@class JXCategoryListContainerView;
@protocol JXCategoryListContentViewDelegate <NSObject>
/**
如果列表是VC,就返回VC.view
如果列表是View,就返回View自己
@return 返回列表视图
*/
- (UIView *)listView;
@optional
/**
可选实现,列表逻辑层面显示的时候调用
*/
- (void)listDidAppear;
/**
可选实现,列表逻辑层面消失的时候调用
*/
- (void)listDidDisappear;
@end
@protocol JXCategoryListContainerViewDelegate <NSObject>
/**
返回list的数量
@param listContainerView 列表的容器视图
@return list的数量
*/
- (NSInteger)numberOfListsInlistContainerView:(JXCategoryListContainerView *)listContainerView;
/**
根据index初始化对应的遵从JXCategoryListContentViewDelegate协议的list,注意是初始化哟,要new一个新的实例!!!
@param listContainerView 列表的容器视图
@param index 目标下标
@return 新的遵从JXCategoryListContentViewDelegate协议的list实例
*/
- (id<JXCategoryListContentViewDelegate>)listContainerView:(JXCategoryListContainerView *)listContainerView initListForIndex:(NSInteger)index;
@end
@interface JXCategoryListContainerView : UIView
@property (nonatomic, strong, readonly) UIScrollView *scrollView;
/**
滚动切换的时候,滚动距离超过一页的多少百分比,就认为切换了页面。默认0.5(即滚动超过了半屏,就认为翻页了)。范围0~1,开区间不包括0和1
*/
@property (nonatomic, assign) CGFloat didAppearPercent;
/**
需要和self.categoryView.defaultSelectedIndex保持一致
*/
@property (nonatomic, assign) NSInteger defaultSelectedIndex;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
/**
指定的初始化器
@param parentVC 父vc
@param delegate JXCategoryListContainerViewDelegate代理
@return JXCategoryListContainerView实例
*/
- (instancetype)initWithParentVC:(UIViewController *)parentVC delegate:(id<JXCategoryListContainerViewDelegate>)delegate NS_DESIGNATED_INITIALIZER;
- (void)reloadData;
//必须调用,请按照demo示例那样调用
- (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio selectedIndex:(NSInteger)selectedIndex;
//必须调用,请按照demo示例那样调用(注意是是点击选中的回调,不是其他回调)
- (void)didClickSelectedItemAtIndex:(NSInteger)index;
@end
//
// JXCategoryListContainerView.m
// JXCategoryView
//
// Created by jiaxin on 2018/9/12.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryListContainerView.h"
@interface JXCategoryListContainerView ()
@property (nonatomic, weak) id<JXCategoryListContainerViewDelegate> delegate;
@property (nonatomic, weak) UIViewController *parentViewController;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, assign) NSInteger currentIndex;
@property (nonatomic, strong) NSMutableDictionary <NSNumber *, id<JXCategoryListContentViewDelegate>> *listVCDict;
@property (nonatomic, assign) BOOL isLayoutSubviewsed;
@end
@implementation JXCategoryListContainerView
- (instancetype)initWithParentVC:(UIViewController *)parentVC delegate:(id<JXCategoryListContainerViewDelegate>)delegate {
self = [super initWithFrame:CGRectZero];
if (self) {
_didAppearPercent = 0.5;
_parentViewController = parentVC;
_parentViewController.automaticallyAdjustsScrollViewInsets = NO;
_delegate = delegate;
_listVCDict = [NSMutableDictionary dictionary];
[self initializeViews];
}
return self;
}
- (void)initializeViews {
_scrollView = [[UIScrollView alloc] init];
self.scrollView.pagingEnabled = YES;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.scrollsToTop = NO;
self.scrollView.bounces = NO;
if (@available(iOS 11.0, *)) {
self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
[self addSubview:self.scrollView];
}
- (void)reloadData {
for (id<JXCategoryListContentViewDelegate> list in self.listVCDict.allValues) {
[list.listView removeFromSuperview];
}
[self.listVCDict removeAllObjects];
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height);
[self listDidAppear:self.currentIndex];
}
- (void)layoutSubviews {
[super layoutSubviews];
self.scrollView.frame = self.bounds;
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*[self.delegate numberOfListsInlistContainerView:self], self.scrollView.bounds.size.height);
if (!self.isLayoutSubviewsed) {
self.isLayoutSubviewsed = YES;
//初始化第一次调用
[self listDidAppear:self.currentIndex];
}
}
- (void)setDefaultSelectedIndex:(NSInteger)defaultSelectedIndex {
_defaultSelectedIndex = defaultSelectedIndex;
self.currentIndex = defaultSelectedIndex;
}
#pragma mark - JXCategoryBaseView回调
- (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio selectedIndex:(NSInteger)selectedIndex {
NSInteger targetIndex = -1;
NSInteger disappearIndex = -1;
if (rightIndex == selectedIndex) {
//当前选中的在右边,用户正在从右边往左边滑动
if (ratio < (1 - self.didAppearPercent)) {
targetIndex = leftIndex;
disappearIndex = rightIndex;
}
}else {
//当前选中的在左边,用户正在从左边往右边滑动
if (ratio > self.didAppearPercent) {
targetIndex = rightIndex;
disappearIndex = leftIndex;
}
}
if (targetIndex != -1 && self.currentIndex != targetIndex) {
[self listDidAppear:targetIndex];
[self listDidDisappear:disappearIndex];
}
}
- (void)didClickSelectedItemAtIndex:(NSInteger)index {
[self listDidDisappear:self.currentIndex];
[self listDidAppear:index];
}
#pragma mark - Private
- (void)listDidAppear:(NSInteger)index {
self.currentIndex = index;
id<JXCategoryListContentViewDelegate> list = self.listVCDict[@(index)];
if (list == nil) {
list = [self.delegate listContainerView:self initListForIndex:index];
}
if (list.listView.superview == nil) {
list.listView.frame = CGRectMake(index*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
[self.scrollView addSubview:list.listView];
self.listVCDict[@(index)] = list;
}
if (list && [list respondsToSelector:@selector(listDidAppear)]) {
[list listDidAppear];
}
}
- (void)listDidDisappear:(NSInteger)index {
id<JXCategoryListContentViewDelegate> list = self.listVCDict[@(index)];
if (list && [list respondsToSelector:@selector(listDidDisappear)]) {
[list listDidDisappear];
}
}
@end
//
// JXCategoryListScrollView.h
// JXCategoryView
//
// Created by jiaxin on 2018/9/12.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
/**
此类已不再维护,推荐使用JXCategoryListContainerView类!!!
*/
@interface JXCategoryListVCContainerView : UIView
@property (nonatomic, weak) UIViewController *parentViewController;
@property (nonatomic, strong, readonly) UIScrollView *scrollView;
@property (nonatomic, strong) NSArray <UIViewController *> *listVCArray;
//这个defaultSelectedIndex仅仅用于触发对应index的数据加载,如果要让categoryView和listView都处于对应的index。还应该添加后面这段代码:self.categoryView.defaultSelectedIndex = n
@property (nonatomic, assign) NSInteger defaultSelectedIndex;
- (void)reloadData;
- (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio;
- (void)didClickSelectedItemAtIndex:(NSInteger)index;
- (void)didScrollSelectedItemAtIndex:(NSInteger)index;
- (void)parentVCWillAppear:(BOOL)animated;
- (void)parentVCDidAppear:(BOOL)animated;
- (void)parentVCWillDisappear:(BOOL)animated;
- (void)parentVCDidDisappear:(BOOL)animated;
@end
//
// JXCategoryListContainerView.m
// JXCategoryView
//
// Created by jiaxin on 2018/9/12.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryListVCContainerView.h"
@interface JXCategoryListVCContainerView () <UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, assign) NSInteger currentIndex;
@property (nonatomic, assign) NSInteger targetIndex;
@end
@implementation JXCategoryListVCContainerView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initializeViews];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self initializeViews];
}
return self;
}
- (void)initializeViews {
_scrollView = [[UIScrollView alloc] init];
self.scrollView.pagingEnabled = YES;
self.scrollView.showsHorizontalScrollIndicator = NO;
[self addSubview:self.scrollView];
}
- (void)reloadData {
[self listVCWillAppear:self.defaultSelectedIndex];
[self listVCDidAppear:self.defaultSelectedIndex];
}
- (void)layoutSubviews {
[super layoutSubviews];
self.scrollView.frame = self.bounds;
//根据新的数据源重新添加listView
for (int i = 0; i < self.listVCArray.count; i ++) {
UIViewController *listVC = self.listVCArray[i];
[listVC willMoveToParentViewController:self.parentViewController];
[self.parentViewController addChildViewController:self.parentViewController];
[listVC didMoveToParentViewController:self.parentViewController];
listVC.view.frame = CGRectMake(i*self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
[self.scrollView addSubview:listVC.view];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width*self.listVCArray.count, self.scrollView.bounds.size.height);
}
- (void)setListVCArray:(NSArray<UIViewController *> *)listVCArray {
for (UIViewController *vc in self.listVCArray) {
[vc.view removeFromSuperview];
}
_listVCArray = listVCArray;
[self setNeedsLayout];
}
- (void)setDefaultSelectedIndex:(NSInteger)defaultSelectedIndex {
_defaultSelectedIndex = defaultSelectedIndex;
self.currentIndex = defaultSelectedIndex;
}
- (void)parentVCWillAppear:(BOOL)animated {
[self listVCWillAppear:self.currentIndex];
}
- (void)parentVCDidAppear:(BOOL)animated {
[self listVCDidAppear:self.currentIndex];
}
- (void)parentVCWillDisappear:(BOOL)animated {
[self listVCWillDisappear:self.currentIndex];
}
- (void)parentVCDidDisappear:(BOOL)animated {
[self listVCDidDisappear:self.currentIndex];
}
- (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio {
NSInteger targetIndex = 0;
if (ratio > 0.5) {
targetIndex = rightIndex;
}else {
targetIndex = leftIndex;
}
if (self.targetIndex != targetIndex) {
[self listVCWillAppear:targetIndex];
[self listVCDidAppear:targetIndex];
//源代码
//[self listVCWillDisappear:self.currentIndex];
//[self listVCDidDisappear:self.currentIndex];
//add by wuna 解决了部分生命周期问题和标题跟页面正确对应问题
if (ratio > 0.5) {
[self listVCWillDisappear:leftIndex];
[self listVCDidDisappear:leftIndex];
}else{
[self listVCWillDisappear:rightIndex];
[self listVCDidDisappear:rightIndex];
}
}
}
- (void)didScrollSelectedItemAtIndex:(NSInteger)index {
}
- (void)didClickSelectedItemAtIndex:(NSInteger)index {
[self listVCWillDisappear:self.currentIndex];
[self listVCDidDisappear:self.currentIndex];
[self listVCWillAppear:index];
[self listVCDidAppear:index];
}
#pragma mark - Private
- (void)listVCWillAppear:(NSInteger)index {
self.targetIndex = index;
UIViewController *vc = self.listVCArray[index];
[vc beginAppearanceTransition:YES animated:YES];
}
- (void)listVCDidAppear:(NSInteger)index {
self.currentIndex = index;
UIViewController *vc = self.listVCArray[index];
[vc endAppearanceTransition];
}
- (void)listVCWillDisappear:(NSInteger)index {
UIViewController *vc = self.listVCArray[index];
[vc beginAppearanceTransition:NO animated:YES];
}
- (void)listVCDidDisappear:(NSInteger)index {
UIViewController *vc = self.listVCArray[index];
[vc endAppearanceTransition];
}
@end
//
// JXCategoryViewDefines.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/17.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
static const CGFloat JXCategoryViewAutomaticDimension = -1;
typedef NS_ENUM(NSUInteger, JXCategoryComponentPosition) {
JXCategoryComponentPosition_Bottom,
JXCategoryComponentPosition_Top,
};
typedef NS_ENUM(NSUInteger, JXCategoryIndicatorScrollStyle) {
JXCategoryIndicatorScrollStyleSimple, //简单滚动,即从当前位置过渡到目标位置
JXCategoryIndicatorScrollStyleSameAsUserScroll, //和用户左右滚动列表时的效果一样
};
//
// UIColor+JXAdd.h
// UI系列测试
//
// Created by jiaxin on 2018/3/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIColor (JXAdd)
@property (nonatomic, assign, readonly) CGFloat jx_red;
@property (nonatomic, assign, readonly) CGFloat jx_green;
@property (nonatomic, assign, readonly) CGFloat jx_blue;
@property (nonatomic, assign, readonly) CGFloat jx_alpha;
@end
//
// UIColor+JXAdd.m
// UI系列测试
//
// Created by jiaxin on 2018/3/21.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "UIColor+JXAdd.h"
@implementation UIColor (JXAdd)
- (CGFloat)jx_red {
CGFloat r = 0, g, b, a;
[self getRed:&r green:&g blue:&b alpha:&a];
return r;
}
- (CGFloat)jx_green {
CGFloat r, g = 0, b, a;
[self getRed:&r green:&g blue:&b alpha:&a];
return g;
}
- (CGFloat)jx_blue {
CGFloat r, g, b = 0, a;
[self getRed:&r green:&g blue:&b alpha:&a];
return b;
}
- (CGFloat)jx_alpha {
return CGColorGetAlpha(self.CGColor);
}
@end
//
// JXCategoryDotCell.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleCell.h"
@interface JXCategoryDotCell : JXCategoryTitleCell
@end
//
// JXCategoryDotCellModel.h
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryTitleCellModel.h"
typedef NS_ENUM(NSUInteger, JXCategoryDotRelativePosition) {
JXCategoryDotRelativePosition_TopLeft = 0,
JXCategoryDotRelativePosition_TopRight,
JXCategoryDotRelativePosition_BottomLeft,
JXCategoryDotRelativePosition_BottomRight,
};
@interface JXCategoryDotCellModel : JXCategoryTitleCellModel
@property (nonatomic, assign) BOOL dotHidden;
@property (nonatomic, assign) JXCategoryDotRelativePosition relativePosition;
@property (nonatomic, assign) CGSize dotSize;
@property (nonatomic, assign) CGFloat dotCornerRadius;
@property (nonatomic, strong) UIColor *dotColor;
@end
//
// JXCategoryDotCellModel.m
// JXCategoryView
//
// Created by jiaxin on 2018/8/20.
// Copyright © 2018年 jiaxin. All rights reserved.
//
#import "JXCategoryDotCellModel.h"
@implementation JXCategoryDotCellModel
@end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment