{"id":1559,"date":"2019-10-10T16:45:05","date_gmt":"2019-10-10T14:45:05","guid":{"rendered":"http:\/\/productcrafters.io\/blog\/?p=1559"},"modified":"2026-01-19T23:04:47","modified_gmt":"2026-01-19T21:04:47","slug":"creating-custom-react-native-ui-components-android","status":"publish","type":"post","link":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/","title":{"rendered":"Creating custom React Native UI components [Android]"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">In the process of learning and growing as a React Native developer, at some point in your career you\u2019ll get to the point when you get a task that requires more specific\/exotic functionality than React Native abstractions can offer at that point of time. E.g. you need to use some library written in another language (C++, Obj-C, Swift, Java, Kotlin&#8230;) and there is no existing RN wrapper for this library. Or you need to create some fancy UI component which is hard to do on your own, but you know that there are plenty of UI libraries for that platform that can do exactly what you need in a couple of code lines. There could be even more examples of such scenarios, but the point is:<\/span><\/p>\n<blockquote><p><span style=\"font-weight: 400;\">&#8220;Sometimes you might come to a task that slightly differs from the regular workflow, and React Native doesn\u2019t provide required tools out of the box, and third party modules for solving this kind of problems do not exist, or you doubt their reliability&#8221;<\/span><\/p><\/blockquote>\n<p><span style=\"font-weight: 400;\">That\u2019s what I faced on one of my recent projects. Hopefully, for such cases, <a href=\"https:\/\/facebook.github.io\/react-native\/docs\/native-modules-android\">React Native<\/a> provides a pretty comfortable way to integrate your own native modules to the project.<\/span><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_77 counter-flat ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#Problem\" >Problem<\/a><\/li><li class='ez-toc-page-1'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#General_Guideline\" >General Guideline\u00a0<\/a><\/li><li class='ez-toc-page-1'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#Creating_custom_ImageView\" >Creating custom ImageView<\/a><\/li><li class='ez-toc-page-1'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#Creating_custom_ViewManager\" >Creating custom ViewManager<\/a><\/li><li class='ez-toc-page-1'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#Add_your_custom_UI_component_to_the_global_RN_native_modules_registry\" >Add your custom UI component to the global RN native modules registry<\/a><\/li><li class='ez-toc-page-1'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#Using_your_custom_native_UI_component_in_JS\" >Using your custom native UI component in JS\u00a0<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Problem\"><\/span><b>Problem<\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Firstly, I needed to perform contrast changing for an image by dragging the slider. Secondly, to achieve better performance by avoiding serialization and sending data over the <\/span>RN Bridge<span style=\"font-weight: 400;\">, I needed to display the processed image right on the \u2018native\u2019 side with <a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/uiimageview?changes=_4&amp;language=objc\">UIImageView<\/a>\/<a href=\"https:\/\/developer.android.com\/reference\/android\/support\/v7\/widget\/AppCompatImageView\">AppCompatImageView<\/a> (for iOS and Android respectively). That\u2019s exactly what we\u2019re going to build by the end of this article.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">\u00a0For the task of changing image contrast, I decided to use <a href=\"https:\/\/opencv.org\/\">OpenCV<\/a> library, which is written in C++. The process of integrating OpenCV in native code for Java and Objective-C is described in details in <\/span><strong><a href=\"https:\/\/brainhub.eu\/blog\/opencv-react-native-image-processing\">this beautiful article<\/a><\/strong><span style=\"font-weight: 400;\"> by Piotr Suwala.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Now with <a href=\"https:\/\/opencv.org\/\">OpenCV<\/a> library set up, we\u2019re ready to create our native UI module that will use it. I want to create an <\/span><span style=\"font-weight: 400;\">Image<\/span><span style=\"font-weight: 400;\"> UI component which fetches picture from the received <\/span><code>url<\/code><span style=\"font-weight: 400;\">, processes and displays it with the defined <\/span><span style=\"font-weight: 400;\">contrast<\/span><span style=\"font-weight: 400;\">. This view also should receive <\/span><code>resizeMode<\/code><span style=\"font-weight: 400;\"> to remain visually consistent between iOS and Android. <\/span><\/p>\n<figure id=\"attachment_1566\" aria-describedby=\"caption-attachment-1566\" style=\"width: 303px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\" wp-image-1566\" src=\"http:\/\/productcrafters.io\/blog\/wp-content\/uploads\/2026\/01\/Final-demo-screenshot.webp\" alt=\"Final demo screenshot\" width=\"303\" height=\"560\" \/><figcaption id=\"caption-attachment-1566\" class=\"wp-caption-text\">Final demo screenshot<\/figcaption><\/figure>\n<p>Link to the demo repo: <a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\">https:\/\/github.com\/ProductCrafters\/rn-contrast-changer<\/a><\/p>\n<h2><span class=\"ez-toc-section\" id=\"General_Guideline\"><\/span><b>General Guideline\u00a0<\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span style=\"font-weight: 400;\">General guidelines for creating custom native UI components are:\u00a0<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Create your custom <\/span>View<span style=\"font-weight: 400;\"> by subclassing native <\/span><span style=\"font-weight: 400;\">ImageView<\/span><span style=\"font-weight: 400;\"> class of your platform (<\/span><a href=\"https:\/\/developer.android.com\/reference\/android\/support\/v7\/widget\/AppCompatImageView\">AppCompatImageView<\/a><span style=\"font-weight: 400;\">\/<\/span><a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/uiimageview?changes=_4&amp;language=objc\">UIImageView<\/a><span style=\"font-weight: 400;\"> for Android and iOS respectively). Add private <\/span><code>fetchedImageData<\/code><span style=\"font-weight: 400;\">\u00a0property, also add <\/span><code>url<\/code><span style=\"font-weight: 400;\">, <\/span><code>contrast<\/code><span style=\"font-weight: 400;\">, <\/span><code>resizeMode<\/code><span style=\"font-weight: 400;\"> public props with corresponding setters, so that on changing <\/span>url<span style=\"font-weight: 400;\"> value the <\/span>fetchedImageData<span style=\"font-weight: 400;\">\u00a0will be re-fetched, and on <\/span>contrast<span style=\"font-weight: 400;\"> changing the <\/span>fetchedImageData<span style=\"font-weight: 400;\"> will be re-processed and re-drawn.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Create the <\/span>ViewManager<span style=\"font-weight: 400;\"> for your custom <\/span>View<span style=\"font-weight: 400;\"> by subclassing ReactNative <\/span><span style=\"font-weight: 400;\">ViewManager<\/span><span style=\"font-weight: 400;\"> wrapper class (<\/span><a href=\"https:\/\/facebook.github.io\/react-native\/docs\/native-components-android#1-create-the-viewmanager-subclass\">SimpleViewManager<\/a><span style=\"font-weight: 400;\">\/<\/span><a href=\"https:\/\/facebook.github.io\/react-native\/docs\/native-components-ios#ios-mapview-example\">RCTViewManager<\/a><span style=\"font-weight: 400;\"> for Android and iOS respectively). In your custom ViewManager override <\/span>createView<span style=\"font-weight: 400;\"> method (<\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageManager.java#L15\">createViewInstance<\/a><span style=\"font-weight: 400;\">\/<\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/ios\/OpenCV\/RNContrastChangingImageManager.h#L6\">RCTViewManager<\/a><span style=\"font-weight: 400;\"> for Android and iOS respectively), and also declare <\/span><span style=\"font-weight: 400;\">ReactViewProp<\/span><span style=\"font-weight: 400;\"> methods that will expose your custom View\u2019s properties and will call it\u2019s correspondent property setters.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Create the package with your custom <\/span>ViewManager<span style=\"font-weight: 400;\"> subclassed from <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImagePackage.java#L11\">ReactPackage<\/a><span style=\"font-weight: 400;\">. Add your package to the global ReactNative native modules registry.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">For more details read farther through the post. So, let\u2019s start with Android.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Creating_custom_ImageView\"><\/span><b>Creating custom ImageView<\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Our first step is to create our own <\/span><span style=\"font-weight: 400;\">ImageView<\/span><span style=\"font-weight: 400;\">. Before moving forward, just take a slight glance at the <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageView.java\"><span style=\"font-weight: 400;\">final file of custom ImageView class<\/span><\/a><span style=\"font-weight: 400;\"> to get a general idea of what\u2019s going on.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Viewing code in the file above, you might come to a question, why did we subclass <\/span><a href=\"https:\/\/developer.android.com\/reference\/android\/support\/v7\/widget\/AppCompatImageView\"><span style=\"font-weight: 400;\">AppCompatImageView<\/span><\/a><span style=\"font-weight: 400;\"> and not <\/span><a href=\"https:\/\/developer.android.com\/reference\/android\/widget\/ImageView.html\"><span style=\"font-weight: 400;\">ImageView<\/span><\/a><span style=\"font-weight: 400;\"> ? Firstly, because <\/span><a href=\"https:\/\/developer.android.com\/reference\/android\/support\/v7\/widget\/AppCompatImageView\"><span style=\"font-weight: 400;\">AppCompatImageView<\/span><\/a><span style=\"font-weight: 400;\"> is very like<\/span> <a href=\"https:\/\/developer.android.com\/reference\/android\/widget\/ImageView.html\"><span style=\"font-weight: 400;\">ImageView<\/span><\/a><span style=\"font-weight: 400;\">, but it also supports compatible features on older versions of the Android platform. Secondly, just because Android Studio gives you that annoying yellow warning when you try to use <\/span><a href=\"https:\/\/developer.android.com\/reference\/android\/widget\/ImageView.html\"><span style=\"font-weight: 400;\">ImageView<\/span><\/a><span style=\"font-weight: 400;\"> instead of <\/span><a href=\"https:\/\/developer.android.com\/reference\/android\/support\/v7\/widget\/AppCompatImageView\"><span style=\"font-weight: 400;\">AppCompatImageView<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageView.java\">Here<\/a> besides the default constructor, you can notice three self-explanatory private variables.<\/span><\/p>\n<pre><code class=\"js\"><b>  private <\/b><span style=\"font-weight: 400;\">Bitmap <\/span><b>fetchedImageData <\/b><span style=\"font-weight: 400;\">= <\/span><b>null<\/b><span style=\"font-weight: 400;\">;\r\n<b>   private <\/b>String <b>fetchUrl <\/b>= <b>null<\/b>;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>private double <\/b><b>contrast <\/b><span style=\"font-weight: 400;\">= <\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">;<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public <\/b><span style=\"font-weight: 400;\">RNContrastChangingImageView(Context context) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>super<\/b><span style=\"font-weight: 400;\">(context);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">There are also three setter methods for each of public properties (<\/span><code>url<\/code><span style=\"font-weight: 400;\">, <\/span><code>contrast<\/code><span style=\"font-weight: 400;\">, <\/span><code>resizeMode<\/code><span style=\"font-weight: 400;\">)<\/span><\/p>\n<pre><code class=\"js\"><b>\u00a0public void <\/b><span style=\"font-weight: 400;\">setFetchUrl(String imgUrl) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>if <\/b><span style=\"font-weight: 400;\">(imgUrl != <\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>fetchUrl<\/b><span style=\"font-weight: 400;\">) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>fetchUrl <\/b><span style=\"font-weight: 400;\">= imgUrl;<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0downloadImage(imgUrl);<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public void <\/b><span style=\"font-weight: 400;\">setContrast(<\/span><b>double <\/b><span style=\"font-weight: 400;\">contrastVal) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>contrast <\/b><span style=\"font-weight: 400;\">= contrastVal;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>if <\/b><span style=\"font-weight: 400;\">(<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>fetchedImageData <\/b><span style=\"font-weight: 400;\">!= <\/span><b>null<\/b><span style=\"font-weight: 400;\">) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.updateImageContrast();<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public void <\/b><span style=\"font-weight: 400;\">setResizeMode(String mode) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>switch <\/b><span style=\"font-weight: 400;\">(mode) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>case <\/b><b>\"cover\"<\/b><span style=\"font-weight: 400;\">:<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.setScaleType(ScaleType.<\/span><b><i>CENTER_CROP<\/i><\/b><span style=\"font-weight: 400;\">);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>break<\/b><span style=\"font-weight: 400;\">;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>case <\/b><b>\"stretch\"<\/b><span style=\"font-weight: 400;\">:<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.setScaleType(ScaleType.<\/span><b><i>FIT_XY<\/i><\/b><span style=\"font-weight: 400;\">);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>break<\/b><span style=\"font-weight: 400;\">;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>case <\/b><b>\"contain\"<\/b><span style=\"font-weight: 400;\">:<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>default<\/b><span style=\"font-weight: 400;\">:<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.setScaleType(ScaleType.<\/span><b><i>FIT_CENTER<\/i><\/b><span style=\"font-weight: 400;\">);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>break<\/b><span style=\"font-weight: 400;\">;<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0}<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">Here in setters we re-fetch the image in case the <\/span><code>url<\/code><span style=\"font-weight: 400;\"> prop has changed by calling our <\/span><code>downloadImage()<\/code><span style=\"font-weight: 400;\"> method, and also do the re-processing of image in case the <\/span><span style=\"font-weight: 400; color: #ff6600;\"><code>contrast<\/code><\/span><span style=\"font-weight: 400;\"> prop changing by calling our <\/span><code>updateImageContrast()<\/code><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageView.java#L89\">Interesting part<\/a> comes when we need to download the image from the <\/span><span style=\"font-weight: 400; color: #ff6600;\"><code>url<\/code><\/span><span style=\"font-weight: 400;\"> prop.<\/span><\/p>\n<pre><code class=\"js\"><b>private void <\/b><span style=\"font-weight: 400;\">downloadImage(String imgUrl) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0DownloadImage task = <\/span><b>new <\/b><span style=\"font-weight: 400;\">DownloadImage();<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Bitmap result = <\/span><b>null<\/b><span style=\"font-weight: 400;\">;<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>try <\/b><span style=\"font-weight: 400;\">{<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0result = task.execute(imgUrl).get();<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>catch <\/b><span style=\"font-weight: 400;\">(InterruptedException | ExecutionException e) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0e.printStackTrace();<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>fetchedImageData <\/b><span style=\"font-weight: 400;\">= result;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.setImageBitmap(result);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>class <\/b><span style=\"font-weight: 400;\">DownloadImage <\/span><b>extends <\/b><span style=\"font-weight: 400;\">AsyncTask&lt;String, Void, Bitmap&gt; {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@Override<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>protected <\/b><span style=\"font-weight: 400;\">Bitmap doInBackground(String... imgUrls) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0URL url;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0HttpURLConnection httpURLConnection;<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>try <\/b><span style=\"font-weight: 400;\">{<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0url = <\/span><b>new <\/b><span style=\"font-weight: 400;\">URL(imgUrls[<\/span><span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">]);<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0httpURLConnection = (HttpURLConnection) url.openConnection();<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0httpURLConnection.connect();<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0InputStream in =httpURLConnection.getInputStream();<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Bitmap myBitmap = BitmapFactory.<\/span><i><span style=\"font-weight: 400;\">decodeStream<\/span><\/i><span style=\"font-weight: 400;\">(in);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return <\/b><span style=\"font-weight: 400;\">myBitmap;<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>catch <\/b><span style=\"font-weight: 400;\">(MalformedURLException e) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0e.printStackTrace();<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return null<\/b><span style=\"font-weight: 400;\">;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} <\/span><b>catch <\/b><span style=\"font-weight: 400;\">(IOException e) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0e.printStackTrace();<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return null<\/b><span style=\"font-weight: 400;\">;<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">To avoid blocking of the main thread while fetching the image, we create our little <\/span><code>DownloadImage<\/code><span style=\"font-weight: 400;\"> class derived from <\/span><a href=\"https:\/\/developer.android.com\/reference\/android\/os\/AsyncTask.html\"><span style=\"font-weight: 400;\">AsyncTask<\/span><\/a><span style=\"font-weight: 400;\">, to download image in the background. In this class we override required method <\/span><a href=\"https:\/\/developer.android.com\/reference\/android\/os\/AsyncTask.html#doInBackground(Params...)\"><code>doInBackground()<\/code><\/a><span style=\"font-weight: 400;\">. It downloads the image form received URL and return it\u2019s <\/span><span style=\"font-weight: 400;\">Bitmap<\/span><span style=\"font-weight: 400;\"> data.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We use <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageView.java#L104\"><code>DownloadImage<\/code><\/a><span style=\"font-weight: 400;\"> class in our <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageView.java#L89\"><code>downloadImage()<\/code><\/a><span style=\"font-weight: 400;\"> method by creating the <\/span><span style=\"font-weight: 400;\">task<\/span><span style=\"font-weight: 400;\"> instance and execute it with received <\/span><code>imgUrl<\/code><span style=\"font-weight: 400;\"> prop. The result is stored to our private <\/span><code>fetchedImageData<\/code><span style=\"font-weight: 400;\"> field.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In<\/span> <a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageView.java#L62\"><code>updateImageContrast()<\/code><\/a><span style=\"font-weight: 400;\"> method we just do some image data transformations with <a href=\"https:\/\/opencv.org\/\">OpenCV<\/a> library which I googled for this task \ud83d\ude42<\/span><\/p>\n<pre><code class=\"js\"><b>private void <\/b><span style=\"font-weight: 400;\">updateImageContrast() {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>try <\/b><span style=\"font-weight: 400;\">{<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Mat matImage = <\/span><b>new <\/b><span style=\"font-weight: 400;\">Mat();<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Utils.<\/span><i><span style=\"font-weight: 400;\">bitmapToMat<\/span><\/i><span style=\"font-weight: 400;\">(<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>fetchedImageData<\/b><span style=\"font-weight: 400;\">, matImage);<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Scalar imgScalVec = Core.<\/span><i><span style=\"font-weight: 400;\">sumElems<\/span><\/i><span style=\"font-weight: 400;\">(matImage);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>double<\/b><span style=\"font-weight: 400;\">[] imgAvgVec = imgScalVec.<\/span><b>val<\/b><span style=\"font-weight: 400;\">;<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>for <\/b><span style=\"font-weight: 400;\">(<\/span><b>int <\/b><span style=\"font-weight: 400;\">i = <\/span><span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">; i &lt; imgAvgVec.<\/span><b>length<\/b><span style=\"font-weight: 400;\">; i++) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0imgAvgVec[i] = imgAvgVec[i] \/ (matImage.cols() * matImage.rows());<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>double <\/b><span style=\"font-weight: 400;\">imgAvg = (imgAvgVec[<\/span><span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">] + imgAvgVec[<\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">] + imgAvgVec[<\/span><span style=\"font-weight: 400;\">2<\/span><span style=\"font-weight: 400;\">]) \/ <\/span><span style=\"font-weight: 400;\">3<\/span><span style=\"font-weight: 400;\">;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>int <\/b><span style=\"font-weight: 400;\">brightness = -(<\/span><b>int<\/b><span style=\"font-weight: 400;\">) ((<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>contrast <\/b><span style=\"font-weight: 400;\">- <\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">) * imgAvg);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0matImage.convertTo(matImage, matImage.type(), <\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>contrast<\/b><span style=\"font-weight: 400;\">, brightness);<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Bitmap resultImage = Bitmap.<\/span><i><span style=\"font-weight: 400;\">createBitmap<\/span><\/i><span style=\"font-weight: 400;\">(<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>fetchedImageData<\/b><span style=\"font-weight: 400;\">.getWidth(),<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>fetchedImageData<\/b><span style=\"font-weight: 400;\">.getHeight(),<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.<\/span><b>fetchedImageData<\/b><span style=\"font-weight: 400;\">.getConfig()<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Utils.<\/span><i><span style=\"font-weight: 400;\">matToBitmap<\/span><\/i><span style=\"font-weight: 400;\">(matImage, resultImage);<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>this<\/b><span style=\"font-weight: 400;\">.setImageBitmap(resultImage);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0} <\/span><b>catch <\/b><span style=\"font-weight: 400;\">(Exception e) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0e.printStackTrace();<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">}<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">That\u2019s it for our custom <\/span><span style=\"font-weight: 400;\">ImageView<\/span><span style=\"font-weight: 400;\">. Let\u2019s move on to the manager class for our view.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Creating_custom_ViewManager\"><\/span><b>Creating custom ViewManager<\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span style=\"font-weight: 400;\">The next step is to create the manager class for our custom <\/span><span style=\"font-weight: 400;\">ImageView<\/span><span style=\"font-weight: 400;\">. The class is pretty small, so <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageManager.java\"><span style=\"font-weight: 400;\">here it is<\/span><\/a><span style=\"font-weight: 400;\">:<\/span><\/p>\n<pre><code class=\"js\"><b>public class <\/b><span style=\"font-weight: 400;\">RNContrastChangingImageManager <\/span><b>extends <\/b><span style=\"font-weight: 400;\">SimpleViewManager&lt;RNContrastChangingImageView&gt;{<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@Override<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public <\/b><span style=\"font-weight: 400;\">String getName() {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return <\/b><b>\"RNContrastChangingImage\"<\/b><span style=\"font-weight: 400;\">;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@Override<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>protected <\/b><span style=\"font-weight: 400;\">RNContrastChangingImageView createViewInstance(ThemedReactContext reactContext) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return new <\/b><span style=\"font-weight: 400;\">RNContrastChangingImageView(reactContext);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@ReactProp<\/span><span style=\"font-weight: 400;\">(name = <\/span><b>\"url\"<\/b><span style=\"font-weight: 400;\">)<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public void <\/b><span style=\"font-weight: 400;\">setFetchUrl(RNContrastChangingImageView view, String imgUrl) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0view.setFetchUrl(imgUrl);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@ReactProp<\/span><span style=\"font-weight: 400;\">(name = <\/span><b>\"contrast\"<\/b><span style=\"font-weight: 400;\">, defaultFloat = <\/span><span style=\"font-weight: 400;\">1f<\/span><span style=\"font-weight: 400;\">)<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public void <\/b><span style=\"font-weight: 400;\">setContrastValue(RNContrastChangingImageView view, <\/span><b>float <\/b><span style=\"font-weight: 400;\">contrast) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0view.setContrast(contrast);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@ReactProp<\/span><span style=\"font-weight: 400;\">(name = <\/span><b>\"resizeMode\"<\/b><span style=\"font-weight: 400;\">)<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public void <\/b><span style=\"font-weight: 400;\">setResizeMode(RNContrastChangingImageView view, String mode) {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0view.setResizeMode(mode);<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">}<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">In our custom <\/span><span style=\"font-weight: 400;\">ViewManager<\/span><span style=\"font-weight: 400;\"> we extend the generic <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageManager.java#L8\">SimpleViewManager<\/a><span style=\"font-weight: 400;\"> React Native class with the type parameter of our custom <\/span><span style=\"font-weight: 400;\">ImageView<\/span><span style=\"font-weight: 400;\">, which is <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageView.java#L22\">RNContrastChangingImageView<\/a><span style=\"font-weight: 400;\"> in my case. Here we must override the <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageManager.java#L10\"><code>getName()<\/code><\/a><span style=\"font-weight: 400;\"> method, which returns the name string of our module, and that\u2019s how our native module will be called in JS.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The next mandatory method that we need to override is <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageManager.java#L15\"><code>createViewInstance()<\/code><\/a><span style=\"font-weight: 400;\">. This is the most important method in this class, as it instantiates out custom <\/span><span style=\"font-weight: 400;\">ImageView<\/span><span style=\"font-weight: 400;\"> that we created above. It receives the <\/span><code>ThemedReactContext<\/code><span style=\"font-weight: 400;\"> prop and passes it to the constructor of our custom <\/span><span style=\"font-weight: 400;\">ImageView<\/span><span style=\"font-weight: 400;\">. This means that our view block can be responsive to the passed styles just like any other View in our ReactNative JS code.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Other methods are the view properties that we expose to JS. They are marked with <\/span><code>@ReactProp<\/code><span style=\"font-weight: 400;\"> annotation with specified <\/span><code>name<\/code><span style=\"font-weight: 400;\"> value (this value will be used as prop name exposed to JS), and they receive two params, the first one is the reference to the instance of our custom ImageView, and the second is param is the value of the prop. The bodies of these methods do only one thing, call proper setters on our view instance and pass received property value to it.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">That\u2019s all what we\u2019ve got on our custom ImageViewManager, let\u2019s move on to the last part.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Add_your_custom_UI_component_to_the_global_RN_native_modules_registry\"><\/span><b>Add your custom UI component to the global RN native modules registry<\/b><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Firstly, create the package module with your <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImageManager.java\"><span style=\"font-weight: 400;\">custom ImageViewManager<\/span><\/a><\/p>\n<pre><code class=\"js\"><b>public class <\/b><span style=\"font-weight: 400;\">RNContrastChangingImagePackage <\/span><b>implements <\/b><span style=\"font-weight: 400;\">ReactPackage\u00a0 {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@Override<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public <\/b><span style=\"font-weight: 400;\">List&lt;NativeModule&gt; createNativeModules(ReactApplicationContext reactContext) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return <\/b><span style=\"font-weight: 400;\">Collections.<\/span><i><span style=\"font-weight: 400;\">emptyList<\/span><\/i><span style=\"font-weight: 400;\">();<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@Override<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public <\/b><span style=\"font-weight: 400;\">List&lt;ViewManager&gt; createViewManagers(ReactApplicationContext reactContext) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return <\/b><span style=\"font-weight: 400;\">Collections.&lt;ViewManager&gt;<\/span><i><span style=\"font-weight: 400;\">singletonList<\/span><\/i><span style=\"font-weight: 400;\">(<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>new <\/b><span style=\"font-weight: 400;\">RNContrastChangingImageManager()<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0);<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">}<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">Implement the <\/span><span style=\"font-weight: 400;\">ReactPackage<\/span><span style=\"font-weight: 400;\"> from ReactNative. Add your <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImagePackage.java#L19\"><code><span style=\"color: #800080;\">new<\/span> CustomImageViewManager()<code><\/code><\/code><\/a><span style=\"font-weight: 400;\"> to the returning list in <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/reactlibrary\/RNContrastChangingImagePackage.java#L17\"><code>createViewManagers()<\/code><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Secondly, add your <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/nativeimagestuff59\/MainApplication.java#L35\"><code><span style=\"color: #800080;\">new<\/span> CustomImageViewPackage()<\/code><\/a><span style=\"font-weight: 400;\"> to the returning list in <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/nativeimagestuff59\/MainApplication.java#L32\"><code>getPackages()<\/code><\/a><span style=\"font-weight: 400;\"> method in <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/android\/app\/src\/main\/java\/com\/nativeimagestuff59\/MainApplication.java\"><span style=\"font-weight: 400;\">MainApplication.java<\/span><span style=\"font-weight: 400;\"> of your Android project<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<pre><code class=\"js\"><b>public class <\/b><span style=\"font-weight: 400;\">MainApplication <\/span><b>extends <\/b><span style=\"font-weight: 400;\">Application <\/span><b>implements <\/b><span style=\"font-weight: 400;\">ReactApplication {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0<\/span><b>private final <\/b><span style=\"font-weight: 400;\">ReactNativeHost <\/span><b>mReactNativeHost <\/b><span style=\"font-weight: 400;\">= <\/span><b>new <\/b><span style=\"font-weight: 400;\">ReactNativeHost(<\/span><b>this<\/b><span style=\"font-weight: 400;\">) {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@Override<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>public boolean <\/b><span style=\"font-weight: 400;\">getUseDeveloperSupport() {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return <\/b><span style=\"font-weight: 400;\">BuildConfig.<\/span><b><i>DEBUG<\/i><\/b><span style=\"font-weight: 400;\">;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">@Override<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0<\/span><b>protected <\/b><span style=\"font-weight: 400;\">List&lt;ReactPackage&gt; getPackages() {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>return <\/b><span style=\"font-weight: 400;\">Arrays.&lt;ReactPackage&gt;<\/span><i><span style=\"font-weight: 400;\">asList<\/span><\/i><span style=\"font-weight: 400;\">(<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>new <\/b><span style=\"font-weight: 400;\">MainReactPackage(),<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><b>new <\/b><span style=\"font-weight: 400;\">RNContrastChangingImagePackage()<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0\u00a0);<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0 \u00a0<\/span><span style=\"font-weight: 400;\">{{ \u2026 }}<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">And that\u2019s it, you\u2019re ready to call your module from your JS code.<\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Using_your_custom_native_UI_component_in_JS\"><\/span><strong>Using your custom native UI component in JS\u00a0<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><span style=\"font-weight: 400;\">For the sake of comfortability, we will import our custom ImageView from the global React native modules registry and export it as a React component. The last, but not least is documentation for our component. We will add PropTypes and DefaultProps.<\/span><\/p>\n<pre><code class=\"js\"><span style=\"font-weight: 400;\">import React from 'react'\r\nimport PropTypes from 'prop-types'<\/span>\r\n<span style=\"font-weight: 400;\">import<\/span><span style=\"font-weight: 400;\"> { requireNativeComponent }<\/span><span style=\"font-weight: 400;\"> from<\/span> <span style=\"font-weight: 400;\">'react-native'<\/span>\r\n\r\n<span style=\"font-weight: 400;\">class<\/span><span style=\"font-weight: 400;\"> ContrastChangingImage <\/span><span style=\"font-weight: 400;\">extends<\/span><span style=\"font-weight: 400;\"> React.Component {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0render() {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0return<\/span> <span style=\"font-weight: 400;\">&lt;RNContrastChangingImage<\/span> <span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">...<\/span><span style=\"font-weight: 400;\">this<\/span><span style=\"font-weight: 400;\">.props<\/span><span style=\"font-weight: 400;\">}<\/span> <span style=\"font-weight: 400;\">\/&gt;<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">ContrastChangingImage.propTypes = {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">url<\/span><span style=\"font-weight: 400;\">: PropTypes.string.isRequired,<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">contrast<\/span><span style=\"font-weight: 400;\">: PropTypes.number.isRequired,<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\/**<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0* Determines how to resize the image when the frame doesn't match the raw image dimensions.<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0* enum('contain', 'cover', 'stretch') with 'contain' value by default.<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0*\/<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">resizeMode<\/span><span style=\"font-weight: 400;\">: PropTypes.oneOf([<\/span><span style=\"font-weight: 400;\">'contain'<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">'cover'<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">'stretch'<\/span><span style=\"font-weight: 400;\">]),<\/span>\r\n<span style=\"font-weight: 400;\">}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">ContrastChangingImage.defaultProps = {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">resizeMode<\/span><span style=\"font-weight: 400;\">: <\/span><span style=\"font-weight: 400;\">'contain'<\/span><span style=\"font-weight: 400;\">,<\/span>\r\n<span style=\"font-weight: 400;\">}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">var<\/span><span style=\"font-weight: 400;\"> RNContrastChangingImage = requireNativeComponent(<\/span><span style=\"font-weight: 400;\">'RNContrastChangingImage'<\/span><span style=\"font-weight: 400;\">, ContrastChangingImage)<\/span>\r\n\r\n<span style=\"font-weight: 400;\">export default<\/span><span style=\"font-weight: 400;\"> ContrastChangingImage<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">The <\/span><a href=\"https:\/\/github.com\/ProductCrafters\/rn-contrast-changer\/blob\/master\/App.js\"><span style=\"font-weight: 400;\">example of usage of our custom ImageView<\/span><\/a><span style=\"font-weight: 400;\"> component would look like this.<\/span><\/p>\n<pre><code class=\"js\"><span style=\"font-weight: 400;\">\u00a0 \u00a0{{ \u2026 }}\r\nimport Slider from 'react-native-slider'\r\n\r\nexport default<\/span> <span style=\"font-weight: 400;\">class<\/span><span style=\"font-weight: 400;\"> App <\/span><span style=\"font-weight: 400;\">extends<\/span><span style=\"font-weight: 400;\"> Component {<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0state = {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">imgUrl<\/span><span style=\"font-weight: 400;\">: <\/span><span style=\"font-weight: 400;\">'https:\/\/www.publicdomainpictures.net\/pictures\/20000\/nahled\/monarch-butterfly-on-flower.jpg'<\/span><span style=\"font-weight: 400;\">,<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">contrastValue<\/span><span style=\"font-weight: 400;\">: <\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">,<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0handleSave = () <\/span><span style=\"font-weight: 400;\">=&gt;<\/span><span style=\"font-weight: 400;\"> {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0Alert.alert(<\/span><span style=\"font-weight: 400;\">'Current Contrast Value'<\/span><span style=\"font-weight: 400;\">,<\/span><span style=\"font-weight: 400;\"> `${<\/span><span style=\"font-weight: 400;\">this<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">state<\/span><span style=\"font-weight: 400;\">.<\/span><span style=\"font-weight: 400;\">contrastValue}`<\/span><span style=\"font-weight: 400;\">)<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0}<\/span>\r\n\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0onValueChange = value <\/span><span style=\"font-weight: 400;\">=&gt; this<\/span><span style=\"font-weight: 400;\">.setState({ <\/span><span style=\"font-weight: 400;\">contrastValue<\/span><span style=\"font-weight: 400;\">: +value.toFixed(<\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">) })<\/span>\r\n\r\n<span style=\"font-weight: 400;\"> \u00a0render() {<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0const<\/span><span style=\"font-weight: 400;\"> { contrastValue, imgUrl } =<\/span><span style=\"font-weight: 400;\"> this<\/span><span style=\"font-weight: 400;\">.state<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0return<\/span><span style=\"font-weight: 400;\"> (<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;View<\/span> <span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">styles.container<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;Text<\/span> <span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">styles.title<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">&gt;<\/span><span style=\"font-weight: 400;\">Change Contrast<\/span><span style=\"font-weight: 400;\">&lt;\/Text&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;Text<\/span> <span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">styles.title<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">&gt;<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">contrastValue<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">&lt;\/Text&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;Slider<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">styles.slider<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">value<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">contrastValue<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">onValueChange<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{this<\/span><span style=\"font-weight: 400;\">.onValueChange<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">step<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">0.1<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">minimumValue<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">maximumValue<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">2<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">thumbTintColor<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">'#efefef'<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">minimumTrackTintColor<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">'#F8A136'<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">maximumTrackTintColor<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">'#5E82BC'<\/span><span style=\"font-weight: 400;\">}<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">\/&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;Text<\/span> <span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">styles.instructions<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">&gt;<\/span><span style=\"font-weight: 400;\">Move the slider left or right<\/span><span style=\"font-weight: 400;\">&lt;\/Text&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;ContrastChangingImage<\/span> <span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">styles.image<\/span><span style=\"font-weight: 400;\">}<\/span> <span style=\"font-weight: 400;\">contrast<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">contrastValue<\/span><span style=\"font-weight: 400;\">}<\/span> <span style=\"font-weight: 400;\">url<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">imgUrl<\/span><span style=\"font-weight: 400;\">}<\/span> <span style=\"font-weight: 400;\">\/&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;TouchableOpacity<\/span> <span style=\"font-weight: 400;\">onPress<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{this<\/span><span style=\"font-weight: 400;\">.handleSave<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;Text<\/span> <span style=\"font-weight: 400;\">style<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">{<\/span><span style=\"font-weight: 400;\">styles.title<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">&gt;<\/span><span style=\"font-weight: 400;\">Save<\/span><span style=\"font-weight: 400;\">&lt;\/Text&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;\/TouchableOpacity&gt;<\/span>\r\n<span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span style=\"font-weight: 400;\">&lt;\/View&gt;<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0\u00a0\u00a0)<\/span>\r\n<span style=\"font-weight: 400;\"> \u00a0}<\/span>\r\n<span style=\"font-weight: 400;\">}<\/span><\/code><\/pre>\n<p><span style=\"font-weight: 400;\">As you can see, it\u2019s not that hard to write your own native modules for React Native. So the next time you face the situation, when there\u2019s no existing RN module solving your task, you will be able to start searching for some native code solutions for your platform, write a little wrapper for them, and use it in your JS project.<\/span><\/p>\n<h4><b>References<\/b><\/h4>\n<ul>\n<li style=\"font-weight: 400;\"><a href=\"https:\/\/brainhub.eu\/blog\/opencv-react-native-image-processing\/\">https:\/\/brainhub.eu\/blog\/opencv-react-native-image-processing<\/a><\/li>\n<li><a style=\"word-break: break-all;\" href=\"https:\/\/docs.opencv.org\/3.4.3\/d3\/dc1\/tutorial_basic_linear_transform.html\">https:\/\/docs.opencv.org\/3.4.3\/d3\/dc1\/tutorial_basic_linear_transform.html<\/a><\/li>\n<li style=\"font-weight: 400;\"><a href=\"https:\/\/facebook.github.io\/react-native\/docs\/native-components-android\">https:\/\/facebook.github.io\/react-native\/docs\/native-components-android<\/a><\/li>\n<li style=\"font-weight: 400;\"><a href=\"https:\/\/facebook.github.io\/react-native\/docs\/native-components-ios\">https:\/\/facebook.github.io\/react-native\/docs\/native-components-ios<\/a><\/li>\n<li><a href=\"https:\/\/hackernoon.com\/react-native-bridge-for-ios-and-android-43feb9712fcb\">https:\/\/hackernoon.com\/react-native-bridge-for-ios-and-android-43feb9712fcb<\/a><\/li>\n<li style=\"font-weight: 400;\"><a href=\"https:\/\/hackernoon.com\/react-native-bridge-for-android-and-ios-ui-component-782cb4c0217d\">https:\/\/hackernoon.com\/react-native-bridge-for-android-and-ios-ui-component-782cb4c0217d<\/a><\/li>\n<\/ul>\n<p class=\"p1\">Read more:<\/p>\n<p class=\"p1\">\u2013 <a href=\"https:\/\/productcrafters.io\/blog\/adding-svg-icons-to-your-react-native-app\/\">Adding SVG Icons to Your React Native App<\/a><\/p>\n<p class=\"p1\">\u2013 <a href=\"https:\/\/productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/\">Creating Custom React Native UI Components Android<\/a><\/p>\n<p class=\"p1\">\u2013 <a href=\"https:\/\/productcrafters.io\/blog\/how-to-create-wysiwyg-widget-editor-on-react-native\/\">How to Create WYSIWYG Widget Editor on React Native<\/a><\/p>\n<p class=\"p1\">\u2013 <a href=\"https:\/\/productcrafters.io\/blog\/responsive-react-native-apps\/\">Responsive React Native Apps<\/a><\/p>\n<p class=\"p1\">\u2013 <a href=\"https:\/\/productcrafters.io\/blog\/react-native-tips-to-style-you-app\/\">React Native Tips to Style Your App<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the process of learning and growing as a React Native developer, at some point in your career you\u2019ll get to the point when&#8230;<\/p>\n","protected":false},"author":4,"featured_media":2066,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-1559","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Custom React Native Components: Android Development | ProductCrafters<\/title>\n<meta name=\"description\" content=\"Build custom React Native components for Android. Complete guide to native modules, bridging, platform-specific UI, and implementation tips.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Custom React Native Components: Android Development | ProductCrafters\" \/>\n<meta property=\"og:description\" content=\"Build custom React Native components for Android. Complete guide to native modules, bridging, platform-specific UI, and implementation tips.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/\" \/>\n<meta property=\"og:site_name\" content=\"ProductCrafters\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/productcrafters\" \/>\n<meta property=\"article:published_time\" content=\"2019-10-10T14:45:05+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-01-19T21:04:47+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"768\" \/>\n\t<meta property=\"og:image:height\" content=\"775\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Alex Mischenko\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alex Mischenko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/\"},\"author\":{\"name\":\"Alex Mischenko\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/person\/155941d8ba4116a8a1027d1b7d667e16\"},\"headline\":\"Creating custom React Native UI components [Android]\",\"datePublished\":\"2019-10-10T14:45:05+00:00\",\"dateModified\":\"2026-01-19T21:04:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/\"},\"wordCount\":1329,\"publisher\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp\",\"articleSection\":[\"Development\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/\",\"url\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/\",\"name\":\"Custom React Native Components: Android Development | ProductCrafters\",\"isPartOf\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp\",\"datePublished\":\"2019-10-10T14:45:05+00:00\",\"dateModified\":\"2026-01-19T21:04:47+00:00\",\"description\":\"Build custom React Native components for Android. Complete guide to native modules, bridging, platform-specific UI, and implementation tips.\",\"breadcrumb\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#primaryimage\",\"url\":\"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp\",\"contentUrl\":\"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp\",\"width\":768,\"height\":775},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/stage.productcrafters.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Development\",\"item\":\"https:\/\/stage.productcrafters.io\/blog\/development\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Creating custom React Native UI components [Android]\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#website\",\"url\":\"https:\/\/stage.productcrafters.io\/blog\/\",\"name\":\"ProductCrafters\",\"description\":\"Our insights on development and business topics.\",\"publisher\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/stage.productcrafters.io\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#organization\",\"name\":\"ProductCrafters\",\"url\":\"https:\/\/stage.productcrafters.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/productcrafters.io\/blog\/wp-content\/uploads\/2019\/04\/favicon.png\",\"contentUrl\":\"https:\/\/productcrafters.io\/blog\/wp-content\/uploads\/2019\/04\/favicon.png\",\"width\":64,\"height\":64,\"caption\":\"ProductCrafters\"},\"image\":{\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/productcrafters\",\"https:\/\/www.linkedin.com\/company\/18621816\",\"https:\/\/github.com\/ProductCrafters\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/person\/155941d8ba4116a8a1027d1b7d667e16\",\"name\":\"Alex Mischenko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/38dc4ad49474b4031c35cd800378f25878e9d2f544bf759cf433dfa89c0dcfdb?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/38dc4ad49474b4031c35cd800378f25878e9d2f544bf759cf433dfa89c0dcfdb?s=96&d=mm&r=g\",\"caption\":\"Alex Mischenko\"},\"url\":\"https:\/\/stage.productcrafters.io\/blog\/author\/alex-m\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Custom React Native Components: Android Development | ProductCrafters","description":"Build custom React Native components for Android. Complete guide to native modules, bridging, platform-specific UI, and implementation tips.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/","og_locale":"en_US","og_type":"article","og_title":"Custom React Native Components: Android Development | ProductCrafters","og_description":"Build custom React Native components for Android. Complete guide to native modules, bridging, platform-specific UI, and implementation tips.","og_url":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/","og_site_name":"ProductCrafters","article_publisher":"https:\/\/www.facebook.com\/productcrafters","article_published_time":"2019-10-10T14:45:05+00:00","article_modified_time":"2026-01-19T21:04:47+00:00","og_image":[{"width":768,"height":775,"url":"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp","type":"image\/webp"}],"author":"Alex Mischenko","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Alex Mischenko","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#article","isPartOf":{"@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/"},"author":{"name":"Alex Mischenko","@id":"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/person\/155941d8ba4116a8a1027d1b7d667e16"},"headline":"Creating custom React Native UI components [Android]","datePublished":"2019-10-10T14:45:05+00:00","dateModified":"2026-01-19T21:04:47+00:00","mainEntityOfPage":{"@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/"},"wordCount":1329,"publisher":{"@id":"https:\/\/stage.productcrafters.io\/blog\/#organization"},"image":{"@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#primaryimage"},"thumbnailUrl":"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp","articleSection":["Development"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/","url":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/","name":"Custom React Native Components: Android Development | ProductCrafters","isPartOf":{"@id":"https:\/\/stage.productcrafters.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#primaryimage"},"image":{"@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#primaryimage"},"thumbnailUrl":"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp","datePublished":"2019-10-10T14:45:05+00:00","dateModified":"2026-01-19T21:04:47+00:00","description":"Build custom React Native components for Android. Complete guide to native modules, bridging, platform-specific UI, and implementation tips.","breadcrumb":{"@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#primaryimage","url":"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp","contentUrl":"https:\/\/stage.productcrafters.io\/blog\/wp-content\/uploads\/2019\/10\/native-module-crossplatform-768x775-1.webp","width":768,"height":775},{"@type":"BreadcrumbList","@id":"https:\/\/stage.productcrafters.io\/blog\/creating-custom-react-native-ui-components-android\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/stage.productcrafters.io\/blog\/"},{"@type":"ListItem","position":2,"name":"Development","item":"https:\/\/stage.productcrafters.io\/blog\/development\/"},{"@type":"ListItem","position":3,"name":"Creating custom React Native UI components [Android]"}]},{"@type":"WebSite","@id":"https:\/\/stage.productcrafters.io\/blog\/#website","url":"https:\/\/stage.productcrafters.io\/blog\/","name":"ProductCrafters","description":"Our insights on development and business topics.","publisher":{"@id":"https:\/\/stage.productcrafters.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/stage.productcrafters.io\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/stage.productcrafters.io\/blog\/#organization","name":"ProductCrafters","url":"https:\/\/stage.productcrafters.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/productcrafters.io\/blog\/wp-content\/uploads\/2019\/04\/favicon.png","contentUrl":"https:\/\/productcrafters.io\/blog\/wp-content\/uploads\/2019\/04\/favicon.png","width":64,"height":64,"caption":"ProductCrafters"},"image":{"@id":"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/productcrafters","https:\/\/www.linkedin.com\/company\/18621816","https:\/\/github.com\/ProductCrafters"]},{"@type":"Person","@id":"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/person\/155941d8ba4116a8a1027d1b7d667e16","name":"Alex Mischenko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/stage.productcrafters.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/38dc4ad49474b4031c35cd800378f25878e9d2f544bf759cf433dfa89c0dcfdb?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/38dc4ad49474b4031c35cd800378f25878e9d2f544bf759cf433dfa89c0dcfdb?s=96&d=mm&r=g","caption":"Alex Mischenko"},"url":"https:\/\/stage.productcrafters.io\/blog\/author\/alex-m\/"}]}},"_links":{"self":[{"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/posts\/1559","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/comments?post=1559"}],"version-history":[{"count":88,"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/posts\/1559\/revisions"}],"predecessor-version":[{"id":2248,"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/posts\/1559\/revisions\/2248"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/media\/2066"}],"wp:attachment":[{"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/media?parent=1559"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/categories?post=1559"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/stage.productcrafters.io\/blog\/wp-json\/wp\/v2\/tags?post=1559"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}