init
This commit is contained in:
BIN
Example/SubModules/FUBeautyComponent/.DS_Store
vendored
Normal file
BIN
Example/SubModules/FUBeautyComponent/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "FUBeautyComponent"
|
||||
s.version = "1.0"
|
||||
s.license = 'MIT'
|
||||
s.summary = "Beauty component"
|
||||
s.description = "The beauty component of FULiveDemo."
|
||||
s.homepage = "https://github.com/Faceunity/FULiveDemo"
|
||||
s.author = { 'faceunity' => 'dev@faceunity.com' }
|
||||
s.platform = :ios, "12.0"
|
||||
s.source = { "http": "https://github.com/Faceunity/FULiveDemo"}
|
||||
s.source_files = '**/*.{h,m}'
|
||||
s.resources = 'FUBeautyComponent/Resource/**/*.{json}'
|
||||
s.requires_arc = true
|
||||
s.dependency 'FURenderKit'
|
||||
s.dependency 'FUCommonUIComponent'
|
||||
end
|
||||
@@ -0,0 +1,493 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 55;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
E30500B42891364700C9408B /* FUBeautySkinViewModel.h in Headers */ = {isa = PBXBuildFile; fileRef = E30500B22891364700C9408B /* FUBeautySkinViewModel.h */; };
|
||||
E30500B52891364700C9408B /* FUBeautySkinViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E30500B32891364700C9408B /* FUBeautySkinViewModel.m */; };
|
||||
E30500B82891365300C9408B /* FUBeautyShapeViewModel.h in Headers */ = {isa = PBXBuildFile; fileRef = E30500B62891365300C9408B /* FUBeautyShapeViewModel.h */; };
|
||||
E30500B92891365300C9408B /* FUBeautyShapeViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E30500B72891365300C9408B /* FUBeautyShapeViewModel.m */; };
|
||||
E32C6DCE2877DEDC008A9C08 /* FUBeautySkinModel.h in Headers */ = {isa = PBXBuildFile; fileRef = E32C6DCC2877DEDC008A9C08 /* FUBeautySkinModel.h */; };
|
||||
E32C6DCF2877DEDC008A9C08 /* FUBeautySkinModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E32C6DCD2877DEDC008A9C08 /* FUBeautySkinModel.m */; };
|
||||
E32C6DD22877DEEC008A9C08 /* FUBeautyShapeModel.h in Headers */ = {isa = PBXBuildFile; fileRef = E32C6DD02877DEEC008A9C08 /* FUBeautyShapeModel.h */; };
|
||||
E32C6DD32877DEEC008A9C08 /* FUBeautyShapeModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E32C6DD12877DEEC008A9C08 /* FUBeautyShapeModel.m */; };
|
||||
E32C6DD62877E114008A9C08 /* FUBeautyShapeView.h in Headers */ = {isa = PBXBuildFile; fileRef = E32C6DD42877E114008A9C08 /* FUBeautyShapeView.h */; };
|
||||
E32C6DD72877E114008A9C08 /* FUBeautyShapeView.m in Sources */ = {isa = PBXBuildFile; fileRef = E32C6DD52877E114008A9C08 /* FUBeautyShapeView.m */; };
|
||||
E32D08E928758C5600884AE5 /* FUBeautyComponentManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D08E828758C5600884AE5 /* FUBeautyComponentManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
E32D09192876CEF300884AE5 /* FUBeautyFilterViewModel.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D09172876CEF300884AE5 /* FUBeautyFilterViewModel.h */; };
|
||||
E32D091A2876CEF300884AE5 /* FUBeautyFilterViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E32D09182876CEF300884AE5 /* FUBeautyFilterViewModel.m */; };
|
||||
E32D091D2876CF0F00884AE5 /* FUBeautyFilterModel.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D091B2876CF0F00884AE5 /* FUBeautyFilterModel.h */; };
|
||||
E32D091E2876CF0F00884AE5 /* FUBeautyFilterModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E32D091C2876CF0F00884AE5 /* FUBeautyFilterModel.m */; };
|
||||
E32D09222876CFDE00884AE5 /* beauty_filter.json in Resources */ = {isa = PBXBuildFile; fileRef = E32D09212876CFDE00884AE5 /* beauty_filter.json */; };
|
||||
E32D09242876D01C00884AE5 /* beauty_skin.json in Resources */ = {isa = PBXBuildFile; fileRef = E32D09232876D01C00884AE5 /* beauty_skin.json */; };
|
||||
E32D09262876D02E00884AE5 /* beauty_shape.json in Resources */ = {isa = PBXBuildFile; fileRef = E32D09252876D02E00884AE5 /* beauty_shape.json */; };
|
||||
E33834A12861772B0023482D /* FUBeautySkinView.h in Headers */ = {isa = PBXBuildFile; fileRef = E338349F2861772B0023482D /* FUBeautySkinView.h */; };
|
||||
E33834A22861772B0023482D /* FUBeautySkinView.m in Sources */ = {isa = PBXBuildFile; fileRef = E33834A02861772B0023482D /* FUBeautySkinView.m */; };
|
||||
E33834BA2861BE8C0023482D /* FUBeautyFilterView.h in Headers */ = {isa = PBXBuildFile; fileRef = E33834B82861BE8C0023482D /* FUBeautyFilterView.h */; };
|
||||
E33834BB2861BE8C0023482D /* FUBeautyFilterView.m in Sources */ = {isa = PBXBuildFile; fileRef = E33834B92861BE8C0023482D /* FUBeautyFilterView.m */; };
|
||||
E34C47EE285338080040093C /* FUBeautyComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = E34C47ED285338080040093C /* FUBeautyComponent.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
E34C47FC2853381E0040093C /* FUBeautyDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = E34C47F52853381E0040093C /* FUBeautyDefine.h */; };
|
||||
E34C4831285347100040093C /* FUBeautyComponentManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E34C482F285347100040093C /* FUBeautyComponentManager.m */; };
|
||||
E3618FEC28583B9B00E7D8D2 /* FUBeautyDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = E3618FEB28583B9B00E7D8D2 /* FUBeautyDefine.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
E30500B22891364700C9408B /* FUBeautySkinViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautySkinViewModel.h; sourceTree = "<group>"; };
|
||||
E30500B32891364700C9408B /* FUBeautySkinViewModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautySkinViewModel.m; sourceTree = "<group>"; };
|
||||
E30500B62891365300C9408B /* FUBeautyShapeViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautyShapeViewModel.h; sourceTree = "<group>"; };
|
||||
E30500B72891365300C9408B /* FUBeautyShapeViewModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautyShapeViewModel.m; sourceTree = "<group>"; };
|
||||
E32C6DCC2877DEDC008A9C08 /* FUBeautySkinModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautySkinModel.h; sourceTree = "<group>"; };
|
||||
E32C6DCD2877DEDC008A9C08 /* FUBeautySkinModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautySkinModel.m; sourceTree = "<group>"; };
|
||||
E32C6DD02877DEEC008A9C08 /* FUBeautyShapeModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautyShapeModel.h; sourceTree = "<group>"; };
|
||||
E32C6DD12877DEEC008A9C08 /* FUBeautyShapeModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautyShapeModel.m; sourceTree = "<group>"; };
|
||||
E32C6DD42877E114008A9C08 /* FUBeautyShapeView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautyShapeView.h; sourceTree = "<group>"; };
|
||||
E32C6DD52877E114008A9C08 /* FUBeautyShapeView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautyShapeView.m; sourceTree = "<group>"; };
|
||||
E32D08E828758C5600884AE5 /* FUBeautyComponentManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUBeautyComponentManager.h; sourceTree = "<group>"; };
|
||||
E32D09172876CEF300884AE5 /* FUBeautyFilterViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautyFilterViewModel.h; sourceTree = "<group>"; };
|
||||
E32D09182876CEF300884AE5 /* FUBeautyFilterViewModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautyFilterViewModel.m; sourceTree = "<group>"; };
|
||||
E32D091B2876CF0F00884AE5 /* FUBeautyFilterModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautyFilterModel.h; sourceTree = "<group>"; };
|
||||
E32D091C2876CF0F00884AE5 /* FUBeautyFilterModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautyFilterModel.m; sourceTree = "<group>"; };
|
||||
E32D09212876CFDE00884AE5 /* beauty_filter.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = beauty_filter.json; sourceTree = "<group>"; };
|
||||
E32D09232876D01C00884AE5 /* beauty_skin.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = beauty_skin.json; sourceTree = "<group>"; };
|
||||
E32D09252876D02E00884AE5 /* beauty_shape.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = beauty_shape.json; sourceTree = "<group>"; };
|
||||
E338349B286173C10023482D /* FUCommonUIComponent.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FUCommonUIComponent.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E338349F2861772B0023482D /* FUBeautySkinView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautySkinView.h; sourceTree = "<group>"; };
|
||||
E33834A02861772B0023482D /* FUBeautySkinView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautySkinView.m; sourceTree = "<group>"; };
|
||||
E33834B82861BE8C0023482D /* FUBeautyFilterView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautyFilterView.h; sourceTree = "<group>"; };
|
||||
E33834B92861BE8C0023482D /* FUBeautyFilterView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautyFilterView.m; sourceTree = "<group>"; };
|
||||
E34C47EA285338080040093C /* FUBeautyComponent.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FUBeautyComponent.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E34C47ED285338080040093C /* FUBeautyComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUBeautyComponent.h; sourceTree = "<group>"; };
|
||||
E34C47F52853381E0040093C /* FUBeautyDefine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUBeautyDefine.h; sourceTree = "<group>"; };
|
||||
E34C482F285347100040093C /* FUBeautyComponentManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautyComponentManager.m; sourceTree = "<group>"; };
|
||||
E3618FEB28583B9B00E7D8D2 /* FUBeautyDefine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUBeautyDefine.m; sourceTree = "<group>"; };
|
||||
E369F8CF28D851550036AC5A /* FURenderKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FURenderKit.framework; path = ../FULiveDemo/FURenderKit/FURenderKit.framework; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
E34C47E7285338080040093C /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
E338349A286173C10023482D /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E369F8CF28D851550036AC5A /* FURenderKit.framework */,
|
||||
E338349B286173C10023482D /* FUCommonUIComponent.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E34C47E0285338080040093C = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E34C47EC285338080040093C /* FUBeautyComponent */,
|
||||
E34C47EB285338080040093C /* Products */,
|
||||
E338349A286173C10023482D /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E34C47EB285338080040093C /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E34C47EA285338080040093C /* FUBeautyComponent.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E34C47EC285338080040093C /* FUBeautyComponent */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E34C47F42853381E0040093C /* Model */,
|
||||
E34C47F92853381E0040093C /* View */,
|
||||
E34C47F62853381E0040093C /* ViewModel */,
|
||||
E3A787302859AB0000FBDAFF /* Resource */,
|
||||
E34C47F52853381E0040093C /* FUBeautyDefine.h */,
|
||||
E3618FEB28583B9B00E7D8D2 /* FUBeautyDefine.m */,
|
||||
E32D08E828758C5600884AE5 /* FUBeautyComponentManager.h */,
|
||||
E34C482F285347100040093C /* FUBeautyComponentManager.m */,
|
||||
E34C47ED285338080040093C /* FUBeautyComponent.h */,
|
||||
);
|
||||
path = FUBeautyComponent;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E34C47F42853381E0040093C /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E32C6DCC2877DEDC008A9C08 /* FUBeautySkinModel.h */,
|
||||
E32C6DCD2877DEDC008A9C08 /* FUBeautySkinModel.m */,
|
||||
E32C6DD02877DEEC008A9C08 /* FUBeautyShapeModel.h */,
|
||||
E32C6DD12877DEEC008A9C08 /* FUBeautyShapeModel.m */,
|
||||
E32D091B2876CF0F00884AE5 /* FUBeautyFilterModel.h */,
|
||||
E32D091C2876CF0F00884AE5 /* FUBeautyFilterModel.m */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E34C47F62853381E0040093C /* ViewModel */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E30500B22891364700C9408B /* FUBeautySkinViewModel.h */,
|
||||
E30500B32891364700C9408B /* FUBeautySkinViewModel.m */,
|
||||
E30500B62891365300C9408B /* FUBeautyShapeViewModel.h */,
|
||||
E30500B72891365300C9408B /* FUBeautyShapeViewModel.m */,
|
||||
E32D09172876CEF300884AE5 /* FUBeautyFilterViewModel.h */,
|
||||
E32D09182876CEF300884AE5 /* FUBeautyFilterViewModel.m */,
|
||||
);
|
||||
path = ViewModel;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E34C47F92853381E0040093C /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E338349F2861772B0023482D /* FUBeautySkinView.h */,
|
||||
E33834A02861772B0023482D /* FUBeautySkinView.m */,
|
||||
E32C6DD42877E114008A9C08 /* FUBeautyShapeView.h */,
|
||||
E32C6DD52877E114008A9C08 /* FUBeautyShapeView.m */,
|
||||
E33834B82861BE8C0023482D /* FUBeautyFilterView.h */,
|
||||
E33834B92861BE8C0023482D /* FUBeautyFilterView.m */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E3A787302859AB0000FBDAFF /* Resource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E32D09232876D01C00884AE5 /* beauty_skin.json */,
|
||||
E32D09252876D02E00884AE5 /* beauty_shape.json */,
|
||||
E32D09212876CFDE00884AE5 /* beauty_filter.json */,
|
||||
);
|
||||
path = Resource;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
E34C47E5285338080040093C /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E30500B82891365300C9408B /* FUBeautyShapeViewModel.h in Headers */,
|
||||
E30500B42891364700C9408B /* FUBeautySkinViewModel.h in Headers */,
|
||||
E32D08E928758C5600884AE5 /* FUBeautyComponentManager.h in Headers */,
|
||||
E32C6DD22877DEEC008A9C08 /* FUBeautyShapeModel.h in Headers */,
|
||||
E32C6DCE2877DEDC008A9C08 /* FUBeautySkinModel.h in Headers */,
|
||||
E32C6DD62877E114008A9C08 /* FUBeautyShapeView.h in Headers */,
|
||||
E33834BA2861BE8C0023482D /* FUBeautyFilterView.h in Headers */,
|
||||
E32D09192876CEF300884AE5 /* FUBeautyFilterViewModel.h in Headers */,
|
||||
E33834A12861772B0023482D /* FUBeautySkinView.h in Headers */,
|
||||
E34C47FC2853381E0040093C /* FUBeautyDefine.h in Headers */,
|
||||
E32D091D2876CF0F00884AE5 /* FUBeautyFilterModel.h in Headers */,
|
||||
E34C47EE285338080040093C /* FUBeautyComponent.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
E34C47E9285338080040093C /* FUBeautyComponent */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E34C47F1285338080040093C /* Build configuration list for PBXNativeTarget "FUBeautyComponent" */;
|
||||
buildPhases = (
|
||||
E34C47E5285338080040093C /* Headers */,
|
||||
E34C47E6285338080040093C /* Sources */,
|
||||
E34C47E7285338080040093C /* Frameworks */,
|
||||
E34C47E8285338080040093C /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = FUBeautyComponent;
|
||||
productName = FUBeautyComponent;
|
||||
productReference = E34C47EA285338080040093C /* FUBeautyComponent.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
E34C47E1285338080040093C /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastUpgradeCheck = 1330;
|
||||
TargetAttributes = {
|
||||
E34C47E9285338080040093C = {
|
||||
CreatedOnToolsVersion = 13.3.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = E34C47E4285338080040093C /* Build configuration list for PBXProject "FUBeautyComponent" */;
|
||||
compatibilityVersion = "Xcode 13.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
"zh-Hans",
|
||||
Base,
|
||||
);
|
||||
mainGroup = E34C47E0285338080040093C;
|
||||
productRefGroup = E34C47EB285338080040093C /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
E34C47E9285338080040093C /* FUBeautyComponent */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
E34C47E8285338080040093C /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E32D09242876D01C00884AE5 /* beauty_skin.json in Resources */,
|
||||
E32D09222876CFDE00884AE5 /* beauty_filter.json in Resources */,
|
||||
E32D09262876D02E00884AE5 /* beauty_shape.json in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
E34C47E6285338080040093C /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E34C4831285347100040093C /* FUBeautyComponentManager.m in Sources */,
|
||||
E32C6DD32877DEEC008A9C08 /* FUBeautyShapeModel.m in Sources */,
|
||||
E33834A22861772B0023482D /* FUBeautySkinView.m in Sources */,
|
||||
E32D091A2876CEF300884AE5 /* FUBeautyFilterViewModel.m in Sources */,
|
||||
E32D091E2876CF0F00884AE5 /* FUBeautyFilterModel.m in Sources */,
|
||||
E30500B92891365300C9408B /* FUBeautyShapeViewModel.m in Sources */,
|
||||
E30500B52891364700C9408B /* FUBeautySkinViewModel.m in Sources */,
|
||||
E33834BB2861BE8C0023482D /* FUBeautyFilterView.m in Sources */,
|
||||
E32C6DCF2877DEDC008A9C08 /* FUBeautySkinModel.m in Sources */,
|
||||
E32C6DD72877E114008A9C08 /* FUBeautyShapeView.m in Sources */,
|
||||
E3618FEC28583B9B00E7D8D2 /* FUBeautyDefine.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
E34C47EF285338080040093C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.4;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E34C47F0285338080040093C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.4;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E34C47F2285338080040093C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 35A6KD62ZJ;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SRCROOT)/../FULiveDemo/FURenderKit",
|
||||
);
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = faceunity.FUBeautyComponent;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E34C47F3285338080040093C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = 35A6KD62ZJ;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SRCROOT)/../FULiveDemo/FURenderKit",
|
||||
);
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = faceunity.FUBeautyComponent;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
E34C47E4285338080040093C /* Build configuration list for PBXProject "FUBeautyComponent" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E34C47EF285338080040093C /* Debug */,
|
||||
E34C47F0285338080040093C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E34C47F1285338080040093C /* Build configuration list for PBXNativeTarget "FUBeautyComponent" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E34C47F2285338080040093C /* Debug */,
|
||||
E34C47F3285338080040093C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = E34C47E1285338080040093C /* Project object */;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1330"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E34C47E9285338080040093C"
|
||||
BuildableName = "FUBeautyComponent.framework"
|
||||
BlueprintName = "FUBeautyComponent"
|
||||
ReferencedContainer = "container:FUBeautyComponent.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E34C47E9285338080040093C"
|
||||
BuildableName = "FUBeautyComponent.framework"
|
||||
BlueprintName = "FUBeautyComponent"
|
||||
ReferencedContainer = "container:FUBeautyComponent.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
BIN
Example/SubModules/FUBeautyComponent/FUBeautyComponent/.DS_Store
vendored
Normal file
BIN
Example/SubModules/FUBeautyComponent/FUBeautyComponent/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// FUBeautyComponent.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/6/10.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FUBeautyComponentManager.h"
|
||||
|
||||
//! Project version number for FUBeautyComponent.
|
||||
FOUNDATION_EXPORT double FUBeautyComponentVersionNumber;
|
||||
|
||||
//! Project version string for FUBeautyComponent.
|
||||
FOUNDATION_EXPORT const unsigned char FUBeautyComponentVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <FUBeautyComponent/PublicHeader.h>
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// FUBeautyComponentManager.h
|
||||
// FUBeautyComponentManager
|
||||
//
|
||||
// Created by 项林平 on 2022/6/10.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FUBeautyComponentDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
- (void)beautyComponentViewHeightDidChange:(CGFloat)height;
|
||||
|
||||
- (void)beautyComponentDidTouchDownComparison;
|
||||
|
||||
- (void)beautyComponentDidTouchUpComparison;
|
||||
/// 提示
|
||||
- (void)beautyComponentNeedsDisplayPromptContent:(NSString *)content;
|
||||
|
||||
@end
|
||||
|
||||
@interface FUBeautyComponentManager : NSObject
|
||||
|
||||
@property (nonatomic, weak) id<FUBeautyComponentDelegate> delegate;
|
||||
/// 美颜视图总高度
|
||||
@property (nonatomic, assign, readonly) CGFloat componentViewHeight;
|
||||
/// 美颜视图选中功能索引,默认-1,-1表示未选中
|
||||
@property (nonatomic, assign, readonly) NSInteger selectedIndex;
|
||||
|
||||
@property (nonatomic, weak, readonly) UIView *targetView;
|
||||
+ (instancetype)sharedManager;
|
||||
|
||||
/// 销毁
|
||||
+ (void)destory;
|
||||
|
||||
/// 在目标视图中添加美颜组件视图(固定位置为目标视图底部)
|
||||
/// @param view 目标视图
|
||||
- (void)addComponentViewToView:(UIView *)view;
|
||||
|
||||
/// 在父视图中移除美颜组件视图
|
||||
- (void)removeComponentView;
|
||||
|
||||
//设置所有效果为上次数据
|
||||
- (void)beautyStyleSetAllDefaultValues;
|
||||
|
||||
@property (nonatomic, assign)BOOL enableRender;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,329 @@
|
||||
//
|
||||
// FUBeautyComponentManager.m
|
||||
// FUBeautyComponentManager
|
||||
//
|
||||
// Created by 项林平 on 2022/6/10.
|
||||
//
|
||||
|
||||
#import "FUBeautyComponentManager.h"
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
#import "FUBeautySkinView.h"
|
||||
#import "FUBeautyShapeView.h"
|
||||
#import "FUBeautyFilterView.h"
|
||||
|
||||
#import <FUCommonUIComponent/FUCommonUIComponent.h>
|
||||
#import <FURenderKit/FURenderKit.h>
|
||||
|
||||
static FUBeautyComponentManager *beautyComponentManager = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
@interface FUBeautyComponentManager ()<FUSegmentBarDelegate, FUBeautyFilterViewDelegate>
|
||||
|
||||
@property (nonatomic, weak) UIView *targetView;
|
||||
|
||||
@property (nonatomic, strong) FUSegmentBar *categoryView;
|
||||
@property (nonatomic, strong) UIButton *compareButton;
|
||||
|
||||
@property (nonatomic, strong) FUBeautySkinView *beautySkinView;
|
||||
@property (nonatomic, strong) FUBeautyShapeView *beautyShapeView;
|
||||
@property (nonatomic, strong) FUBeautyFilterView *beautyFilterView;
|
||||
|
||||
@property (nonatomic, strong) FUBeautySkinViewModel *beautySkinViewModel;
|
||||
@property (nonatomic, strong) FUBeautyShapeViewModel *beautyShapeViewModel;
|
||||
@property (nonatomic, strong) FUBeautyFilterViewModel *beautyFilterViewModel;
|
||||
|
||||
@property (nonatomic, assign) NSInteger selectedIndex;
|
||||
@property (nonatomic, strong) UIControl *control;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautyComponentManager
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (instancetype)sharedManager {
|
||||
dispatch_once(&onceToken, ^{
|
||||
beautyComponentManager = [[FUBeautyComponentManager alloc] init];
|
||||
beautyComponentManager.enableRender = true;
|
||||
});
|
||||
return beautyComponentManager;
|
||||
}
|
||||
|
||||
+ (void)destory {
|
||||
onceToken = 0;
|
||||
beautyComponentManager = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.selectedIndex = FUBeautyCategoryNone;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Instance methods
|
||||
|
||||
- (void)addComponentViewToView:(UIView *)view {
|
||||
NSAssert(view != nil, @"FUBeautyComponent: view can not be nil!");
|
||||
self.targetView = view;
|
||||
// [self removeComponentView];
|
||||
self.control.frame = view.bounds;
|
||||
[self.targetView addSubview:self.control];
|
||||
// [self.targetView addSubview:self.compareButton];
|
||||
[self.targetView addSubview:self.beautySkinView];
|
||||
[self.targetView addSubview:self.beautyShapeView];
|
||||
[self.targetView addSubview:self.beautyFilterView];
|
||||
[self.targetView addSubview:self.categoryView];
|
||||
if (self.categoryView.selectedIndex < 0) {
|
||||
[self.categoryView selectItemAtIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeComponentView {
|
||||
[self.control removeFromSuperview];
|
||||
// if (self.compareButton.superview) {
|
||||
// [self.compareButton removeFromSuperview];
|
||||
// }
|
||||
if (self.beautySkinView.superview) {
|
||||
[self.beautySkinView removeFromSuperview];
|
||||
}
|
||||
if (self.beautyShapeView.superview) {
|
||||
[self.beautyShapeView removeFromSuperview];
|
||||
}
|
||||
if (self.beautyFilterView.superview) {
|
||||
[self.beautyFilterView removeFromSuperview];
|
||||
}
|
||||
if (self.categoryView.superview) {
|
||||
[self.categoryView removeFromSuperview];
|
||||
}
|
||||
_targetView = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
- (void)controlClick {
|
||||
[self removeComponentView];
|
||||
}
|
||||
|
||||
- (void)showEffectView:(UIView *)view animated:(BOOL)animated completion:(void (^)(void))completion {
|
||||
view.hidden = NO;
|
||||
self.compareButton.hidden = NO;
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.2 animations:^{
|
||||
view.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(view.frame));
|
||||
self.compareButton.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(view.frame));
|
||||
} completion:^(BOOL finished) {
|
||||
!completion ?: completion();
|
||||
}];
|
||||
} else {
|
||||
view.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(view.frame));
|
||||
self.compareButton.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(view.frame));
|
||||
!completion ?: completion();
|
||||
}
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(beautyComponentViewHeightDidChange:)]) {
|
||||
[self.delegate beautyComponentViewHeightDidChange:CGRectGetHeight(view.frame) + CGRectGetHeight(self.categoryView.frame)];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)hideEffectView:(UIView *)view animated:(BOOL)animated completion:(void (^)(void))completion {
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.2 animations:^{
|
||||
view.transform = CGAffineTransformIdentity;
|
||||
} completion:^(BOOL finished) {
|
||||
view.hidden = YES;
|
||||
!completion ?: completion();
|
||||
}];
|
||||
} else {
|
||||
view.transform = CGAffineTransformIdentity;
|
||||
view.hidden = YES;
|
||||
!completion ?: completion();
|
||||
}
|
||||
}
|
||||
|
||||
- (UIView *)showingView {
|
||||
UIView *view;
|
||||
switch (self.selectedIndex) {
|
||||
case FUBeautyCategorySkin:{
|
||||
view = self.beautySkinView;
|
||||
}
|
||||
break;
|
||||
case FUBeautyCategoryShape:{
|
||||
view = self.beautyShapeView;
|
||||
}
|
||||
break;
|
||||
case FUBeautyCategoryFilter:{
|
||||
view = self.beautyFilterView;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
#pragma mark - Event response
|
||||
|
||||
- (void)compareTouchDownAction {
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(beautyComponentDidTouchDownComparison)]) {
|
||||
[self.delegate beautyComponentDidTouchDownComparison];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)compareTouchUpAction {
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(beautyComponentDidTouchUpComparison)]) {
|
||||
[self.delegate beautyComponentDidTouchUpComparison];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FUSegmentBarDelegate
|
||||
|
||||
- (void)segmentBar:(FUSegmentBar *)segmentBar didSelectItemAtIndex:(NSUInteger)index {
|
||||
if(index == 3) {
|
||||
self.enableRender = !self.enableRender;
|
||||
[self hideEffectView:[self showingView] animated:YES completion:^{
|
||||
segmentBar.userInteractionEnabled = YES;
|
||||
}];
|
||||
if (self.enableRender) {
|
||||
[self.categoryView selectItemAtIndex:0];
|
||||
}
|
||||
else {
|
||||
self.selectedIndex = index;
|
||||
}
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(beautyComponentViewHeightDidChange:)]) {
|
||||
[self.delegate beautyComponentViewHeightDidChange:CGRectGetHeight(self.categoryView.frame)];
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (index == self.selectedIndex) {
|
||||
// 隐藏
|
||||
segmentBar.userInteractionEnabled = NO;
|
||||
[self hideEffectView:[self showingView] animated:YES completion:^{
|
||||
segmentBar.userInteractionEnabled = YES;
|
||||
}];
|
||||
self.compareButton.transform = CGAffineTransformIdentity;
|
||||
self.compareButton.hidden = YES;
|
||||
[segmentBar selectItemAtIndex:-1];
|
||||
self.selectedIndex = FUBeautyCategoryNone;
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(beautyComponentViewHeightDidChange:)]) {
|
||||
[self.delegate beautyComponentViewHeightDidChange:CGRectGetHeight(self.categoryView.frame)];
|
||||
}
|
||||
} else {
|
||||
segmentBar.userInteractionEnabled = NO;
|
||||
if (self.selectedIndex > FUBeautyCategoryNone) {
|
||||
[self hideEffectView:[self showingView] animated:NO completion:nil];
|
||||
}
|
||||
self.selectedIndex = index;
|
||||
[self showEffectView:[self showingView] animated:YES completion:^{
|
||||
segmentBar.userInteractionEnabled = YES;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FUBeautyFilterViewDelegate
|
||||
|
||||
- (void)beautyFilterViewDidChangeFilter:(NSString *)name {
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(beautyComponentNeedsDisplayPromptContent:)]) {
|
||||
[self.delegate beautyComponentNeedsDisplayPromptContent:name];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)beautyStyleSetAllDefaultValues {
|
||||
// 恢复美肤、美型、滤镜效果
|
||||
[self.beautySkinViewModel setAllSkinValues];
|
||||
[self.beautyShapeViewModel setAllShapeValues];
|
||||
[self.beautyFilterViewModel setCurrentFilter];
|
||||
}
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
- (FUSegmentBar *)categoryView {
|
||||
if (!_categoryView) {
|
||||
NSArray<NSString *> *categories = @[FUBeautyStringWithKey(@"skin"), FUBeautyStringWithKey(@"shape"), FUBeautyStringWithKey(@"filter")];
|
||||
FUSegmentBarConfigurations *configurations = [[FUSegmentBarConfigurations alloc] init];
|
||||
configurations.titleFont = [UIFont systemFontOfSize:15];
|
||||
_categoryView = [[FUSegmentBar alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.targetView.bounds) - FUBeautyHeightIncludeBottomSafeArea(FUBeautyCategoryViewHeight), CGRectGetWidth(self.targetView.bounds), FUBeautyHeightIncludeBottomSafeArea(FUBeautyCategoryViewHeight)) titles:categories configuration:configurations];
|
||||
_categoryView.delegate = self;
|
||||
}
|
||||
return _categoryView;
|
||||
}
|
||||
|
||||
//- (UIButton *)compareButton {
|
||||
// if (!_compareButton) {
|
||||
// _compareButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
// _compareButton.frame = CGRectMake(15, CGRectGetMinY(self.categoryView.frame) - 54, 44, 44);
|
||||
// [_compareButton setImage:[UIImage imageNamed:@"compare_item"] forState:UIControlStateNormal];
|
||||
// [_compareButton addTarget:self action:@selector(compareTouchDownAction) forControlEvents:UIControlEventTouchDown];
|
||||
// [_compareButton addTarget:self action:@selector(compareTouchUpAction) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
|
||||
// _compareButton.hidden = YES;
|
||||
// }
|
||||
// return _compareButton;
|
||||
//}
|
||||
|
||||
- (FUBeautySkinView *)beautySkinView {
|
||||
if (!_beautySkinView) {
|
||||
_beautySkinView = [[FUBeautySkinView alloc] initWithFrame:CGRectMake(0, CGRectGetMinY(self.categoryView.frame), CGRectGetWidth(self.targetView.bounds), FUBeautyFunctionViewOverallHeight) viewModel:self.beautySkinViewModel];
|
||||
_beautySkinView.hidden = YES;
|
||||
}
|
||||
return _beautySkinView;
|
||||
}
|
||||
|
||||
- (FUBeautyShapeView *)beautyShapeView {
|
||||
if (!_beautyShapeView) {
|
||||
_beautyShapeView = [[FUBeautyShapeView alloc] initWithFrame:CGRectMake(0, CGRectGetMinY(self.categoryView.frame), CGRectGetWidth(self.targetView.bounds), FUBeautyFunctionViewOverallHeight) viewModel:self.beautyShapeViewModel];
|
||||
_beautyShapeView.hidden = YES;
|
||||
}
|
||||
return _beautyShapeView;
|
||||
}
|
||||
|
||||
- (FUBeautyFilterView *)beautyFilterView {
|
||||
if (!_beautyFilterView) {
|
||||
_beautyFilterView = [[FUBeautyFilterView alloc] initWithFrame:CGRectMake(0, CGRectGetMinY(self.categoryView.frame), CGRectGetWidth(self.targetView.bounds), FUBeautyFunctionViewOverallHeight) viewModel:self.beautyFilterViewModel];
|
||||
_beautyFilterView.hidden = YES;
|
||||
_beautyFilterView.delegate = self;
|
||||
}
|
||||
return _beautyFilterView;
|
||||
}
|
||||
|
||||
- (FUBeautySkinViewModel *)beautySkinViewModel {
|
||||
if (!_beautySkinViewModel) {
|
||||
_beautySkinViewModel = [[FUBeautySkinViewModel alloc] init];
|
||||
}
|
||||
return _beautySkinViewModel;
|
||||
}
|
||||
|
||||
- (FUBeautyShapeViewModel *)beautyShapeViewModel {
|
||||
if (!_beautyShapeViewModel) {
|
||||
_beautyShapeViewModel = [[FUBeautyShapeViewModel alloc] init];
|
||||
}
|
||||
return _beautyShapeViewModel;
|
||||
}
|
||||
|
||||
- (FUBeautyFilterViewModel *)beautyFilterViewModel {
|
||||
if (!_beautyFilterViewModel) {
|
||||
_beautyFilterViewModel = [[FUBeautyFilterViewModel alloc] init];
|
||||
}
|
||||
return _beautyFilterViewModel;
|
||||
}
|
||||
|
||||
- (CGFloat)componentViewHeight {
|
||||
if (self.selectedIndex == FUBeautyCategoryNone) {
|
||||
return FUBeautyHeightIncludeBottomSafeArea(FUBeautyCategoryViewHeight);
|
||||
} else {
|
||||
return FUBeautyHeightIncludeBottomSafeArea(FUBeautyCategoryViewHeight) + FUBeautyFunctionViewOverallHeight;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIControl *)control {
|
||||
if (!_control) {
|
||||
_control = [[UIControl alloc] init];
|
||||
_control.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1];
|
||||
[_control addTarget:self action:@selector(controlClick) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _control;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// FUBeautyDefine.h
|
||||
// FUBeautyUIComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/6/9.
|
||||
//
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#ifndef FUBeautyDefine_h
|
||||
#define FUBeautyDefine_h
|
||||
|
||||
|
||||
#define FUBeautyStringWithKey(aKey) NSLocalizedString(aKey, nil)
|
||||
|
||||
#pragma mark - Const
|
||||
|
||||
extern const CGFloat FUBeautyCategoryViewHeight;
|
||||
|
||||
extern const CGFloat FUBeautyFunctionViewOverallHeight;
|
||||
|
||||
extern const CGFloat FUBeautyFunctionSliderHeight;
|
||||
|
||||
extern NSString * const FUPersistentBeautySkinKey;
|
||||
|
||||
extern NSString * const FUPersistentBeautyShapeKey;
|
||||
|
||||
extern NSString * const FUPersistentBeautyFilterKey;
|
||||
|
||||
extern NSString * const FUPersistentBeautySelectedFilterIndexKey;
|
||||
|
||||
|
||||
#pragma mark - Enum
|
||||
|
||||
typedef NS_ENUM(NSInteger, FUBeautyCategory) {
|
||||
FUBeautyCategoryNone = -1,
|
||||
FUBeautyCategorySkin = 0, //美肤
|
||||
FUBeautyCategoryShape = 1, //美型
|
||||
FUBeautyCategoryFilter = 2 //滤镜
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, FUBeautySkin) {
|
||||
FUBeautySkinBlurLevel = 0,
|
||||
FUBeautySkinColorLevel,
|
||||
FUBeautySkinRedLevel,
|
||||
FUBeautySkinSharpen,
|
||||
FUBeautySkinFaceThreed,
|
||||
FUBeautySkinEyeBright,
|
||||
FUBeautySkinToothWhiten,
|
||||
FUBeautySkinRemovePouchStrength,
|
||||
FUBeautySkinRemoveNasolabialFoldsStrength
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, FUBeautyShape) {
|
||||
FUBeautyShapeCheekThinning = 0,
|
||||
FUBeautyShapeCheekV,
|
||||
FUBeautyShapeCheekNarrow,
|
||||
FUBeautyShapeCheekShort,
|
||||
FUBeautyShapeCheekSmall,
|
||||
FUBeautyShapeCheekbones,
|
||||
FUBeautyShapeLowerJaw,
|
||||
FUBeautyShapeEyeEnlarging,
|
||||
FUBeautyShapeEyeCircle,
|
||||
FUBeautyShapeChin,
|
||||
FUBeautyShapeForehead,
|
||||
FUBeautyShapeNose,
|
||||
FUBeautyShapeMouth,
|
||||
FUBeautyShapeLipThick,
|
||||
FUBeautyShapeEyeHeight,
|
||||
FUBeautyShapeCanthus,
|
||||
FUBeautyShapeEyeLid,
|
||||
FUBeautyShapeEyeSpace,
|
||||
FUBeautyShapeEyeRotate,
|
||||
FUBeautyShapeLongNose,
|
||||
FUBeautyShapePhiltrum,
|
||||
FUBeautyShapeSmile,
|
||||
FUBeautyShapeBrowHeight,
|
||||
FUBeautyShapeBrowSpace,
|
||||
FUBeautyShapeBrowThick
|
||||
};
|
||||
|
||||
#pragma mark - Inline methods
|
||||
|
||||
static inline CGFloat FUBeautyHeightIncludeBottomSafeArea(CGFloat height) {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
height += [UIApplication sharedApplication].delegate.window.safeAreaInsets.bottom;
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
static inline UIImage * FUBeautyImageNamed(NSString *name) {
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"FUBeautyComponent" ofType:@"framework" inDirectory:@"Frameworks"];
|
||||
NSBundle *bundle = [NSBundle bundleWithPath:path];
|
||||
return [UIImage imageNamed:name inBundle:bundle compatibleWithTraitCollection:nil];;
|
||||
}
|
||||
|
||||
#endif /* FUBeautyDefine_h */
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// FUBeautyDefine.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/6/14.
|
||||
//
|
||||
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
const CGFloat FUBeautyCategoryViewHeight = 49.f;
|
||||
|
||||
const CGFloat FUBeautyFunctionViewOverallHeight = 141.f;
|
||||
|
||||
const CGFloat FUBeautyFunctionSliderHeight = 30.f;
|
||||
|
||||
NSString * const FUPersistentBeautySkinKey = @"FUPersistentBeautySkin";
|
||||
|
||||
NSString * const FUPersistentBeautyShapeKey = @"FUPersistentBeautyShape";
|
||||
|
||||
NSString * const FUPersistentBeautyFilterKey = @"FUPersistentBeautyFilter";
|
||||
|
||||
NSString * const FUPersistentBeautySelectedFilterIndexKey = @"FUPersistentBeautySelectedFilterIndex";
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// FUBeautyFilterModel.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/7.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FUBeautyFilterModel : NSObject
|
||||
|
||||
@property (nonatomic, assign) NSInteger filterIndex;
|
||||
@property (nonatomic, copy) NSString *filterName;
|
||||
@property (nonatomic, assign) double filterLevel;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// FUBeautyFilterModel.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/7.
|
||||
//
|
||||
|
||||
#import "FUBeautyFilterModel.h"
|
||||
|
||||
@implementation FUBeautyFilterModel
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// FUBeautyShapeModel.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/8.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FUBeautyShapeModel : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSString *name;
|
||||
/// 美型类型
|
||||
@property (nonatomic, assign) FUBeautyShape type;
|
||||
/// 当前值
|
||||
@property (nonatomic) double currentValue;
|
||||
/// 默认值
|
||||
@property (nonatomic) double defaultValue;
|
||||
/// 默认值是否中位数
|
||||
@property (nonatomic, assign) BOOL defaultValueInMiddle;
|
||||
/// 是否区分设备性能
|
||||
@property (nonatomic, assign) BOOL differentiateDevicePerformance;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// FUBeautyShapeModel.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/8.
|
||||
//
|
||||
|
||||
#import "FUBeautyShapeModel.h"
|
||||
|
||||
@implementation FUBeautyShapeModel
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// FUBeautySkinModel.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/8.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FUBeautySkinModel : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSString *name;
|
||||
/// 美肤类型
|
||||
@property (nonatomic, assign) FUBeautySkin type;
|
||||
/// 当前值
|
||||
@property (nonatomic, assign) double currentValue;
|
||||
/// 默认值
|
||||
@property (nonatomic, assign) double defaultValue;
|
||||
/// 默认值是否中位数
|
||||
@property (nonatomic, assign) BOOL defaultValueInMiddle;
|
||||
/// 实际值对应0.0-1.0的倍率
|
||||
@property (nonatomic, assign) NSInteger ratio;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// FUBeautySkinModel.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/8.
|
||||
//
|
||||
|
||||
#import "FUBeautySkinModel.h"
|
||||
|
||||
@implementation FUBeautySkinModel
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,322 @@
|
||||
[
|
||||
{
|
||||
"filterIndex":0,
|
||||
"filterName":"origin",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":1,
|
||||
"filterName":"ziran1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":2,
|
||||
"filterName":"ziran2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":3,
|
||||
"filterName":"ziran3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":4,
|
||||
"filterName":"ziran4",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":5,
|
||||
"filterName":"ziran5",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":6,
|
||||
"filterName":"ziran6",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":7,
|
||||
"filterName":"ziran7",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":8,
|
||||
"filterName":"ziran8",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":9,
|
||||
"filterName":"zhiganhui1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":10,
|
||||
"filterName":"zhiganhui2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":11,
|
||||
"filterName":"zhiganhui3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":12,
|
||||
"filterName":"zhiganhui4",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":13,
|
||||
"filterName":"zhiganhui5",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":14,
|
||||
"filterName":"zhiganhui6",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":15,
|
||||
"filterName":"zhiganhui7",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":16,
|
||||
"filterName":"zhiganhui8",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":17,
|
||||
"filterName":"mitao1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":18,
|
||||
"filterName":"mitao2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":19,
|
||||
"filterName":"mitao3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":20,
|
||||
"filterName":"mitao4",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":21,
|
||||
"filterName":"mitao5",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":22,
|
||||
"filterName":"mitao6",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":23,
|
||||
"filterName":"mitao7",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":24,
|
||||
"filterName":"mitao8",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":25,
|
||||
"filterName":"bailiang1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":26,
|
||||
"filterName":"bailiang2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":27,
|
||||
"filterName":"bailiang3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":28,
|
||||
"filterName":"bailiang4",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":29,
|
||||
"filterName":"bailiang5",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":30,
|
||||
"filterName":"bailiang6",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":31,
|
||||
"filterName":"bailiang7",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":32,
|
||||
"filterName":"fennen1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":33,
|
||||
"filterName":"fennen2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":34,
|
||||
"filterName":"fennen3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":35,
|
||||
"filterName":"fennen5",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":36,
|
||||
"filterName":"fennen6",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":37,
|
||||
"filterName":"fennen7",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":38,
|
||||
"filterName":"fennen8",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":39,
|
||||
"filterName":"lengsediao1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":40,
|
||||
"filterName":"lengsediao2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":41,
|
||||
"filterName":"lengsediao3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":42,
|
||||
"filterName":"lengsediao4",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":43,
|
||||
"filterName":"lengsediao7",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":44,
|
||||
"filterName":"lengsediao8",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":45,
|
||||
"filterName":"lengsediao11",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":46,
|
||||
"filterName":"nuansediao1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":47,
|
||||
"filterName":"nuansediao2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":48,
|
||||
"filterName":"gexing1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":49,
|
||||
"filterName":"gexing2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":50,
|
||||
"filterName":"gexing3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":51,
|
||||
"filterName":"gexing4",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":52,
|
||||
"filterName":"gexing5",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":53,
|
||||
"filterName":"gexing7",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":54,
|
||||
"filterName":"gexing10",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":55,
|
||||
"filterName":"gexing11",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":56,
|
||||
"filterName":"xiaoqingxin1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":57,
|
||||
"filterName":"xiaoqingxin3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":58,
|
||||
"filterName":"xiaoqingxin4",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":59,
|
||||
"filterName":"xiaoqingxin6",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":60,
|
||||
"filterName":"heibai1",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":61,
|
||||
"filterName":"heibai2",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":62,
|
||||
"filterName":"heibai3",
|
||||
"filterLevel":0.4
|
||||
},
|
||||
{
|
||||
"filterIndex":63,
|
||||
"filterName":"heibai4",
|
||||
"filterLevel":0.4
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,202 @@
|
||||
[
|
||||
{
|
||||
"name":"瘦脸",
|
||||
"type":0,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"v脸",
|
||||
"type":1,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"窄脸",
|
||||
"type":2,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"短脸",
|
||||
"type":3,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"小脸",
|
||||
"type":4,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"瘦颧骨",
|
||||
"type":5,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"瘦下颌骨",
|
||||
"type":6,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"大眼",
|
||||
"type":7,
|
||||
"currentValue":0.4,
|
||||
"defaultValue":0.4,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"圆眼",
|
||||
"type":8,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"下巴",
|
||||
"type":9,
|
||||
"currentValue":0.3,
|
||||
"defaultValue":0.3,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"额头",
|
||||
"type":10,
|
||||
"currentValue":0.3,
|
||||
"defaultValue":0.3,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"瘦鼻",
|
||||
"type":11,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"嘴型",
|
||||
"type":12,
|
||||
"currentValue":0.4,
|
||||
"defaultValue":0.4,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"嘴唇厚度",
|
||||
"type":13,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":true
|
||||
},
|
||||
{
|
||||
"name":"眼睛位置",
|
||||
"type":14,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":true
|
||||
},
|
||||
{
|
||||
"name":"开眼角",
|
||||
"type":15,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"眼睑下至",
|
||||
"type":16,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":true
|
||||
},
|
||||
{
|
||||
"name":"眼距",
|
||||
"type":17,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"眼睛角度",
|
||||
"type":18,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"长鼻",
|
||||
"type":19,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"缩人中",
|
||||
"type":20,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"微笑嘴角",
|
||||
"type":21,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"differentiateDevicePerformance":false
|
||||
},
|
||||
{
|
||||
"name":"眉毛上下",
|
||||
"type":22,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":true
|
||||
},
|
||||
{
|
||||
"name":"眉间距",
|
||||
"type":23,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":true
|
||||
},
|
||||
{
|
||||
"name":"眉毛粗细",
|
||||
"type":24,
|
||||
"currentValue":0.5,
|
||||
"defaultValue":0.5,
|
||||
"defaultValueInMiddle":true,
|
||||
"differentiateDevicePerformance":true
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,74 @@
|
||||
[
|
||||
{
|
||||
"name":"磨皮",
|
||||
"type":0,
|
||||
"currentValue":2,
|
||||
"defaultValue":2,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":6
|
||||
},
|
||||
{
|
||||
"name":"美白",
|
||||
"type":1,
|
||||
"currentValue":0.3,
|
||||
"defaultValue":0.3,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":1
|
||||
},
|
||||
{
|
||||
"name":"红润",
|
||||
"type":2,
|
||||
"currentValue":0.3,
|
||||
"defaultValue":0.3,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":1
|
||||
},
|
||||
{
|
||||
"name":"锐化",
|
||||
"type":3,
|
||||
"currentValue":0.2,
|
||||
"defaultValue":0.2,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":1
|
||||
},
|
||||
{
|
||||
"name":"五官立体",
|
||||
"type":4,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":1
|
||||
},
|
||||
{
|
||||
"name":"亮眼",
|
||||
"type":5,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":1
|
||||
},
|
||||
{
|
||||
"name":"美牙",
|
||||
"type":6,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":1
|
||||
},
|
||||
{
|
||||
"name":"去黑眼圈",
|
||||
"type":7,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":1
|
||||
},
|
||||
{
|
||||
"name":"去法令纹",
|
||||
"type":8,
|
||||
"currentValue":0.0,
|
||||
"defaultValue":0.0,
|
||||
"defaultValueInMiddle":false,
|
||||
"ratio":1
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// FUBeautyFilterView.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/6/21.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "FUBeautyFilterViewModel.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FUBeautyFilterViewDelegate <NSObject>
|
||||
|
||||
/// 滤镜变化
|
||||
- (void)beautyFilterViewDidChangeFilter:(NSString *)name;
|
||||
|
||||
@end
|
||||
|
||||
@interface FUBeautyFilterView : UIView
|
||||
|
||||
@property (nonatomic, weak) id<FUBeautyFilterViewDelegate> delegate;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautyFilterViewModel *)viewModel;
|
||||
|
||||
@end
|
||||
|
||||
@interface FUBeautyFilterCell : UICollectionViewCell
|
||||
|
||||
@property (nonatomic, strong, readonly) UIImageView *imageView;
|
||||
@property (nonatomic, strong, readonly) UILabel *textLabel;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,201 @@
|
||||
//
|
||||
// FUBeautyFilterView.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/6/21.
|
||||
//
|
||||
|
||||
#import "FUBeautyFilterView.h"
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
#import <FUCommonUIComponent/FUSlider.h>
|
||||
|
||||
static NSString * const kFUBeautyFilterCellIdentifier = @"FUBeautyFilterCell";
|
||||
|
||||
@interface FUBeautyFilterView ()<UICollectionViewDataSource, UICollectionViewDelegate>
|
||||
|
||||
@property (nonatomic, strong) FUSlider *filterSlider;
|
||||
|
||||
@property (nonatomic, strong) UICollectionView *filterCollectionView;
|
||||
|
||||
@property (nonatomic, strong) FUBeautyFilterViewModel *viewModel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautyFilterView
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
return [self initWithFrame:frame viewModel:[[FUBeautyFilterViewModel alloc] init]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautyFilterViewModel *)viewModel {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
self.viewModel = viewModel;
|
||||
[self configureUI];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - UI
|
||||
|
||||
- (void)configureUI {
|
||||
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
|
||||
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
|
||||
effectView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
|
||||
[self addSubview:effectView];
|
||||
|
||||
[self addSubview:self.filterSlider];
|
||||
[self addSubview:self.filterCollectionView];
|
||||
NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:self.filterCollectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
|
||||
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:self.filterCollectionView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
|
||||
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:self.filterCollectionView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:self.filterCollectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:98];
|
||||
[self addConstraints:@[bottom, leading, trailing]];
|
||||
[self.filterCollectionView addConstraint:height];
|
||||
// 默认选中
|
||||
[self.filterCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.viewModel.selectedIndex inSection:0] animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
|
||||
self.filterSlider.hidden = self.viewModel.selectedIndex < 1;
|
||||
if (!self.filterSlider.hidden) {
|
||||
self.filterSlider.value = self.viewModel.beautyFilters[self.viewModel.selectedIndex].filterLevel;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Event response
|
||||
|
||||
- (void)sliderValueChanged {
|
||||
[self.viewModel setFilterValue:self.filterSlider.value];
|
||||
}
|
||||
|
||||
#pragma mark - Collection view data source
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||
return self.viewModel.beautyFilters.count;
|
||||
}
|
||||
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
FUBeautyFilterCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFUBeautyFilterCellIdentifier forIndexPath:indexPath];
|
||||
FUBeautyFilterModel *filter = self.viewModel.beautyFilters[indexPath.item];
|
||||
cell.imageView.image = [UIImage imageNamed:filter.filterName];
|
||||
cell.textLabel.text = FUBeautyStringWithKey(filter.filterName);
|
||||
return cell;
|
||||
}
|
||||
|
||||
#pragma mark - Collection view delegate
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (self.viewModel.selectedIndex == indexPath.item) {
|
||||
return;
|
||||
}
|
||||
self.filterSlider.hidden = indexPath.item < 1;
|
||||
if (!self.filterSlider.hidden) {
|
||||
self.filterSlider.value = self.viewModel.beautyFilters[indexPath.item].filterLevel;
|
||||
}
|
||||
self.viewModel.selectedIndex = indexPath.item;
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(beautyFilterViewDidChangeFilter:)]) {
|
||||
[self.delegate beautyFilterViewDidChangeFilter:FUBeautyStringWithKey(self.viewModel.beautyFilters[indexPath.item].filterName)];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
- (FUSlider *)filterSlider {
|
||||
if (!_filterSlider) {
|
||||
_filterSlider = [[FUSlider alloc] initWithFrame:CGRectMake(56, 16, CGRectGetWidth(self.frame) - 112, 30)];
|
||||
_filterSlider.bidirection = NO;
|
||||
_filterSlider.hidden = YES;
|
||||
[_filterSlider addTarget:self action:@selector(sliderValueChanged) forControlEvents:UIControlEventValueChanged];
|
||||
}
|
||||
return _filterSlider;
|
||||
}
|
||||
|
||||
- (UICollectionView *)filterCollectionView {
|
||||
if (!_filterCollectionView) {
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
||||
layout.itemSize = CGSizeMake(54, 70);
|
||||
layout.minimumLineSpacing = 16;
|
||||
layout.minimumInteritemSpacing = 50;
|
||||
layout.sectionInset = UIEdgeInsetsMake(16, 18, 10, 18);
|
||||
_filterCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
_filterCollectionView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
_filterCollectionView.backgroundColor = [UIColor clearColor];
|
||||
_filterCollectionView.showsHorizontalScrollIndicator = NO;
|
||||
_filterCollectionView.dataSource = self;
|
||||
_filterCollectionView.delegate = self;
|
||||
[_filterCollectionView registerClass:[FUBeautyFilterCell class] forCellWithReuseIdentifier:kFUBeautyFilterCellIdentifier];
|
||||
}
|
||||
return _filterCollectionView;
|
||||
}
|
||||
|
||||
- (FUBeautyFilterViewModel *)viewModel {
|
||||
if (!_viewModel) {
|
||||
_viewModel = [[FUBeautyFilterViewModel alloc] init];
|
||||
}
|
||||
return _viewModel;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface FUBeautyFilterCell ()
|
||||
|
||||
@property (nonatomic, strong) UIImageView *imageView;
|
||||
@property (nonatomic, strong) UILabel *textLabel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautyFilterCell
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self.contentView addSubview:self.imageView];
|
||||
NSLayoutConstraint *imageTop = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageLeading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageTrailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageHeight = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
|
||||
[self.contentView addConstraints:@[imageTop, imageLeading, imageTrailing]];
|
||||
[self.imageView addConstraint:imageHeight];
|
||||
|
||||
[self.contentView addSubview:self.textLabel];
|
||||
NSLayoutConstraint *textTop = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeBottom multiplier:1 constant:2];
|
||||
NSLayoutConstraint *textLeading = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
|
||||
NSLayoutConstraint *textTrailing = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
[self.contentView addConstraints:@[textTop, textLeading, textTrailing]];
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSelected:(BOOL)selected {
|
||||
[super setSelected:selected];
|
||||
self.imageView.layer.borderWidth = selected ? 2 : 0;
|
||||
self.imageView.layer.borderColor = selected ? [UIColor colorWithRed:103/255.0 green:195/255.0 blue:103/255.0 alpha:1].CGColor : [UIColor clearColor].CGColor;
|
||||
self.textLabel.textColor = selected ? [UIColor colorWithRed:103/255.0 green:195/255.0 blue:103/255.0 alpha:1] : [UIColor whiteColor];
|
||||
}
|
||||
|
||||
- (UIImageView *)imageView {
|
||||
if (!_imageView) {
|
||||
_imageView = [[UIImageView alloc] init];
|
||||
_imageView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
_imageView.layer.masksToBounds = YES;
|
||||
_imageView.layer.cornerRadius = 3.f;
|
||||
}
|
||||
return _imageView;
|
||||
}
|
||||
|
||||
- (UILabel *)textLabel {
|
||||
if (!_textLabel) {
|
||||
_textLabel = [[UILabel alloc] init];
|
||||
_textLabel.textColor = [UIColor whiteColor];
|
||||
_textLabel.font = [UIFont systemFontOfSize:14];
|
||||
_textLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_textLabel.adjustsFontSizeToFitWidth = YES;
|
||||
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _textLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// FUBeautyShapeView.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/8.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "FUBeautyShapeViewModel.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FUBeautyShapeView : UIView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautyShapeViewModel *)viewModel;
|
||||
|
||||
@end
|
||||
|
||||
@interface FUBeautyShapeCell : UICollectionViewCell
|
||||
|
||||
@property (nonatomic, strong, readonly) UIImageView *imageView;
|
||||
|
||||
@property (nonatomic, strong, readonly) UILabel *textLabel;
|
||||
/// 是否允许选择
|
||||
@property (nonatomic, assign) BOOL disabled;
|
||||
|
||||
@property (nonatomic, assign) BOOL defaultInMiddle;
|
||||
|
||||
@property (nonatomic, assign) double currentValue;
|
||||
|
||||
@property (nonatomic, assign) double defaultValue;
|
||||
|
||||
@property (nonatomic, copy) NSString *imageName;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,299 @@
|
||||
//
|
||||
// FUBeautyShapeView.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/8.
|
||||
//
|
||||
|
||||
#import "FUBeautyShapeView.h"
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
#import <FUCommonUIComponent/FUCommonUIComponent.h>
|
||||
|
||||
static NSString * const kFUBeautyShapeCellIdentifier = @"FUBeautyShapeCell";
|
||||
|
||||
@interface FUBeautyShapeView ()<UICollectionViewDataSource, UICollectionViewDelegate>
|
||||
|
||||
@property (nonatomic, strong) UICollectionView *shapeCollectionView;
|
||||
/// 程度调节
|
||||
@property (nonatomic, strong) FUSlider *slider;
|
||||
/// 恢复按钮
|
||||
@property (nonatomic, strong) FUSquareButton *recoverButton;
|
||||
|
||||
@property (nonatomic, strong) FUBeautyShapeViewModel *viewModel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautyShapeView
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
return [self initWithFrame:frame viewModel:[[FUBeautyShapeViewModel alloc] init]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautyShapeViewModel *)viewModel {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
self.viewModel = viewModel;
|
||||
[self configureUI];
|
||||
[self refreshSubviews];
|
||||
[self collectionView:self.shapeCollectionView didSelectItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - UI
|
||||
|
||||
- (void)configureUI {
|
||||
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
|
||||
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
|
||||
effectView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
|
||||
[self addSubview:effectView];
|
||||
|
||||
[self addSubview:self.slider];
|
||||
[self addSubview:self.recoverButton];
|
||||
NSLayoutConstraint *recoverLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:17];
|
||||
NSLayoutConstraint *recoverBottomConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:-6];
|
||||
NSLayoutConstraint *recoverWidthConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:44];
|
||||
NSLayoutConstraint *recoverHeightConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:74];
|
||||
|
||||
[self addConstraints:@[recoverLeadingConstraint, recoverBottomConstraint]];
|
||||
[self.recoverButton addConstraints:@[recoverWidthConstraint, recoverHeightConstraint]];
|
||||
|
||||
// 分割线
|
||||
UIView *verticalLine = [[UIView alloc] init];
|
||||
verticalLine.backgroundColor = [UIColor colorWithRed:229/255.f green:229/255.f blue:229/255.f alpha:0.2];
|
||||
verticalLine.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:verticalLine];
|
||||
NSLayoutConstraint *lineLeadingConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.recoverButton attribute:NSLayoutAttributeTrailing multiplier:1 constant:14];
|
||||
NSLayoutConstraint *lineCenterYConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.recoverButton attribute:NSLayoutAttributeCenterY multiplier:1 constant:-15];
|
||||
NSLayoutConstraint *lineWidthConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:1];
|
||||
NSLayoutConstraint *lineHeightConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:24];
|
||||
[self addConstraints:@[lineLeadingConstraint, lineCenterYConstraint]];
|
||||
[verticalLine addConstraints:@[lineWidthConstraint, lineHeightConstraint]];
|
||||
|
||||
[self addSubview:self.shapeCollectionView];
|
||||
NSLayoutConstraint *collectionLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.shapeCollectionView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:76];
|
||||
NSLayoutConstraint *collectionTrailingConstraint = [NSLayoutConstraint constraintWithItem:self.shapeCollectionView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
NSLayoutConstraint *collectionBottomConstraint = [NSLayoutConstraint constraintWithItem:self.shapeCollectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
|
||||
NSLayoutConstraint *collectionHeightConstraint = [NSLayoutConstraint constraintWithItem:self.shapeCollectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:98];
|
||||
[self addConstraints:@[collectionLeadingConstraint, collectionTrailingConstraint, collectionBottomConstraint]];
|
||||
[self.shapeCollectionView addConstraint:collectionHeightConstraint];
|
||||
}
|
||||
|
||||
- (void)refreshSubviews {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.viewModel.isDefaultValue) {
|
||||
self.recoverButton.alpha = 0.6;
|
||||
self.recoverButton.userInteractionEnabled = NO;
|
||||
} else {
|
||||
self.recoverButton.alpha = 1;
|
||||
self.recoverButton.userInteractionEnabled = YES;
|
||||
}
|
||||
if (!self.slider.hidden && self.viewModel.selectedIndex >= 0) {
|
||||
self.slider.bidirection = self.viewModel.beautyShapes[self.viewModel.selectedIndex].defaultValueInMiddle;
|
||||
self.slider.value = self.viewModel.beautyShapes[self.viewModel.selectedIndex].currentValue;
|
||||
}
|
||||
[self.shapeCollectionView reloadData];
|
||||
if (self.viewModel.selectedIndex >= 0) {
|
||||
[self.shapeCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.viewModel.selectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Event response
|
||||
|
||||
- (void)recoverAction {
|
||||
[FUAlertManager showAlertWithTitle:nil message:FUBeautyStringWithKey(@"是否将所有参数恢复到默认值") cancel:FUBeautyStringWithKey(@"取消") confirm:FUBeautyStringWithKey(@"确定") inController:nil confirmHandler:^{
|
||||
[self.viewModel recoverAllShapeValuesToDefault];
|
||||
[self refreshSubviews];
|
||||
} cancelHandler:nil];
|
||||
}
|
||||
|
||||
- (void)sliderValueChanged {
|
||||
[self.viewModel setShapeValue:self.slider.value];
|
||||
}
|
||||
|
||||
- (void)sliderChangeEnded {
|
||||
[self refreshSubviews];
|
||||
}
|
||||
|
||||
#pragma mark - Collection view data source
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||
return self.viewModel.beautyShapes.count;
|
||||
}
|
||||
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
FUBeautyShapeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFUBeautyShapeCellIdentifier forIndexPath:indexPath];
|
||||
FUBeautyShapeModel *shape = self.viewModel.beautyShapes[indexPath.item];
|
||||
cell.textLabel.text = FUBeautyStringWithKey(shape.name);
|
||||
cell.imageName = shape.name;
|
||||
cell.defaultInMiddle = shape.defaultValueInMiddle;
|
||||
cell.defaultValue = shape.defaultValue;
|
||||
cell.currentValue = shape.currentValue;
|
||||
// 处理低性能手机禁用特效
|
||||
if (shape.differentiateDevicePerformance) {
|
||||
cell.disabled = self.viewModel.performanceLevel != FUDevicePerformanceLevelHigh;
|
||||
} else {
|
||||
cell.disabled = NO;
|
||||
}
|
||||
cell.selected = indexPath.item == self.viewModel.selectedIndex;
|
||||
return cell;
|
||||
}
|
||||
|
||||
#pragma mark - Collection view delegate
|
||||
|
||||
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
FUBeautyShapeModel *shape = self.viewModel.beautyShapes[indexPath.item];
|
||||
if (shape.differentiateDevicePerformance) {
|
||||
if (self.viewModel.performanceLevel != FUDevicePerformanceLevelHigh) {
|
||||
[FUTipHUD showTips:[NSString stringWithFormat:FUBeautyStringWithKey(@"该功能只支持在高端机上使用"), FUBeautyStringWithKey(shape.name)] dismissWithDelay:1];
|
||||
[self.shapeCollectionView reloadData];
|
||||
if (self.viewModel.selectedIndex >= 0) {
|
||||
[self.shapeCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.viewModel.selectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.item == self.viewModel.selectedIndex) {
|
||||
return;
|
||||
}
|
||||
self.viewModel.selectedIndex = indexPath.item;
|
||||
FUBeautyShapeModel *shape = self.viewModel.beautyShapes[indexPath.item];
|
||||
if (self.slider.hidden) {
|
||||
self.slider.hidden = NO;
|
||||
}
|
||||
self.slider.bidirection = shape.defaultValueInMiddle;
|
||||
self.slider.value = shape.currentValue;
|
||||
}
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
- (UICollectionView *)shapeCollectionView {
|
||||
if (!_shapeCollectionView) {
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
||||
layout.itemSize = CGSizeMake(44, 74);
|
||||
layout.minimumLineSpacing = 22;
|
||||
layout.minimumInteritemSpacing = 22;
|
||||
layout.sectionInset = UIEdgeInsetsMake(16, 16, 6, 16);
|
||||
_shapeCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
_shapeCollectionView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
_shapeCollectionView.backgroundColor = [UIColor clearColor];
|
||||
_shapeCollectionView.showsVerticalScrollIndicator = NO;
|
||||
_shapeCollectionView.showsHorizontalScrollIndicator = NO;
|
||||
_shapeCollectionView.dataSource = self;
|
||||
_shapeCollectionView.delegate = self;
|
||||
[_shapeCollectionView registerClass:[FUBeautyShapeCell class] forCellWithReuseIdentifier:kFUBeautyShapeCellIdentifier];
|
||||
}
|
||||
return _shapeCollectionView;
|
||||
}
|
||||
|
||||
- (FUSquareButton *)recoverButton {
|
||||
if (!_recoverButton) {
|
||||
_recoverButton = [[FUSquareButton alloc] initWithFrame:CGRectMake(0, 0, 44, 74)];
|
||||
[_recoverButton setTitle:FUBeautyStringWithKey(@"恢复") forState:UIControlStateNormal];
|
||||
[_recoverButton setImage:[UIImage imageNamed:@"recover_item"] forState:UIControlStateNormal];
|
||||
_recoverButton.alpha = 0.6;
|
||||
_recoverButton.userInteractionEnabled = NO;
|
||||
[_recoverButton addTarget:self action:@selector(recoverAction) forControlEvents:UIControlEventTouchUpInside];
|
||||
_recoverButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _recoverButton;
|
||||
}
|
||||
|
||||
-(FUSlider *)slider {
|
||||
if (!_slider) {
|
||||
_slider = [[FUSlider alloc] initWithFrame:CGRectMake(56, 16, CGRectGetWidth(self.frame) - 116, FUBeautyFunctionSliderHeight)];
|
||||
_slider.hidden = YES;
|
||||
[_slider addTarget:self action:@selector(sliderValueChanged) forControlEvents:UIControlEventValueChanged];
|
||||
[_slider addTarget:self action:@selector(sliderChangeEnded) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
|
||||
}
|
||||
return _slider;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface FUBeautyShapeCell ()
|
||||
|
||||
@property (nonatomic, strong) UIImageView *imageView;
|
||||
|
||||
@property (nonatomic, strong) UILabel *textLabel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautyShapeCell
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self.contentView addSubview:self.imageView];
|
||||
NSLayoutConstraint *imageTop = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageLeading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageTrailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageHeight = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
|
||||
[self.contentView addConstraints:@[imageTop, imageLeading, imageTrailing]];
|
||||
[self.imageView addConstraint:imageHeight];
|
||||
|
||||
[self.contentView addSubview:self.textLabel];
|
||||
NSLayoutConstraint *textTop = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeBottom multiplier:1 constant:7];
|
||||
NSLayoutConstraint *textLeading = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
|
||||
NSLayoutConstraint *textTrailing = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
[self.contentView addConstraints:@[textTop, textLeading, textTrailing]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSelected:(BOOL)selected {
|
||||
[super setSelected:selected];
|
||||
if (self.disabled) {
|
||||
self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-0", self.imageName]];
|
||||
self.imageView.alpha = 0.7;
|
||||
self.textLabel.alpha = 0.7;
|
||||
} else {
|
||||
self.imageView.alpha = 1;
|
||||
self.textLabel.alpha = 1;
|
||||
BOOL changed = NO;
|
||||
if (self.defaultInMiddle) {
|
||||
changed = fabs(self.currentValue - 0.5) > 0.01;
|
||||
}else{
|
||||
changed = self.currentValue > 0.01;
|
||||
}
|
||||
if (selected) {
|
||||
self.imageView.image = changed ? [UIImage imageNamed:[NSString stringWithFormat:@"%@-3", self.imageName]] : [UIImage imageNamed:[NSString stringWithFormat:@"%@-2", self.imageName]];
|
||||
self.textLabel.textColor = [UIColor colorWithRed:103/255.f green:195/255.f blue:103/255.f alpha:1];
|
||||
} else {
|
||||
self.imageView.image = changed ? [UIImage imageNamed:[NSString stringWithFormat:@"%@-1", self.imageName]] : [UIImage imageNamed:[NSString stringWithFormat:@"%@-0", self.imageName]];
|
||||
self.textLabel.textColor = [UIColor whiteColor];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImageView *)imageView {
|
||||
if (!_imageView) {
|
||||
_imageView = [[UIImageView alloc] init];
|
||||
_imageView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _imageView;
|
||||
}
|
||||
|
||||
- (UILabel *)textLabel {
|
||||
if (!_textLabel) {
|
||||
_textLabel = [[UILabel alloc] init];
|
||||
_textLabel.font = [UIFont systemFontOfSize:14];
|
||||
_textLabel.textColor = [UIColor whiteColor];
|
||||
_textLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_textLabel.adjustsFontSizeToFitWidth = YES;
|
||||
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _textLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// FUBeautySkinView.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/6/21.
|
||||
//
|
||||
// 美肤&美型视图
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "FUBeautySkinViewModel.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FUBeautySkinView : UIView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautySkinViewModel *)viewModel;
|
||||
|
||||
@end
|
||||
|
||||
@interface FUBeautySkinCell : UICollectionViewCell
|
||||
|
||||
@property (nonatomic, strong, readonly) UIImageView *imageView;
|
||||
|
||||
@property (nonatomic, strong, readonly) UILabel *textLabel;
|
||||
|
||||
@property (nonatomic, assign) BOOL defaultInMiddle;
|
||||
|
||||
@property (nonatomic, assign) double currentValue;
|
||||
|
||||
@property (nonatomic, assign) double defaultValue;
|
||||
|
||||
@property (nonatomic, copy) NSString *imageName;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,269 @@
|
||||
//
|
||||
// FUBeautySkinView.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/6/21.
|
||||
//
|
||||
|
||||
#import "FUBeautySkinView.h"
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
#import <FUCommonUIComponent/FUCommonUIComponent.h>
|
||||
|
||||
static NSString * const kFUBeautySkinCellIdentifier = @"FUBeautySkinCell";
|
||||
|
||||
@interface FUBeautySkinView ()<UICollectionViewDataSource, UICollectionViewDelegate>
|
||||
|
||||
@property (nonatomic, strong) UICollectionView *skinCollectionView;
|
||||
/// 程度调节
|
||||
@property (nonatomic, strong) FUSlider *slider;
|
||||
/// 恢复按钮
|
||||
@property (nonatomic, strong) FUSquareButton *recoverButton;
|
||||
|
||||
@property (nonatomic, strong) FUBeautySkinViewModel *viewModel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautySkinView
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
return [self initWithFrame:frame viewModel:[[FUBeautySkinViewModel alloc] init]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame viewModel:(FUBeautySkinViewModel *)viewModel {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
self.viewModel = viewModel;
|
||||
[self configureUI];
|
||||
[self refreshSubviews];
|
||||
[self collectionView:self.skinCollectionView didSelectItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - UI
|
||||
|
||||
- (void)configureUI {
|
||||
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
|
||||
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
|
||||
effectView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));
|
||||
[self addSubview:effectView];
|
||||
|
||||
[self addSubview:self.slider];
|
||||
[self addSubview:self.recoverButton];
|
||||
NSLayoutConstraint *recoverLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:17];
|
||||
NSLayoutConstraint *recoverBottomConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:-6];
|
||||
NSLayoutConstraint *recoverWidthConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:44];
|
||||
NSLayoutConstraint *recoverHeightConstraint = [NSLayoutConstraint constraintWithItem:self.recoverButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:74];
|
||||
|
||||
[self addConstraints:@[recoverLeadingConstraint, recoverBottomConstraint]];
|
||||
[self.recoverButton addConstraints:@[recoverWidthConstraint, recoverHeightConstraint]];
|
||||
|
||||
// 分割线
|
||||
UIView *verticalLine = [[UIView alloc] init];
|
||||
verticalLine.backgroundColor = [UIColor colorWithRed:229/255.f green:229/255.f blue:229/255.f alpha:0.2];
|
||||
verticalLine.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self addSubview:verticalLine];
|
||||
NSLayoutConstraint *lineLeadingConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.recoverButton attribute:NSLayoutAttributeTrailing multiplier:1 constant:14];
|
||||
NSLayoutConstraint *lineCenterYConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.recoverButton attribute:NSLayoutAttributeCenterY multiplier:1 constant:-15];
|
||||
NSLayoutConstraint *lineWidthConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:1];
|
||||
NSLayoutConstraint *lineHeightConstraint = [NSLayoutConstraint constraintWithItem:verticalLine attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:24];
|
||||
[self addConstraints:@[lineLeadingConstraint, lineCenterYConstraint]];
|
||||
[verticalLine addConstraints:@[lineWidthConstraint, lineHeightConstraint]];
|
||||
|
||||
[self addSubview:self.skinCollectionView];
|
||||
NSLayoutConstraint *collectionLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.skinCollectionView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:76];
|
||||
NSLayoutConstraint *collectionTrailingConstraint = [NSLayoutConstraint constraintWithItem:self.skinCollectionView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
NSLayoutConstraint *collectionBottomConstraint = [NSLayoutConstraint constraintWithItem:self.skinCollectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
|
||||
NSLayoutConstraint *collectionHeightConstraint = [NSLayoutConstraint constraintWithItem:self.skinCollectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:98];
|
||||
[self addConstraints:@[collectionLeadingConstraint, collectionTrailingConstraint, collectionBottomConstraint]];
|
||||
[self.skinCollectionView addConstraint:collectionHeightConstraint];
|
||||
}
|
||||
|
||||
- (void)refreshSubviews {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.viewModel.isDefaultValue) {
|
||||
self.recoverButton.alpha = 0.6;
|
||||
self.recoverButton.userInteractionEnabled = NO;
|
||||
} else {
|
||||
self.recoverButton.alpha = 1;
|
||||
self.recoverButton.userInteractionEnabled = YES;
|
||||
}
|
||||
if (!self.slider.hidden && self.viewModel.selectedIndex >= 0) {
|
||||
self.slider.bidirection = self.viewModel.beautySkins[self.viewModel.selectedIndex].defaultValueInMiddle;
|
||||
self.slider.value = self.viewModel.beautySkins[self.viewModel.selectedIndex].currentValue / self.viewModel.beautySkins[self.viewModel.selectedIndex].ratio;
|
||||
}
|
||||
[self.skinCollectionView reloadData];
|
||||
if (self.viewModel.selectedIndex >= 0) {
|
||||
[self.skinCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.viewModel.selectedIndex inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Event response
|
||||
|
||||
- (void)recoverAction {
|
||||
[FUAlertManager showAlertWithTitle:nil message:FUBeautyStringWithKey(@"是否将所有参数恢复到默认值") cancel:FUBeautyStringWithKey(@"取消") confirm:FUBeautyStringWithKey(@"确定") inController:nil confirmHandler:^{
|
||||
[self.viewModel recoverAllSkinValuesToDefault];
|
||||
[self refreshSubviews];
|
||||
} cancelHandler:nil];
|
||||
}
|
||||
|
||||
- (void)sliderValueChanged {
|
||||
[self.viewModel setSkinValue:self.slider.value];
|
||||
}
|
||||
|
||||
- (void)sliderChangeEnded {
|
||||
[self refreshSubviews];
|
||||
}
|
||||
|
||||
#pragma mark - Collection view data source
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||
return self.viewModel.beautySkins.count;
|
||||
}
|
||||
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
FUBeautySkinCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kFUBeautySkinCellIdentifier forIndexPath:indexPath];
|
||||
FUBeautySkinModel *skin = self.viewModel.beautySkins[indexPath.item];
|
||||
cell.textLabel.text = FUBeautyStringWithKey(skin.name);
|
||||
cell.imageName = skin.name;
|
||||
cell.defaultInMiddle = skin.defaultValueInMiddle;
|
||||
cell.defaultValue = skin.defaultValue;
|
||||
cell.currentValue = skin.currentValue;
|
||||
cell.selected = indexPath.item == self.viewModel.selectedIndex;
|
||||
return cell;
|
||||
}
|
||||
|
||||
#pragma mark - Collection view delegate
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.item == self.viewModel.selectedIndex) {
|
||||
return;
|
||||
}
|
||||
self.viewModel.selectedIndex = indexPath.item;
|
||||
FUBeautySkinModel *skin = self.viewModel.beautySkins[indexPath.item];
|
||||
if (self.slider.hidden) {
|
||||
self.slider.hidden = NO;
|
||||
}
|
||||
self.slider.bidirection = skin.defaultValueInMiddle;
|
||||
self.slider.value = skin.currentValue / skin.ratio;
|
||||
}
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
- (UICollectionView *)skinCollectionView {
|
||||
if (!_skinCollectionView) {
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
||||
layout.itemSize = CGSizeMake(44, 74);
|
||||
layout.minimumLineSpacing = 22;
|
||||
layout.minimumInteritemSpacing = 22;
|
||||
layout.sectionInset = UIEdgeInsetsMake(16, 16, 6, 16);
|
||||
_skinCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
_skinCollectionView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
_skinCollectionView.backgroundColor = [UIColor clearColor];
|
||||
_skinCollectionView.showsVerticalScrollIndicator = NO;
|
||||
_skinCollectionView.showsHorizontalScrollIndicator = NO;
|
||||
_skinCollectionView.dataSource = self;
|
||||
_skinCollectionView.delegate = self;
|
||||
[_skinCollectionView registerClass:[FUBeautySkinCell class] forCellWithReuseIdentifier:kFUBeautySkinCellIdentifier];
|
||||
}
|
||||
return _skinCollectionView;
|
||||
}
|
||||
|
||||
- (FUSquareButton *)recoverButton {
|
||||
if (!_recoverButton) {
|
||||
_recoverButton = [[FUSquareButton alloc] initWithFrame:CGRectMake(0, 0, 44, 74)];
|
||||
[_recoverButton setTitle:FUBeautyStringWithKey(@"恢复") forState:UIControlStateNormal];
|
||||
[_recoverButton setImage:[UIImage imageNamed:@"recover_item"] forState:UIControlStateNormal];
|
||||
_recoverButton.alpha = 0.6;
|
||||
_recoverButton.userInteractionEnabled = NO;
|
||||
[_recoverButton addTarget:self action:@selector(recoverAction) forControlEvents:UIControlEventTouchUpInside];
|
||||
_recoverButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _recoverButton;
|
||||
}
|
||||
|
||||
-(FUSlider *)slider {
|
||||
if (!_slider) {
|
||||
_slider = [[FUSlider alloc] initWithFrame:CGRectMake(56, 16, CGRectGetWidth(self.frame) - 116, FUBeautyFunctionSliderHeight)];
|
||||
_slider.hidden = YES;//67C367
|
||||
[_slider addTarget:self action:@selector(sliderValueChanged) forControlEvents:UIControlEventValueChanged];
|
||||
[_slider addTarget:self action:@selector(sliderChangeEnded) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
|
||||
}
|
||||
return _slider;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface FUBeautySkinCell ()
|
||||
|
||||
@property (nonatomic, strong) UIImageView *imageView;
|
||||
|
||||
@property (nonatomic, strong) UILabel *textLabel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautySkinCell
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self.contentView addSubview:self.imageView];
|
||||
NSLayoutConstraint *imageTop = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageLeading = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageTrailing = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
NSLayoutConstraint *imageHeight = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
|
||||
[self.contentView addConstraints:@[imageTop, imageLeading, imageTrailing]];
|
||||
[self.imageView addConstraint:imageHeight];
|
||||
|
||||
[self.contentView addSubview:self.textLabel];
|
||||
NSLayoutConstraint *textTop = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeBottom multiplier:1 constant:7];
|
||||
NSLayoutConstraint *textLeading = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeading multiplier:1 constant:0];
|
||||
NSLayoutConstraint *textTrailing = [NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0];
|
||||
[self.contentView addConstraints:@[textTop, textLeading, textTrailing]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setSelected:(BOOL)selected {
|
||||
[super setSelected:selected];
|
||||
BOOL changed = NO;
|
||||
if (self.defaultInMiddle) {
|
||||
changed = fabs(self.currentValue - 0.5) > 0.01;
|
||||
}else{
|
||||
changed = self.currentValue > 0.01;
|
||||
}
|
||||
if (selected) {
|
||||
self.imageView.image = changed ? [UIImage imageNamed:[NSString stringWithFormat:@"%@-3", self.imageName]] : [UIImage imageNamed:[NSString stringWithFormat:@"%@-2", self.imageName]];
|
||||
self.textLabel.textColor = [UIColor colorWithRed:103/255.f green:195/255.f blue:103/255.f alpha:1];
|
||||
} else {
|
||||
self.imageView.image = changed ? [UIImage imageNamed:[NSString stringWithFormat:@"%@-1", self.imageName]] : [UIImage imageNamed:[NSString stringWithFormat:@"%@-0", self.imageName]];
|
||||
self.textLabel.textColor = [UIColor whiteColor];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImageView *)imageView {
|
||||
if (!_imageView) {
|
||||
_imageView = [[UIImageView alloc] init];
|
||||
_imageView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _imageView;
|
||||
}
|
||||
|
||||
- (UILabel *)textLabel {
|
||||
if (!_textLabel) {
|
||||
_textLabel = [[UILabel alloc] init];
|
||||
_textLabel.font = [UIFont systemFontOfSize:14];
|
||||
_textLabel.textColor = [UIColor whiteColor];
|
||||
_textLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_textLabel.adjustsFontSizeToFitWidth = YES;
|
||||
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
}
|
||||
return _textLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// FUBeautyFilterViewModel.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/7.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FUBeautyFilterModel.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FUBeautyFilterViewModel : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSArray<FUBeautyFilterModel *> *beautyFilters;
|
||||
/// 选中滤镜索引
|
||||
@property (nonatomic, assign) NSInteger selectedIndex;
|
||||
|
||||
/// 保存滤镜数据到本地
|
||||
- (void)saveFitersPersistently;
|
||||
|
||||
/// 设置当前滤镜
|
||||
- (void)setCurrentFilter;
|
||||
|
||||
/// 设置滤镜程度
|
||||
/// @param value 程度值
|
||||
- (void)setFilterValue:(double)value;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// FUBeautyFilterViewModel.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/7.
|
||||
//
|
||||
|
||||
#import "FUBeautyFilterViewModel.h"
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
#import <FURenderKit/FURenderKit.h>
|
||||
|
||||
@interface FUBeautyFilterViewModel ()
|
||||
|
||||
@property (nonatomic, copy) NSArray<FUBeautyFilterModel *> *beautyFilters;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautyFilterViewModel
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if ([[NSUserDefaults standardUserDefaults] objectForKey:FUPersistentBeautyFilterKey]) {
|
||||
// 获取本地滤镜数据
|
||||
self.beautyFilters = [self localFilters];
|
||||
} else {
|
||||
// 获取默认滤镜数据
|
||||
self.beautyFilters = [self defaultFilters];
|
||||
}
|
||||
if ([[NSUserDefaults standardUserDefaults] objectForKey:FUPersistentBeautySelectedFilterIndexKey]) {
|
||||
// 获取本地保存选中的索引
|
||||
_selectedIndex = [[NSUserDefaults standardUserDefaults] integerForKey:FUPersistentBeautySelectedFilterIndexKey];
|
||||
} else {
|
||||
// 默认索引为2
|
||||
_selectedIndex = 2;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Instance methods
|
||||
|
||||
- (void)saveFitersPersistently {
|
||||
if (self.beautyFilters.count == 0) {
|
||||
return;
|
||||
}
|
||||
NSMutableArray *filters = [[NSMutableArray alloc] init];
|
||||
for (FUBeautyFilterModel *model in self. beautyFilters) {
|
||||
NSDictionary *dictionary = [model dictionaryWithValuesForKeys:@[@"filterIndex", @"filterName", @"filterLevel"]];
|
||||
[filters addObject:dictionary];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] setObject:filters forKey:FUPersistentBeautyFilterKey];
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:self.selectedIndex forKey:FUPersistentBeautySelectedFilterIndexKey];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (void)setSelectedIndex:(NSInteger)selectedIndex {
|
||||
if (selectedIndex < 0 || selectedIndex >= self.beautyFilters.count) {
|
||||
return;
|
||||
}
|
||||
[self setFilter:self.beautyFilters[selectedIndex].filterName level:self.beautyFilters[selectedIndex].filterLevel];
|
||||
_selectedIndex = selectedIndex;
|
||||
}
|
||||
|
||||
- (void)setCurrentFilter {
|
||||
if (self.selectedIndex < 0 || self.selectedIndex >= self.beautyFilters.count) {
|
||||
return;
|
||||
}
|
||||
[self setFilter:self.beautyFilters[self.selectedIndex].filterName level:self.beautyFilters[self.selectedIndex].filterLevel];
|
||||
}
|
||||
|
||||
- (void)setFilterValue:(double)value {
|
||||
if (self.selectedIndex < 0 || self.selectedIndex >= self.beautyFilters.count) {
|
||||
return;
|
||||
}
|
||||
FUBeautyFilterModel *model = self.beautyFilters[self.selectedIndex];
|
||||
model.filterLevel = value;
|
||||
[FURenderKit shareRenderKit].beauty.filterLevel = model.filterLevel;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
- (void)setFilter:(NSString *)filterName level:(double)filterLevel {
|
||||
[FURenderKit shareRenderKit].beauty.filterName = filterName;
|
||||
[FURenderKit shareRenderKit].beauty.filterLevel = filterLevel;
|
||||
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
[self performSelector:@selector(saveFitersPersistently) withObject:nil afterDelay:2];
|
||||
}
|
||||
|
||||
- (NSArray<FUBeautyFilterModel *> *)localFilters {
|
||||
NSArray *filters = [[NSUserDefaults standardUserDefaults] objectForKey:FUPersistentBeautyFilterKey];
|
||||
NSMutableArray *mutableFilters = [[NSMutableArray alloc] init];
|
||||
for (NSDictionary *filter in filters) {
|
||||
FUBeautyFilterModel *model = [[FUBeautyFilterModel alloc] init];
|
||||
[model setValuesForKeysWithDictionary:filter];
|
||||
[mutableFilters addObject:model];
|
||||
}
|
||||
return [mutableFilters copy];
|
||||
}
|
||||
|
||||
- (NSArray<FUBeautyFilterModel *> *)defaultFilters {
|
||||
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||||
NSString *filterPath = [bundle pathForResource:@"beauty_filter" ofType:@"json"];
|
||||
NSArray<NSDictionary *> *filterData = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:filterPath] options:NSJSONReadingMutableContainers error:nil];
|
||||
NSMutableArray *filters = [[NSMutableArray alloc] init];
|
||||
for (NSDictionary *dictionary in filterData) {
|
||||
FUBeautyFilterModel *model = [[FUBeautyFilterModel alloc] init];
|
||||
[model setValuesForKeysWithDictionary:dictionary];
|
||||
[filters addObject:model];
|
||||
}
|
||||
return [filters copy];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// FUBeautyShapeViewModel.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/27.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <FURenderKit/FURenderKit.h>
|
||||
#import "FUBeautyShapeModel.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FUBeautyShapeViewModel : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSArray<FUBeautyShapeModel *> *beautyShapes;
|
||||
/// 是否所有值都是默认
|
||||
@property (nonatomic, assign, readonly) BOOL isDefaultValue;
|
||||
/// 当前选中索引,默认为-1
|
||||
@property (nonatomic, assign) NSInteger selectedIndex;
|
||||
/// 美型属性需要根据高低端机适配
|
||||
@property (nonatomic, assign) FUDevicePerformanceLevel performanceLevel;
|
||||
|
||||
/// 保存美型数据到本地
|
||||
- (void)saveShapesPersistently;
|
||||
|
||||
/// 设置单项美型值
|
||||
/// @param value 当前选中单项的值
|
||||
- (void)setShapeValue:(double)value;
|
||||
|
||||
/// 设置当前所有美型值
|
||||
- (void)setAllShapeValues;
|
||||
|
||||
/// 恢复所有美型值为默认
|
||||
- (void)recoverAllShapeValuesToDefault;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// FUBeautyShapeViewModel.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/27.
|
||||
//
|
||||
|
||||
#import "FUBeautyShapeViewModel.h"
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
#import <FURenderKit/FURenderKit.h>
|
||||
|
||||
@interface FUBeautyShapeViewModel ()
|
||||
|
||||
@property (nonatomic, copy) NSArray<FUBeautyShapeModel *> *beautyShapes;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautyShapeViewModel
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if ([[NSUserDefaults standardUserDefaults] objectForKey:FUPersistentBeautyShapeKey]) {
|
||||
// 获取本地美肤数据
|
||||
self.beautyShapes = [self localShapes];
|
||||
} else {
|
||||
// 获取默认美肤数据
|
||||
self.beautyShapes = [self defaultShapes];
|
||||
}
|
||||
self.selectedIndex = -1;
|
||||
self.performanceLevel = [FURenderKit devicePerformanceLevel];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Instance methods
|
||||
|
||||
- (void)saveShapesPersistently {
|
||||
if (self.beautyShapes.count == 0) {
|
||||
return;
|
||||
}
|
||||
NSMutableArray *shapes = [[NSMutableArray alloc] init];
|
||||
for (FUBeautyShapeModel *model in self.beautyShapes) {
|
||||
NSDictionary *dictionary = [model dictionaryWithValuesForKeys:@[@"name", @"type", @"currentValue", @"defaultValue", @"defaultValueInMiddle", @"differentiateDevicePerformance"]];
|
||||
[shapes addObject:dictionary];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] setObject:shapes forKey:FUPersistentBeautyShapeKey];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (void)setShapeValue:(double)value {
|
||||
if (self.selectedIndex < 0 || self.selectedIndex >= self.beautyShapes.count) {
|
||||
return;
|
||||
}
|
||||
FUBeautyShapeModel *model = self.beautyShapes[self.selectedIndex];
|
||||
model.currentValue = value;
|
||||
[self setValue:model.currentValue forType:model.type];
|
||||
}
|
||||
|
||||
- (void)setAllShapeValues {
|
||||
for (FUBeautyShapeModel *shape in self.beautyShapes) {
|
||||
[self setValue:shape.currentValue forType:shape.type];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)recoverAllShapeValuesToDefault {
|
||||
for (FUBeautyShapeModel *shape in self.beautyShapes) {
|
||||
shape.currentValue = shape.defaultValue;
|
||||
[self setValue:shape.currentValue forType:shape.type];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
- (void)setValue:(double)value forType:(FUBeautyShape)type {
|
||||
switch (type) {
|
||||
case FUBeautyShapeCheekThinning:
|
||||
[FURenderKit shareRenderKit].beauty.cheekThinning = value;
|
||||
break;
|
||||
case FUBeautyShapeCheekV:
|
||||
[FURenderKit shareRenderKit].beauty.cheekV = value;
|
||||
break;
|
||||
case FUBeautyShapeCheekNarrow:
|
||||
[FURenderKit shareRenderKit].beauty.cheekNarrow = value;
|
||||
break;
|
||||
case FUBeautyShapeCheekShort:
|
||||
[FURenderKit shareRenderKit].beauty.cheekShort = value;
|
||||
break;
|
||||
case FUBeautyShapeCheekSmall:
|
||||
[FURenderKit shareRenderKit].beauty.cheekSmall = value;
|
||||
break;
|
||||
case FUBeautyShapeCheekbones:
|
||||
[FURenderKit shareRenderKit].beauty.intensityCheekbones = value;
|
||||
break;
|
||||
case FUBeautyShapeLowerJaw:
|
||||
[FURenderKit shareRenderKit].beauty.intensityLowerJaw = value;
|
||||
break;
|
||||
case FUBeautyShapeEyeEnlarging:
|
||||
[FURenderKit shareRenderKit].beauty.eyeEnlarging = value;
|
||||
break;
|
||||
case FUBeautyShapeEyeCircle:
|
||||
[FURenderKit shareRenderKit].beauty.intensityEyeCircle = value;
|
||||
break;
|
||||
case FUBeautyShapeChin:
|
||||
[FURenderKit shareRenderKit].beauty.intensityChin = value;
|
||||
break;
|
||||
case FUBeautyShapeForehead:
|
||||
[FURenderKit shareRenderKit].beauty.intensityForehead = value;
|
||||
break;
|
||||
case FUBeautyShapeNose:
|
||||
[FURenderKit shareRenderKit].beauty.intensityNose = value;
|
||||
break;
|
||||
case FUBeautyShapeMouth:
|
||||
[FURenderKit shareRenderKit].beauty.intensityMouth = value;
|
||||
break;
|
||||
case FUBeautyShapeLipThick:
|
||||
[FURenderKit shareRenderKit].beauty.intensityLipThick = value;
|
||||
break;
|
||||
case FUBeautyShapeEyeHeight:
|
||||
[FURenderKit shareRenderKit].beauty.intensityEyeHeight = value;
|
||||
break;
|
||||
case FUBeautyShapeCanthus:
|
||||
[FURenderKit shareRenderKit].beauty.intensityCanthus = value;
|
||||
break;
|
||||
case FUBeautyShapeEyeLid:
|
||||
[FURenderKit shareRenderKit].beauty.intensityEyeLid = value;
|
||||
break;
|
||||
case FUBeautyShapeEyeSpace:
|
||||
[FURenderKit shareRenderKit].beauty.intensityEyeSpace = value;
|
||||
break;
|
||||
case FUBeautyShapeEyeRotate:
|
||||
[FURenderKit shareRenderKit].beauty.intensityEyeRotate = value;
|
||||
break;
|
||||
case FUBeautyShapeLongNose:
|
||||
[FURenderKit shareRenderKit].beauty.intensityLongNose = value;
|
||||
break;
|
||||
case FUBeautyShapePhiltrum:
|
||||
[FURenderKit shareRenderKit].beauty.intensityPhiltrum = value;
|
||||
break;
|
||||
case FUBeautyShapeSmile:
|
||||
[FURenderKit shareRenderKit].beauty.intensitySmile = value;
|
||||
break;
|
||||
case FUBeautyShapeBrowHeight:
|
||||
[FURenderKit shareRenderKit].beauty.intensityBrowHeight = value;
|
||||
break;
|
||||
case FUBeautyShapeBrowSpace:
|
||||
[FURenderKit shareRenderKit].beauty.intensityBrowSpace = value;
|
||||
break;
|
||||
case FUBeautyShapeBrowThick:
|
||||
[FURenderKit shareRenderKit].beauty.intensityBrowThick = value;
|
||||
break;
|
||||
}
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
[self performSelector:@selector(saveShapesPersistently) withObject:nil afterDelay:2];
|
||||
}
|
||||
|
||||
- (NSArray<FUBeautyShapeModel *> *)localShapes {
|
||||
NSArray *shapes = [[NSUserDefaults standardUserDefaults] objectForKey:FUPersistentBeautyShapeKey];
|
||||
NSMutableArray *mutableShapes = [[NSMutableArray alloc] init];
|
||||
for (NSDictionary *shape in shapes) {
|
||||
FUBeautyShapeModel *model = [[FUBeautyShapeModel alloc] init];
|
||||
[model setValuesForKeysWithDictionary:shape];
|
||||
[mutableShapes addObject:model];
|
||||
}
|
||||
return [mutableShapes copy];
|
||||
}
|
||||
|
||||
- (NSArray<FUBeautyShapeModel *> *)defaultShapes {
|
||||
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||||
NSString *shapePath = [bundle pathForResource:@"beauty_shape" ofType:@"json"];
|
||||
NSArray<NSDictionary *> *shapeData = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:shapePath] options:NSJSONReadingMutableContainers error:nil];
|
||||
NSMutableArray *shapes = [[NSMutableArray alloc] init];
|
||||
for (NSDictionary *dictionary in shapeData) {
|
||||
FUBeautyShapeModel *model = [[FUBeautyShapeModel alloc] init];
|
||||
[model setValuesForKeysWithDictionary:dictionary];
|
||||
[shapes addObject:model];
|
||||
}
|
||||
return [shapes copy];
|
||||
}
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
- (BOOL)isDefaultValue {
|
||||
for (FUBeautyShapeModel *shape in self.beautyShapes) {
|
||||
int currentIntValue = shape.defaultValueInMiddle ? (int)(shape.currentValue * 100 - 50) : (int)(shape.currentValue * 100);
|
||||
int defaultIntValue = shape.defaultValueInMiddle ? (int)(shape.defaultValue * 100 - 50) : (int)(shape.defaultValue * 100);
|
||||
if (currentIntValue != defaultIntValue) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// FUBeautySkinViewModel.h
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/27.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FUBeautySkinModel.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FUBeautySkinViewModel : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSArray<FUBeautySkinModel *> *beautySkins;
|
||||
/// 是否所有值都是默认
|
||||
@property (nonatomic, assign, readonly) BOOL isDefaultValue;
|
||||
/// 当前选中索引,默认为-1
|
||||
@property (nonatomic, assign) NSInteger selectedIndex;
|
||||
|
||||
/// 保存美肤数据到本地
|
||||
- (void)saveSkinsPersistently;
|
||||
|
||||
/// 设置单项美肤值
|
||||
/// @param value 当前选中单项的值
|
||||
- (void)setSkinValue:(double)value;
|
||||
|
||||
/// 设置当前所有美肤值
|
||||
- (void)setAllSkinValues;
|
||||
|
||||
/// 恢复所有美肤值为默认
|
||||
- (void)recoverAllSkinValuesToDefault;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// FUBeautySkinViewModel.m
|
||||
// FUBeautyComponent
|
||||
//
|
||||
// Created by 项林平 on 2022/7/27.
|
||||
//
|
||||
|
||||
#import "FUBeautySkinViewModel.h"
|
||||
#import "FUBeautyDefine.h"
|
||||
|
||||
#import <FURenderKit/FURenderKit.h>
|
||||
|
||||
@interface FUBeautySkinViewModel ()
|
||||
|
||||
@property (nonatomic, copy) NSArray<FUBeautySkinModel *> *beautySkins;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FUBeautySkinViewModel
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if ([[NSUserDefaults standardUserDefaults] objectForKey:FUPersistentBeautySkinKey]) {
|
||||
// 获取本地美肤数据
|
||||
self.beautySkins = [self localSkins];
|
||||
} else {
|
||||
// 获取默认美肤数据
|
||||
self.beautySkins = [self defaultSkins];
|
||||
}
|
||||
self.selectedIndex = -1;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Instance methods
|
||||
|
||||
- (void)saveSkinsPersistently {
|
||||
if (self.beautySkins.count == 0) {
|
||||
return;
|
||||
}
|
||||
NSMutableArray *skins = [[NSMutableArray alloc] init];
|
||||
for (FUBeautySkinModel *model in self.beautySkins) {
|
||||
NSDictionary *dictionary = [model dictionaryWithValuesForKeys:@[@"name", @"type", @"currentValue", @"defaultValue", @"defaultValueInMiddle", @"ratio"]];
|
||||
[skins addObject:dictionary];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] setObject:skins forKey:FUPersistentBeautySkinKey];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (void)setSkinValue:(double)value {
|
||||
if (self.selectedIndex < 0 || self.selectedIndex >= self.beautySkins.count) {
|
||||
return;
|
||||
}
|
||||
FUBeautySkinModel *model = self.beautySkins[self.selectedIndex];
|
||||
model.currentValue = value * model.ratio;
|
||||
[self setValue:model.currentValue forType:model.type];
|
||||
}
|
||||
|
||||
- (void)setAllSkinValues {
|
||||
for (FUBeautySkinModel *skin in self.beautySkins) {
|
||||
[self setValue:skin.currentValue forType:skin.type];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)recoverAllSkinValuesToDefault {
|
||||
for (FUBeautySkinModel *skin in self.beautySkins) {
|
||||
skin.currentValue = skin.defaultValue;
|
||||
[self setValue:skin.currentValue forType:skin.type];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
- (void)setValue:(double)value forType:(FUBeautySkin)type {
|
||||
switch (type) {
|
||||
case FUBeautySkinBlurLevel:
|
||||
[FURenderKit shareRenderKit].beauty.blurLevel = value;
|
||||
break;
|
||||
case FUBeautySkinColorLevel:
|
||||
[FURenderKit shareRenderKit].beauty.colorLevel = value;
|
||||
break;
|
||||
case FUBeautySkinRedLevel:
|
||||
[FURenderKit shareRenderKit].beauty.redLevel = value;
|
||||
break;
|
||||
case FUBeautySkinSharpen:
|
||||
[FURenderKit shareRenderKit].beauty.sharpen = value;
|
||||
break;
|
||||
case FUBeautySkinFaceThreed:
|
||||
[FURenderKit shareRenderKit].beauty.faceThreed = value;
|
||||
break;
|
||||
case FUBeautySkinEyeBright:
|
||||
[FURenderKit shareRenderKit].beauty.eyeBright = value;
|
||||
break;
|
||||
case FUBeautySkinToothWhiten:
|
||||
[FURenderKit shareRenderKit].beauty.toothWhiten = value;
|
||||
break;
|
||||
case FUBeautySkinRemovePouchStrength:
|
||||
[FURenderKit shareRenderKit].beauty.removePouchStrength = value;
|
||||
break;
|
||||
case FUBeautySkinRemoveNasolabialFoldsStrength:
|
||||
[FURenderKit shareRenderKit].beauty.removeNasolabialFoldsStrength = value;
|
||||
break;
|
||||
}
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
[self performSelector:@selector(saveSkinsPersistently) withObject:nil afterDelay:2];
|
||||
}
|
||||
|
||||
- (NSArray<FUBeautySkinModel *> *)localSkins {
|
||||
NSArray *skins = [[NSUserDefaults standardUserDefaults] objectForKey:FUPersistentBeautySkinKey];
|
||||
NSMutableArray *mutableSkins = [[NSMutableArray alloc] init];
|
||||
for (NSDictionary *skin in skins) {
|
||||
FUBeautySkinModel *model = [[FUBeautySkinModel alloc] init];
|
||||
[model setValuesForKeysWithDictionary:skin];
|
||||
[mutableSkins addObject:model];
|
||||
}
|
||||
return [mutableSkins copy];
|
||||
}
|
||||
|
||||
- (NSArray<FUBeautySkinModel *> *)defaultSkins {
|
||||
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
|
||||
NSString *skinPath = [bundle pathForResource:@"beauty_skin" ofType:@"json"];
|
||||
NSArray<NSDictionary *> *skinData = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:skinPath] options:NSJSONReadingMutableContainers error:nil];
|
||||
NSMutableArray *skins = [[NSMutableArray alloc] init];
|
||||
for (NSDictionary *dictionary in skinData) {
|
||||
FUBeautySkinModel *model = [[FUBeautySkinModel alloc] init];
|
||||
[model setValuesForKeysWithDictionary:dictionary];
|
||||
[skins addObject:model];
|
||||
}
|
||||
return [skins copy];
|
||||
}
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
- (BOOL)isDefaultValue {
|
||||
for (FUBeautySkinModel *skin in self.beautySkins) {
|
||||
int currentIntValue = skin.defaultValueInMiddle ? (int)(skin.currentValue / skin.ratio * 100 - 50) : (int)(skin.currentValue / skin.ratio * 100);
|
||||
int defaultIntValue = skin.defaultValueInMiddle ? (int)(skin.defaultValue / skin.ratio * 100 - 50) : (int)(skin.defaultValue / skin.ratio * 100);
|
||||
if (currentIntValue != defaultIntValue) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user