MLBusinessComponents 2.0.0

MLBusinessComponents 2.0.0

Vicente VeltriTomas De LuccaJuan Sanzone MeliGaston GrippiFacundo Conil 维护。



  • PX 团队 - Juan Sanzone & Esteban Boffa

Screenshot iOS

Codebeat quality status CocoaPods CocoaPods downloads

📲如何安装

使用 CocoaPods

编辑您的 Podfile 并指定依赖项

pod 'MLBusinessComponents'

🐒如何使用

1 - 将其导入项目。

import MLBusinessComponents

2 - 使用您的 UI 组件。

选择并实例化您的组件。

📦组件

每个组件都是 UIView 的子类。

1️⃣- MLBusinessLoyaltyRingView 组件

该组件允许您显示积分进度环、一个标签和可操作按钮。该组件最常见的使用是在会员计划中显示用户的积分进度。

视觉示例

MLBusinessLoyaltyRingView

MLBusinessLoyaltyRingView init

您需要设置 MLBusinessLoyaltyRingData 协议(接口)。此协议允许您将绘制数据填充到组件中。 (环进度百分比、环颜色、标签文本、按钮标题和按钮深度链接)。

let ringView = MLBusinessLoyaltyRingView(_ ringViewData: MLBusinessLoyaltyRingData)
view.addSubView(ringView)

/* 
    Set your constraints. You don't need to set up the HEIGHT contraint. 
    Because this component is responsible for knowing and setting your own HEIGHT.
*/
NSLayoutConstraint.activate([
    ringView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    ringView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    ringView.topAnchor.constraint(equalTo: view.topAnchor)
])

MLBusinessLoyaltyRingData 协议

此协议允许您提供适当的 MLBusinessLoyaltyRingView 绘制数据。您可以设置环进度百分比、环颜色、标签文本、按钮标题和按钮深度链接)。每个值都是必需的。

定义

@objc public protocol MLBusinessLoyaltyRingData: NSObjectProtocol {
    @objc func getRingHexaColor() -> String
    @objc func getRingNumber() -> Int
    @objc func getRingPercentage() -> Float
    @objc func getTitle() -> String
    @objc func getButtonTitle() -> String
    @objc func getButtonDeepLink() -> String
}

实现示例

MLBusinessLoyaltyRingData 的实现示例

class MyDrawDataForRingView: NSObject, MLBusinessLoyaltyRingData {
    func getRingNumber() -> Int {
        return 3
    }

    func getRingHexaColor() -> String {
        return "#17aad6"
    }

    func getRingPercentage() -> Float {
        return 0.80
    }

    func getTitle() -> String {
        return "Ganaste 100 Mercado Puntos"
    }

    func getButtonTitle() -> String {
        return "Mis beneficios"
    }

    func getButtonDeepLink() -> String {
        return "mercadopago://beneficios"
    }
}

如何接收点击动作和按钮深度链接?

您可以在用户按下组件按钮时接收在 MLBusinessLoyaltyRingData 中发送的深度链接。只需添加点击动作回调即可。

let ringView = MLBusinessLoyaltyRingView(MyDrawDataForRingView())
view.addSubView(ringView)

// Add tap action and receive the deepLink
ringView.addTapAction { deepLink in
    print(deepLink)
}

2️⃣- MLBusinessDiscountBoxView 组件

此组件允许您在一个网格系统中显示 N 个项目(默认为 3 列)。您可以为主组件添加标题和副标题。您还可以为每个项目提供 imageUrl、标题和副标题。此组件负责根据列数和项目数量设置自己的高度。

可视化示例

MLBusinessDiscountBoxView

MLBusinessDiscountBoxView 初始化

您需要设置 MLBusinessDiscountBoxData 协议。此接口允许您将绘制数据填充到组件中(主组件的标题、副标题和 imageUrl。每个项目的标题、副标题、深度链接项和 trackId)。

// DiscountData() is an implementation of MLBusinessDiscountBoxData protocol.
let discountView = MLBusinessDiscountBoxView(DiscountData())
view.addSubview(discountView)

/* 
    Set your constraints. You don't need to set up the HEIGHT contraint. 
    Because this component is responsible for knowing and setting your own HEIGHT.
*/
NSLayoutConstraint.activate([
   discountView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
   discountView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
   discountView.topAnchor.constraint(equalTo: targetView.bottomAnchor)
])

MLBusinessDiscountBoxData 协议

本协议允许您提供绘制 MLBusinessDiscountBoxView 所需的正确数据。您可以为主要组件设置标题和副标题,以及代表单元格每个元素的 MLBusinessDiscountSingleItemProtocol 列表。

定义

@objc public protocol MLBusinessDiscountBoxData: NSObjectProtocol {
    @objc optional func getTitle() -> String?
    @objc optional func getSubtitle() -> String?
    @objc func getItems() -> [MLBusinessSingleItemProtocol]
}

在 DiscountData 示例中实现 MLBusinessDiscountBoxData

class DiscountData: NSObject, MLBusinessDiscountBoxData {
    func getTitle() -> String {
        return "200 descuentos"
    }

    func getSubtitle() -> String {
        return "por ser nivel 3"
    }

    func getItems() -> [MLBusinessSingleItemProtocol] {
        var array: [MLBusinessSingleItemProtocol] = [MLBusinessSingleItemProtocol]()
        array.append(SingleItemData(title: "Hasta", subtitle: "$ 200", iconImageUrl: "https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/McDonald%27s_Golden_Arches.svg/1200px-McDonald%27s_Golden_Arches.svg.png"))
        array.append(SingleItemData(title: "Hasta", subtitle: "$ 200", iconImageUrl: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRY0eFECzyTCa83gOV3smCYDOSIggdUxSPirwtt5rS3LcWlzefo"))
        array.append(SingleItemData(title: "Hasta", subtitle: "$ 200", iconImageUrl: "https://upload.wikimedia.org/wikipedia/commons/b/b3/Logo-freddo.jpg"))
        array.append(SingleItemData(title: "Hasta", subtitle: "$ 200", iconImageUrl: "https://urbancomunicacion.com/wp-content/uploads/2017/04/Logotipos-famosos-Starbucks-Urban-comunicacion-1.png"))
        array.append(SingleItemData(title: "Hasta", subtitle: "$ 200", iconImageUrl: "https://www.stickpng.com/assets/images/5a1c3211f65d84088faf13e8.png"))
        array.append(SingleItemData(title: "Hasta", subtitle: "$ 200", iconImageUrl: "https://pbs.twimg.com/profile_images/1124417403566395394/9Wuzg8pf.png"))
        return array
    }
}

SingleItem 协议

此协议/接口代表 MLBusinessDiscountBoxView 的每个单元格元素。每个元素包含 imageUrl、标题、副标题、deepLinkItem 和 trackId。

定义

@objc public protocol MLBusinessSingleItemProtocol: NSObjectProtocol {
    @objc func titleForItem() -> String
    @objc func subtitleForItem() -> String
    @objc func iconImageUrlForItem() -> String
    @objc func deepLinkForItem() -> String?
    @objc func trackIdForItem() -> String?
}

示例中实现 MLBusinessSingleItemProtocol

class SingleItemData: NSObject {
    let title: String
    let subTitle: String
    let iconUrl: String
    let deepLink: String?
    let trackId: String?

    init(title: String, subtitle: String, iconImageUrl: String, deepLink: String? = nil, trackId: String? = nil) {
        self.title = title
        self.subTitle = subtitle
        self.iconUrl = iconImageUrl
        self.deepLink = deepLink
        self.trackId = trackId
    }
}

extension SingleItemData: MLBusinessSingleItemProtocol {
    func titleForItem() -> String {
        return title
    }

    func subtitleForItem() -> String {
        return subTitle
    }

    func iconImageUrlForItem() -> String {
        return iconUrl
    }

    func deepLinkForItem() -> String? {
        return deepLink
    }

    func trackIdForItem() -> String? {
        return trackId
    }
}

如何接收带 deep link 和 trackId 的项目点击动作?

当用户按下组件中的项目时,您可以收到通知,并接收之前在 MLBusinessSingleItemProtocol 中发送的 Deeplink、trackId 和项目索引。

discountView.addTapAction { (selectedIndex, deepLink, trackId) in
   print(selectedIndex)
}

如何更新组件数据?

为了保持相同的引用并只更新数据和布局,您可以使用更新方法。 MLBusinessDiscountBoxView

discountView.update(_ MLBusinessDiscountBoxData)

3️⃣- MLBusinessDividingLineView 组件

该组件允许您绘制分割线以分隔视图。例如,它可以用来自分隔 MLBusinessLoyaltyRingView 组件和 MLBusinessDownloadAppView 组件。

视觉示例

MLBusinessDividingLineView

MLBusinessDividingLineView 初始化

init 方法接收一个名为 'hasTriangle' 的可选参数。此参数默认为 'false'。当此参数被发送为 'true' 时,将绘制一个带向下三角形的矩形线。反之,只显示单一直线。

let dividingLineView = MLBusinessDividingLineView(hasTriangle: true)
view.addSubview(dividingLineView)

/* 
    Set your constraints. You don't have to set up the HEIGHT contraint. 
*/
NSLayoutConstraint.activate([
    dividingLineView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    dividingLineView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    dividingLineView.topAnchor.constraint(equalTo: view.topAnchor)
])

4️⃣- MLBusinessDownloadAppView 组件

该组件允许您展示一个包含应用图标(ML 或 MP)、标题和可操作按钮的视图,以便下载应用。

视觉示例

MLBusinessDownloadAppView

MLBusinessDownloadAppView 初始化

您需要设置 MLBusinessDownloadAppData 协议。这个接口允许您将绘制数据填充到组件中(appSite、标题、按钮标题和按钮深度链接,它们都是必需的)。

// DownloadAppData() is an implementation of MLBusinessDownloadAppData protocol.
let downloadAppView = MLBusinessDownloadAppView(DownloadAppData())
view.addSubview(downloadAppView)

/* 
    Set your constraints. You don't need to set up the HEIGHT contraint. 
    Because this component is responsible for knowing and setting its own HEIGHT.
*/
NSLayoutConstraint.activate([
    downloadAppView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
    downloadAppView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
    downloadAppView.topAnchor.constraint(equalTo: targetView.bottomAnchor, constant: 16)
])

MLBusinessDownloadAppData 协议

此协议允许您提供正确的数据来绘制 MLBusinessDownloadAppView。您必须设置以下数据:appSite(ML 或 MP)、标题、按钮标题和按钮深度链接。

定义

@objc public protocol MLBusinessDownloadAppData: NSObjectProtocol {
    @objc func getAppSite() -> MLBusinessDownloadAppView.AppSite
    @objc func getTitle() -> String
    @objc func getButtonTitle() -> String
    @objc func getButtonDeepLink() -> String
}

DownloadAppData 示例中 MLBusinessDownloadAppData 的实现

class DownloadAppData: NSObject, MLBusinessDownloadAppData {

    func getAppSite() -> MLBusinessDownloadAppView.AppSite {
        return MLBusinessDownloadAppView.AppSite.MP
    }
    func getTitle() -> String {
        return "Exclusivo con la app de Mercado Pago"
    }
    func getButtonTitle() -> String {
        return "Descargar"
    }
    func getButtonDeepLink() -> String {
        return "http://mercadopago"
    }
}

如何接收带有深度链接的项目的点击事件?

当用户按下下载按钮时,您可以接收在 MLBusinessDownloadAppData 中之前发送的深度链接。

downloadAppView.addTapAction { (deepLink) in
   print(deepLink)
}

如何更改下载应用视图背景?

使用 setBackgroundColor 方法。

downloadAppView.setBackgroundColor(.red)

如何更改下载应用视图默认圆角半径?

使用 setCornerRadius 方法。

downloadAppView.setCornerRadius(0)

5️⃣- MLBusinessCrossSellingBoxView 组件

该组件允许你显示包含图像图标、文本和操作按钮的视图。

视觉示例

MLBusinessCrossSellingBoxView

MLBusinessCrossSellingBoxView 初始化

你需要设置 MLBusinessCrossSellingBoxData 协议。此接口允许你将绘制数据填充到组件中(图标URL、文本、按钮标题和按钮深链接,均为必填项)。

// CrossSellingBoxData() is an implementation of MLBusinessCrossSellingBoxData protocol.
let crossSellingBoxView = MLBusinessCrossSellingBoxView(CrossSellingBoxData())
view.addSubview(crossSellingBoxView)

/* 
    Set your constraints. You don't need to set up the HEIGHT contraint. 
    Because this component is responsible for knowing and setting its own HEIGHT.
*/
NSLayoutConstraint.activate([
    crossSellingBoxView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
    crossSellingBoxView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
    crossSellingBoxView.topAnchor.constraint(equalTo: targetView.bottomAnchor, constant: 16)
])

MLBusinessCrossSellingBoxData 协议

该协议允许您提供正确数据来绘制 MLBusinessCrossSellingBoxView。您必须设置以下数据:iconUrl、text、buttonTitle 和 buttonDeepLink。

定义

@objc public protocol MLBusinessCrossSellingBoxData: NSObjectProtocol {
    @objc func getIconUrl() -> String
    @objc func getText() -> String
    @objc func getButtonTitle() -> String
    @objc func getButtonDeepLink() -> String
}

MLBusinessCrossSellingBoxData 在 CrossSellingBoxData 示例中的实现

class CrossSellingBoxData: NSObject, MLBusinessCrossSellingBoxData {

    func getIconUrl() -> String {
        return "https://urbancomunicacion.com/wp-content/uploads/2017/04/Logotipos-famosos-Starbucks-Urban-comunicacion-1.png"
    }
    func getText() -> String {
        return "Ganá $ 50 de regalo para tus pagos diarios"
    }
    func getButtonTitle() -> String {
        return "Invita a más amigos a usar la app"
    }
    func getButtonDeepLink() -> String {
        return "https://mercadopago-crossSelling"
    }
}

如何接收带深链接的项目点击操作?

当用户按下可执行的按钮时,您可以收到在 MLBusinessCrossSellingBoxData 中之前发送的深链接。

crossSellingBoxView.addTapAction { (deepLink) in
    print(deepLink)
}

6️⃣- MLBusinessLoyaltyHeaderView 组件

此组件允许您显示积分进度环、标题和副标题。

视觉示例

loyaltyHeader

// LoyaltyHeaderData() is an implementation of MLBusinessLoyaltyHeaderData protocol.
let loyaltyHeaderView = MLBusinessLoyaltyHeaderView(LoyaltyHeaderData(), fillPercentProgress: true)
containerView.addSubview(loyaltyHeaderView)

/* 
Set your constraints. You don't need to set up the HEIGHT contraint. 
Because this component is responsible for knowing and setting its own HEIGHT.
*/
NSLayoutConstraint.activate([
loyaltyHeaderView.topAnchor.constraint(equalTo: targetView.bottomAnchor, constant: 16),
loyaltyHeaderView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
loyaltyHeaderView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16)
])
return loyaltyHeaderView
])

MLBusinessLoyaltyHeaderData 协议

本协议允许您提供绘制 MLBusinessLoyaltyHeaderView 所需的适当数据。您必须设置以下数据

定义

@objc public protocol MLBusinessLoyaltyHeaderData: NSObjectProtocol {
@objc func getBackgroundHexaColor() -> String
@objc func getPrimaryHexaColor() -> String
@objc func getSecondaryHexaColor() -> String
@objc func getRingNumber() -> Int
@objc func getRingPercentage() -> Float
@objc func getTitle() -> String
@objc func getSubtitle() -> String
}

在 LoyaltyHeaderData 示例中实现 MLBusinessLoyaltyHeaderData

import MLBusinessComponents

class LoyaltyHeaderData: NSObject, MLBusinessLoyaltyHeaderData {
func getBackgroundHexaColor() -> String {
return "1AC2B0"
}

func getPrimaryHexaColor() -> String {
return "FFFFFF"
}

func getSecondaryHexaColor() -> String {
return "65A69E"
}

func getRingNumber() -> Int {
return 4
}

func getRingPercentage() -> Float {
return 0.8
}

func getTitle() -> String {
return "Beneficios"
}

func getSubtitle() -> String {
return "Nivel 4 - Mercado Puntos"
}
}

7️⃣MLBusinessItemDescriptionView 组件

该组件允许您显示一个图标和标题。

视觉示例

iconDescription

// ItemDescriptionData() is an implementation of MLBusinessItemDescriptionData protocol.
let itemDescriptionView = MLBusinessItemDescriptionView(ItemDescriptionData())
containerView.addSubview(itemDescriptionView)

/* 
Set your constraints. You don't need to set up the HEIGHT contraint. 
Because this component is responsible for knowing and setting its own HEIGHT.
*/
NSLayoutConstraint.activate([
            itemDescriptionView.topAnchor.constraint(equalTo: targetView.bottomAnchor, constant: 16),
            itemDescriptionView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),
            itemDescriptionView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -16)
            ])

MLBusinessItemDescriptionData 协议

本协议允许您提供绘制 MLBusinessItemDescriptionView 所需的适当数据。您必须设置以下数据

定义

@objc func getTitle() -> String
@objc func getIconImageURL() -> String
@objc func getIconHexaColor() -> String

MLBusinessItemDescriptionData在项目描述数据示例中的实现

import MLBusinessComponents

final class ItemDescriptionData: NSObject, MLBusinessItemDescriptionData {

    func getTitle() -> String {
        return "Envíos gratis desde $ 1.999"
    }

    func getIconImageURL() -> String {
        return "https://http2.mlstatic.com/static/org-img/loyalty/benefits/mobile/ic-shipping-discount-64.png"
    }

    func getIconHexaColor() -> String {
        return "1AC2B0"
    }
}

8️⃣- MLBusinessAnimatedButton组件

此组件允许您显示一个动画按钮。当您按下它时,它变成一个圆圈,然后扩展到整个屏幕。

视觉示例

AnimatedButton

/* 
To implement this component we only need to initialize it with a String for its normal state 
and another for its load state.
*/

let animatedButton = MLBusinessAnimatedButton(normalLabel: "Normal", loadingLabel: "Loading")
containerView.addSubview(animatedButton)

/* 
Set your constraints. You don't need to set up the HEIGHT contraint. 
Because this component is responsible for knowing and setting its own HEIGHT.
*/

NSLayoutConstraint.activate([
animatedButton.topAnchor.constraint(equalTo: targetView.bottomAnchor, constant: 16),
animatedButton.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16),
animatedButton.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -16)
])

// To start the animation we must call the method called startLoading().
animatedButton.startLoading()

/* 
To end the animation we must call the method called finishLoading(color: UIColor, image: UIImage)
Where we can set the color with which it will expand
and an optional image that will be displayed on the button when it becomes circular.
*/
animatedButton.finishLoading(color: .green, image: nil)

/*
Additionally, the component provides us with a function to push the next view controller with a Fade effect.
*/
animatedButton.goToNextViewController(newViewController, navigationController)

MLBusinessAnimatedButtonDelegate

此协议允许您在动画结束后执行操作,并在可能超时的情况下。

定义

@objc func didFinishAnimation(_ animatedButton: MLBusinessAnimatedButton)
@objc func progressButtonAnimationTimeOut()
@objc optional func expandAnimationInProgress()

MLBusinessAnimatedButtonDelegate的实现

import MLBusinessComponents

extension ViewController: MLBusinessAnimatedButtonDelegate {
    func didFinishAnimation(_ animatedButton: MLBusinessAnimatedButton) {
        guard let navigationController = navigationController else { return }

        let newVC = UIViewController()
        newVC.view.backgroundColor = .red

        animatedButton.goToNextViewController(newVC, navigationController)
    }

    func progressButtonAnimationTimeOut() {
        print("TimeOut")
    }

    func expandAnimationInProgress() {
        navigationController?.setNavigationBarHidden(true, animated: true)
    }
}

🔠字体和颜色自定义。

我们使用MLUI开源库来自定义强调颜色和字体标签。要更改这些值,请查看MLUI样式表协议的文档。https://github.com/mercadolibre/fury_mobile-ios-ui

😉下一步是什么?

  • Bitrise用于发布。
  • Codebeat集成。
  • 快照测试用例。
  • SwiftLint。
  • 迁移到Swift 5。
  • iOS13暗黑模式变体。
  • Swift包管理器支持。
  • SwiftUI桥梁/ UIKit <-> SwiftUI。

📋支持的操作系统和SDK版本

  • iOS 10.0+
  • Swift 4.2
  • xCode 9.2+
  • @Objc全面兼容性

🔮项目示例

该项目包含一个使用MLBusinessComponents基本组件的Swift示例项目。

❤️反馈

  • 欢迎使用贡献或发送反馈。Fork此项目并提交您自己的修复、建议,然后提交带有更改的pull request。

👨‍💻 作者

👮‍ License

MIT License

Copyright (c) 2019 - Mercado Pago / Mercado Libre

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.