diff --git a/android/src/main/kotlin/sakebook/github/com/native_ads/UnifiedAdLayout.kt b/android/src/main/kotlin/sakebook/github/com/native_ads/UnifiedAdLayout.kt index 218c5fc..c4f4916 100644 --- a/android/src/main/kotlin/sakebook/github/com/native_ads/UnifiedAdLayout.kt +++ b/android/src/main/kotlin/sakebook/github/com/native_ads/UnifiedAdLayout.kt @@ -17,12 +17,13 @@ import com.google.android.gms.ads.formats.UnifiedNativeAdView import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.platform.PlatformView +import android.graphics.Color class UnifiedAdLayout( - context: Context, - messenger: BinaryMessenger, - id: Int, - arguments: HashMap + context: Context, + messenger: BinaryMessenger, + id: Int, + arguments: HashMap ) : PlatformView { private val hostPackageName = arguments["package_name"] as String @@ -43,17 +44,36 @@ class UnifiedAdLayout( private var ad: UnifiedNativeAd? = null init { + (arguments["headline_font_size"] as Double?)?.toFloat()?.let(headlineView::setTextSize) + (arguments["headline_font_color"] as String?)?.let(Color::parseColor)?.let(headlineView::setTextColor) + + (arguments["body_font_size"] as Double?)?.toFloat()?.let(bodyView::setTextSize) + (arguments["body_font_color"] as String?)?.let(Color::parseColor)?.let(bodyView::setTextColor) + + (arguments["call_to_action_font_size"] as Double?)?.toFloat()?.let(callToActionView::setTextSize) + (arguments["call_to_action_font_color"] as String?)?.let(Color::parseColor)?.let(callToActionView::setTextColor) + (arguments["call_to_action_background_color"] as String?)?.let(Color::parseColor)?.let(callToActionView::setBackgroundColor) + val ids = arguments["test_devices"] as MutableList? val configuration = RequestConfiguration.Builder().setTestDeviceIds(ids).build() MobileAds.setRequestConfiguration(configuration) - unifiedNativeAdView.findViewById(context.resources.getIdentifier("flutter_native_ad_attribution", "id", hostPackageName)).apply { - this.text = arguments["text_attribution"] as String - } + unifiedNativeAdView.findViewById(context.resources.getIdentifier("flutter_native_ad_attribution", "id", hostPackageName)) + .let { attributuionView -> + (arguments["text_attribution"] as String)?.let { attributuionView.setText(it) } + (arguments["attribution_view_font_size"] as Double?)?.toFloat()?.let { attributuionView?.setTextSize(it) } + (arguments["attribution_view_font_color"] as String?)?.let(Color::parseColor)?.let { attributuionView?.setTextColor(it) } + } + AdLoader.Builder(context, arguments["placement_id"] as String) .forUnifiedNativeAd { ad = it + ensureUnifiedAd(it) + + (arguments["background_color"] as String?)?.let(Color::parseColor)?.let { backgroundColor -> + unifiedNativeAdView?.setBackgroundColor(backgroundColor) + } } .withAdListener(object : AdListener() { override fun onAdImpression() { @@ -129,4 +149,4 @@ class UnifiedAdLayout( unifiedNativeAdView.setNativeAd(ad) } -} \ No newline at end of file +} diff --git a/example/lib/native_ad_view_wrapper.dart b/example/lib/native_ad_view_wrapper.dart index c62caf0..693c9d5 100644 --- a/example/lib/native_ad_view_wrapper.dart +++ b/example/lib/native_ad_view_wrapper.dart @@ -26,7 +26,19 @@ class NativeAdViewWrapperState extends State ..packageName = "sakebook.github.com.native_ads_example" ..layoutName = "native_ad_layout" ..attributionText = "AD" - ..testDevices = ["00000000000000000000000000000000"], + ..testDevices = ["00000000000000000000000000000000"] + ..headlineFontSize = 32.0 + ..headlineFontColor = const Color.fromARGB(0xFF, 0xFF, 0x80, 0x00) + ..bodyFontSize = 32.0 + ..bodyFontColor = const Color.fromARGB(0xFF, 0x00, 0xFF, 0x80) + ..attributionViewFontSize = 32.0 + ..attributionViewFontColor = + const Color.fromARGB(0xFF, 0x80, 0x00, 0xFF) + ..callToActionFontSize = 32.0 + ..callToActionFontColor = const Color.fromARGB(0xFF, 0xFF, 0xF0, 0x00) + ..callToActionBackgroundColor = + const Color.fromARGB(0xFF, 0x00, 0xFF, 0xFF) + ..backgroundColor = const Color.fromARGB(0xFF, 0xFF, 0x00, 0xFF), iosParam: IOSParam() ..placementId = "ca-app-pub-3940256099942544/3986624511" // test ..bundleId = "sakebook.github.com.nativeAdsExample" diff --git a/ios/Classes/Extensions.swift b/ios/Classes/Extensions.swift new file mode 100644 index 0000000..2530ec3 --- /dev/null +++ b/ios/Classes/Extensions.swift @@ -0,0 +1,42 @@ +import UIKit + +extension UIColor { + + convenience init(hex: Int) { + self.init(hex: hex, a: 1.0) + } + + convenience init(hex: Int, a: CGFloat) { + self.init(r: (hex >> 16) & 0xff, g: (hex >> 8) & 0xff, b: hex & 0xff, a: a) + } + + convenience init(r: Int, g: Int, b: Int) { + self.init(r: r, g: g, b: b, a: 1.0) + } + + convenience init(r: Int, g: Int, b: Int, a: CGFloat) { + self.init(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: a) + } + + convenience init?(hexString: String) { + let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int = UInt64() + Scanner(string: hex).scanHexInt64(&int) + let a, r, g, b: UInt64 + switch hex.count { + case 3: // RGB (12-bit) + (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: // RGB (24-bit) + (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: // ARGB (32-bit) + (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (a, r, g, b) = (255, 0, 0, 0) + } + self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255) + } + + static func fromHex(_ hexString: String) -> UIColor { + return UIColor(hexString: hexString) ?? .clear + } +} diff --git a/ios/Classes/UnifiedAdLayout.swift b/ios/Classes/UnifiedAdLayout.swift index 0d85994..ae6d161 100644 --- a/ios/Classes/UnifiedAdLayout.swift +++ b/ios/Classes/UnifiedAdLayout.swift @@ -57,6 +57,7 @@ class UnifiedAdLayout : NSObject, FlutterPlatformView { unifiedNativeAdView = adView super.init() mappingView() + configureView() fetchAd() } @@ -78,6 +79,39 @@ class UnifiedAdLayout : NSObject, FlutterPlatformView { priceView = unifiedNativeAdView.priceView as? UILabel advertiserView = unifiedNativeAdView.advertiserView as? UILabel } + + private func configureView() { + if let headlineFontSize = self.args["headline_font_size"] as? Double { + headlineView.font = .systemFont(ofSize: CGFloat(headlineFontSize)) + } + if let headlineFontColor = self.args["headline_font_color"] as? String { + headlineView.textColor = .fromHex(headlineFontColor) + } + if let bodyFontSize = self.args["body_font_size"] as? Double { + bodyView.font = .systemFont(ofSize: CGFloat(bodyFontSize)) + } + if let bodyFontSize = self.args["body_font_color"] as? String { + bodyView.textColor = .fromHex(bodyFontSize) + } + if let attributionViewFontSize = self.args["attribution_view_font_size"] as? Double { + attributionView.font = .systemFont(ofSize: CGFloat(attributionViewFontSize)) + } + if let attributionViewFontColor = self.args["attribution_view_font_color"] as? String { + attributionView.textColor = .fromHex(attributionViewFontColor) + } + if let callToActionFontSize = self.args["call_to_action_font_size"] as? Double { + callToActionView.font = .systemFont(ofSize: CGFloat(callToActionFontSize)) + } + if let callToActionFontColor = self.args["call_to_action_font_color"] as? String { + callToActionView.textColor = .fromHex(callToActionFontColor) + } + if let callToActionBackgroundColor = self.args["call_to_action_background_color"] as? String { + callToActionView.backgroundColor = .fromHex(callToActionBackgroundColor) + } + if let backgroundColor = self.args["background_color"] as? String { + self.view().backgroundColor = .fromHex(backgroundColor) + } + } private func fetchAd() { adLoader.delegate = self diff --git a/lib/native_ad_param.dart b/lib/native_ad_param.dart index 2b2d558..f6d5c75 100644 --- a/lib/native_ad_param.dart +++ b/lib/native_ad_param.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + /// Android parameter for ad. class AndroidParam { /// AdMob placement id. @@ -15,6 +17,26 @@ class AndroidParam { /// Test device ids. List testDevices; + //Ad Title + double headlineFontSize; + Color headlineFontColor; + + //Ad description + double bodyFontSize; + Color bodyFontColor; + + // "AD" Label + double attributionViewFontSize; + Color attributionViewFontColor; + + // Button + double callToActionFontSize; + Color callToActionFontColor; + Color callToActionBackgroundColor; + + Color backgroundColor; + + /// Converts this param to a Map dynamic toMap() { return { @@ -23,8 +45,23 @@ class AndroidParam { 'layout_name': layoutName, 'text_attribution': attributionText, 'test_devices': testDevices, + 'headline_font_size': headlineFontSize, + 'headline_font_color': _toAndroidColor(headlineFontColor), + 'body_font_size': bodyFontSize, + 'body_font_color': _toAndroidColor(bodyFontColor), + 'attribution_view_font_size': attributionViewFontSize, + 'attribution_view_font_color': _toAndroidColor(attributionViewFontColor), + 'call_to_action_font_size': callToActionFontSize, + 'call_to_action_font_color': _toAndroidColor(callToActionFontColor), + 'call_to_action_background_color': _toAndroidColor(callToActionBackgroundColor), + 'background_color': _toAndroidColor(backgroundColor) }; } + + String _toAndroidColor(Color color) => + color == null + ? null + : '#' + color.value.toRadixString(16); } /// iOS parameter for ad. @@ -44,6 +81,25 @@ class IOSParam { /// Test device ids. List testDevices; + //Ad Title + double headlineFontSize; + String headlineFontColor; + + //Ad description + double bodyFontSize; + String bodyFontColor; + + // "AD" Label + double attributionViewFontSize; + String attributionViewFontColor; + + // Button + double callToActionFontSize; + String callToActionFontColor; + String callToActionBackgroundColor; + + String backgroundColor; + /// Converts this param to a Map dynamic toMap() { return { @@ -52,6 +108,16 @@ class IOSParam { 'layout_name': layoutName, 'text_attribution': attributionText, 'test_devices': testDevices, + 'headline_font_size': headlineFontSize, + 'headline_font_color': headlineFontColor, + 'body_font_size': bodyFontSize, + 'body_font_color': bodyFontColor, + 'attribution_view_font_size': attributionViewFontSize, + 'attribution_view_font_color': attributionViewFontColor, + 'call_to_action_font_size': callToActionFontSize, + 'call_to_action_font_color': callToActionFontColor, + 'call_to_action_background_color': callToActionBackgroundColor, + 'background_color': backgroundColor }; } }