<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Arthur Nagy on Medium]]></title>
        <description><![CDATA[Stories by Arthur Nagy on Medium]]></description>
        <link>https://medium.com/@arthur.nagy?source=rss-3bbc3ba57754------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*uj55Bx3p3eJYysqFUrdkXg.jpeg</url>
            <title>Stories by Arthur Nagy on Medium</title>
            <link>https://medium.com/@arthur.nagy?source=rss-3bbc3ba57754------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 19:43:41 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@arthur.nagy/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Android Architecture Components: DataBinding - Dependent Properties]]></title>
            <link>https://medium.com/halcyon-mobile/android-architecture-components-databinding-dependent-properties-6e8eba6c8b13?source=rss-3bbc3ba57754------2</link>
            <guid isPermaLink="false">https://medium.com/p/6e8eba6c8b13</guid>
            <category><![CDATA[data-binding]]></category>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[Arthur Nagy]]></dc:creator>
            <pubDate>Fri, 27 Jul 2018 11:40:27 GMT</pubDate>
            <atom:updated>2018-07-27T16:11:01.669Z</atom:updated>
            <content:encoded><![CDATA[<p>Ever heard of <strong>DataBinding</strong>? I myself would like to live in a world where every Android developer knows about it. A world where the concept of<strong> </strong><em>findViewById</em><strong> </strong>and handwritten boilerplate glue code does not exist. Where you can easily tie your data to the UI and forget about updating it in case the data changes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yPEGoPdhhor21NGLHjxXHg.png" /></figure><p>To achieve this, my fellow developers, I decided to spread the word about a very powerful feature of DataBinding: <strong>DEPENDENT PROPERTIES.</strong></p><p><em>“What are dependent properties?”</em> you may ask<em>.</em></p><p>About a year ago, I found <a href="https://medium.com/google-developers/android-data-binding-dependent-properties-516d3235cd7c">this</a> short article by <a href="https://medium.com/u/d61fe6bd7eba">George Mount</a> which introduced a really neat feature of DataBinding * <em>drrrrrrrrrrrrrrrrrum-roll </em>* the <strong>Bindable properties</strong> which depend on other <strong>Bindable properties</strong>.</p><p>The cool thing about dependent properties is that any change in dependencies will automatically trigger an update to the field that declared them as dependencies. This is really powerful on screens where you have input views that rely upon the state of other views.</p><p>Let’s look at an example, so you can easily get the gist of it and see how useful this can be when implementing a reactive UI.</p><p>For the sake of simplicity I chose to have a first name and a last name as input fields, format them somehow and display the result. In the followings I’ll refer to this as the <strong>“displayName”</strong>.</p><p>This is how it looks in action:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FQ4x5z9VzrTE%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DQ4x5z9VzrTE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FQ4x5z9VzrTE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/93a50d3b64cd7d632f9c153791d4d45b/href">https://medium.com/media/93a50d3b64cd7d632f9c153791d4d45b/href</a></iframe><p><em>But how can this be implemented? </em>Fair question. I’ll show how I did it.</p><p>If you’ve gotten this far, I assume you’re familiar with the <a href="https://developer.android.com/topic/libraries/data-binding/">DataBinding library</a>, so I won’t explain how to set it up, but if you’d like to dust off your knowledge here’s a <a href="https://developer.android.com/topic/libraries/data-binding/start">guide</a> on how to do it.</p><p>As a first step I created the layout file.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4f5b71a623c88515d923b80bda5f5054/href">https://medium.com/media/4f5b71a623c88515d923b80bda5f5054/href</a></iframe><p>What you’ve just seen is a short version of the layout. I’ve left out the irrelevant tags to focus on what’s important right now. I declared a variable, the <strong>view model </strong>that stores and handles the data, then bound the <strong>displayName</strong> property from within the ViewModel to the <strong>TextView</strong>. Next, the <strong>firstName</strong> and <strong>lastName</strong> properties were bound using the<a href="https://medium.com/google-developers/android-data-binding-lets-flip-this-thing-dc17792d6c24"> <strong>two-way data binding</strong></a> syntax to the <strong>EditText</strong>s (meaning that any changes made in the <strong>EditText</strong>s, will show up in the <strong>ViewModel</strong>’s String properties too).</p><p>Following this, in the view model class, I declared the <strong>displayName</strong> bindable property to depend on the <strong>firstName</strong> and <strong>lastName</strong> bindable properties, by enumerating them in the <strong>@Bindable</strong> annotation as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3136ea72e943c65edf9465089a0eef6e/href">https://medium.com/media/3136ea72e943c65edf9465089a0eef6e/href</a></iframe><p>To use the <strong>notifyPropertyChanged</strong> method which signals whenever the @Bindable properties change, the ViewModel had to extend the <strong>BaseObservable</strong> class. With this, every time the <strong>firstName</strong> &amp; <strong>lastName</strong> changes<strong> </strong>the <strong>notifyPropertyChanged </strong>is called. This updates the <strong>displayName</strong>, which on its turn updates the UI with the new value.</p><p>To wrap this up, as a final step, I tied the <strong>UserViewModel</strong> instance to the XML layout:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3916805ce4f8606c003b495f5483c739/href">https://medium.com/media/3916805ce4f8606c003b495f5483c739/href</a></iframe><p>In the activity class I created a binding instance and set a <strong>UserViewModel</strong> to it.</p><p>Aaaaand that’s it.</p><p>Or is it? 🤔</p><p>Well, not exactly. I mean it’s nice and everything, but as you can see I filled the UserViewModel with boilerplate code in order to make this work.</p><p>Luckily, not so long ago I stumbled upon <a href="https://youtu.be/0cjr4K0tqs4">this</a> interesting talk by <a href="https://medium.com/u/c053a7cae17">Lisa Wray</a> about using DataBinding together with Kotlin. She used Kotlin’s <a href="https://kotlinlang.org/docs/reference/delegated-properties.html">delegated properties</a> feature to create a custom delegate for bindable fields, making the code more readable this way. Following her steps, this is what I ended up having:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/74992939f6a8b0c6f4fe5a9499a50a36/href">https://medium.com/media/74992939f6a8b0c6f4fe5a9499a50a36/href</a></iframe><p>The <strong>BindableDelegate </strong>has a receiver of <strong>R</strong> which extends <strong>BaseObservable</strong> and handles any kind a property of type <strong>T. </strong>In the constructor of the delegate it expects an initial value of the bindable property as well as its <strong>binding resource </strong>identifier. So now, when a value is set, <strong>notifyPropertyChanged </strong>will be called on the receiver class.</p><p>After rewriting the ViewModel to use the custom delegate I had something like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6c557b5e55fde163483ce681573bdc19/href">https://medium.com/media/6c557b5e55fde163483ce681573bdc19/href</a></iframe><p>All right, now the code is clean and concise. It can’t get any better, I’m pretty sure!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FhPPx8yk3Bmqys%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fgiphy.com%2Fgifs%2Frequest-donald-wrong-hPPx8yk3Bmqys&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FhPPx8yk3Bmqys%2Fgiphy-downsized-large.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="394" frameborder="0" scrolling="no"><a href="https://medium.com/media/aa7bad2dedf0a925e1d8565a7effaecf/href">https://medium.com/media/aa7bad2dedf0a925e1d8565a7effaecf/href</a></iframe><p>What seems to be the problem?</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FBRczNG2uNM4%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DBRczNG2uNM4&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FBRczNG2uNM4%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/f9ff62483cd416f578e8eae6a5c6507e/href">https://medium.com/media/f9ff62483cd416f578e8eae6a5c6507e/href</a></iframe><p>Turns out, the data doesn’t survive configuration changes such as screen rotations or entering multi-window mode.</p><p>So that’s where<a href="https://developer.android.com/topic/libraries/architecture/viewmodel"> Android Architecture Components: ViewModel</a> came into play. ViewModel is designed to store and manage UI-related data in a lifecycle conscious way. <em>Well then, let’s extend it, use it and problem solved, right?</em> It’s not exactly that simple, the UserViewModel already extends BaseObservable, in order to use bindable properties.</p><p>Since extending multiple classes is not possible, my options were limited. I could have extended the Architecture Components provided ViewModel and copy-paste the whole code from the BaseObservable class. It’s doable, but let’s be honest, that’s an ugly solution, so I chose not to pursue it.</p><p>Fortunately, the DataBinding library provides Observable classes, more specifically an <a href="https://developer.android.com/reference/android/databinding/ObservableField">ObservableField</a>(or it’s primitive variants) which behaves like a BaseObservable but also wraps a value. Instances of this class can be used as properties in the view model instead of the @Bindable properties. This way properties can be bound to the view and retain the data on configuration change events by extending the ViewModel class.</p><p>Mmmkay, but what about the dependent properties? How can one deliver this feature with ObservableField? In the <a href="https://developer.android.com/studio/releases/#codingide">Android Studio 3.1</a> update, Google silently updated the DataBinding library, and one of the changes was:</p><blockquote>The <a href="https://developer.android.com/reference/android/databinding/ObservableField.html">ObservableField</a> class can now accept other <a href="https://developer.android.com/reference/android/databinding/Observable.html">Observable</a> objects in its constructor.</blockquote><p>Crystal clear, right? It turns out, using this, the same dependent property behaviour can be achieved as with @Bindable properties. So I refactored the UserViewModel to use the Architecture Component ViewModel and ObservableFields as properties:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/91f805f2b3bde138e918276b4a222402/href">https://medium.com/media/91f805f2b3bde138e918276b4a222402/href</a></iframe><p>To make the code more readable, I created a top-level inline function which hides the ObservableField instantiation and overrides the get() method:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8a17faa59c674d0e778cbc6cfeed59fd/href">https://medium.com/media/8a17faa59c674d0e778cbc6cfeed59fd/href</a></iframe><p>I also modified the view model creation logic in the activity:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9ec03bb291832916c9066856022834dc/href">https://medium.com/media/9ec03bb291832916c9066856022834dc/href</a></iframe><p><em>Et voila!</em> Problem solved! Now the data is retained on configuration change and the dependent property is working as expected.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F-VA9WSJl8Sk%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D-VA9WSJl8Sk&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F-VA9WSJl8Sk%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/52f6b2fc65432f1a9850df7c4f7e3903/href">https://medium.com/media/52f6b2fc65432f1a9850df7c4f7e3903/href</a></iframe><p><strong>Bonus: LiveData</strong></p><p>Like ViewModel, <a href="https://developer.android.com/topic/libraries/architecture/livedata">LiveData</a> is another class from the Lifecycle Architecture Component library. LiveData is a data holder which also happens to be lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, this ensures that if an activity or fragment is observing a LiveData, it will only send an update to them in an active lifecycle state.</p><p>Android Studio 3.1 brought another sweet update to the DataBinding library:</p><blockquote>You can now use a <a href="https://developer.android.com/reference/android/arch/lifecycle/LiveData.html">LiveData</a> object as an observable field in data binding expressions. The <a href="https://developer.android.com/reference/android/databinding/ViewDataBinding.html">ViewDataBinding</a>class now includes a new setLifecycleOwner() method that you use to observe <a href="https://developer.android.com/reference/android/arch/lifecycle/LiveData.html">LiveData</a> objects.</blockquote><p>So instead of using ObservableField’s I used LiveData for binding the data to the UI. The property dependency can be achieved by using a <a href="https://developer.android.com/reference/android/arch/lifecycle/MediatorLiveData">MediatorLiveData</a>: I created another top-level inline function only this time returning a MediatorLiveData instead of ObservableField and its dependencies were LiveData instead of Observable:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0f01ad38cd0babdf6472e39d1c5513a2/href">https://medium.com/media/0f01ad38cd0babdf6472e39d1c5513a2/href</a></iframe><p>All that was left do is swapping out all <strong>ObservableField</strong> properties to <strong>LiveData</strong> in the <strong>UserViewModel</strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2029fe0a02d76cdf90ccb6b555e5770f/href">https://medium.com/media/2029fe0a02d76cdf90ccb6b555e5770f/href</a></iframe><p>and calling <strong>setLifecycleOwner() </strong>on the binding instance in the activity:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1ff5c81ee9461cb6b3b11bc2f86649fc/href">https://medium.com/media/1ff5c81ee9461cb6b3b11bc2f86649fc/href</a></iframe><p>The end!</p><p>Hope you find this feature useful and now that you’ve seen how easy it is to integrate it into your codebase, you’ll start experimenting with it. I’d be thrilled to hear your thought on this functionality, as well as ideas about cases you see yourself using it.</p><p>You can find all the code <a href="https://github.com/ArthurNagy/DataBindingPlayground">here</a>. Any feedback, and of course shares and claps are more than welcome.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6e8eba6c8b13" width="1" height="1" alt=""><hr><p><a href="https://medium.com/halcyon-mobile/android-architecture-components-databinding-dependent-properties-6e8eba6c8b13">Android Architecture Components: DataBinding - Dependent Properties</a> was originally published in <a href="https://medium.com/halcyon-mobile">The Halcyon Mobile Collection</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Implementing Google’s refreshed modal bottom sheet]]></title>
            <link>https://medium.com/halcyon-mobile/implementing-googles-refreshed-modal-bottom-sheet-4e76cb5de65b?source=rss-3bbc3ba57754------2</link>
            <guid isPermaLink="false">https://medium.com/p/4e76cb5de65b</guid>
            <category><![CDATA[material-design]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[androiddev]]></category>
            <dc:creator><![CDATA[Arthur Nagy]]></dc:creator>
            <pubDate>Tue, 22 May 2018 12:24:07 GMT</pubDate>
            <atom:updated>2019-06-30T14:29:39.962Z</atom:updated>
            <content:encoded><![CDATA[<p>This year’s Google I/O introduced an improved version of Material Design to the curious public in Mountain View and across the globe. With the new release a couple of components got a fresh coat of paint but some shiny new elements entered the game too. The tech giant debuted a few new and revamped apps that already reflect the changes in their official design language.</p><p>One of their new joiner apps is <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.tasks&amp;hl=en">Tasks</a>, a simple and clean productivity app that integrates well with other G suite apps. I’ve been using it since its release and I really like it.</p><p><a href="https://play.google.com/store/apps/details?id=com.google.android.apps.magazines">News</a>, formerly known as Play Newsstand is another app that has been well received at the event. Besides its new Material theme News is now powered by AI.</p><p>Both of these products have a neat, simple and intuitive design, that showcases the capabilities of the updated <a href="https://github.com/material-components/material-components-android">Material Design for Android</a>. It’s stunning. So much so, that it got me taking these apps as design examples for a side project I started working on.</p><p>Shortly after I started implementing the UI, I stumbled upon my first issue: the BottomSheetDialog component, available through the <a href="https://github.com/material-components/material-components-android/blob/master/docs/getting-started.md">new design library</a>, did not look like the ones from these apps:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rLBf6fPtfWhXqnTOLlj0cQ.png" /><figcaption>Left: Tasks, right: News, both apps have their menu open</figcaption></figure><p>As you can see, both apps use a modal bottom sheet dialog to present their menu, but their top edges are rounded and the NavigationBar isn’t dimmed. If we use the BottomSheet from the MaterialComponents library this is what we get:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6BxLHKE97eBkGTeG12MT4w.png" /><figcaption>Left: app with menu closed, on the right we have the menu open which brings up a modal bottom sheet</figcaption></figure><p>The screenshot from the left hand side shows the home screen with its menu closed. The one on the right illustrates how the modal bottom sheet is shown when the menu icon from the bottom app bar is tapped.</p><p>The question: how can one implement the same behaviour that’s present in the apps from the examples? My goal was to do it as simple and elegant as possible, so here’s how I did it:</p><blockquote><strong>EDIT</strong>: Since publishing this article the Material Components team released <a href="https://material.io/design/shape/about-shape.html#">Shape Theming</a> support in the <a href="https://github.com/material-components/material-components-android/releases/tag/1.1.0-alpha02">Material Design Components Android library, version 1.1.0-alpha02</a>.</blockquote><blockquote>If you are already using the latest version of Material Design Components library for Android, then implementing this rounded corner bottom sheet got much easier. All you have to do is to set the <strong>shapeAppearanceLargeComponent </strong>attribute in your <strong>Theme </strong>to a style which extends <strong>ShapeAppearance.MaterialComponents.LargeComponent </strong>and has the <strong>cornerFamily </strong>attribute set to <strong>rounded</strong> and the <strong>cornerSize</strong> to 16dp or your dimension of choice.</blockquote><blockquote>For more details about shape theming check out <a href="https://material.io/develop/android/theming/shape/">this documentation.</a></blockquote><p>First I created a shape drawable which I’ll be using as background for the bottom sheet:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/88ffcfdc60c0b71012a445e1f8a36376/href">https://medium.com/media/88ffcfdc60c0b71012a445e1f8a36376/href</a></iframe><p>Next, I made a custom style for the BottomSheet widget and a custom theme for the BottomSheetDialogFragment:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e7444f1567b5cc6189c3538d07eb4bfd/href">https://medium.com/media/e7444f1567b5cc6189c3538d07eb4bfd/href</a></iframe><p>In the BottomSheet style, I set the custom background drawable to be used as the bottom sheet’s background. After that I created a custom theme for the fragment, set the statusBarColor to transparent and the navigationBarColor to white (that’s our desired color in this case). Then I set the fragment’s window <a href="https://developer.android.com/reference/android/view/Window#isfloating">floating attribute</a> which wraps the dialog to false.</p><p>Lastly, I extended the BottomSheetDialogFragment and set my new theme on it:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/893097a35896972996dd6d15b3f4a179/href">https://medium.com/media/893097a35896972996dd6d15b3f4a179/href</a></iframe><p>Aaaand that’s it. All that was left to do is extend the RoundedBottomSheetDialogFragment, inflate a layout of my choice in it and simply show it, like you’d do with a normal BottomSheetDialogFragment:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8072b2d507bb2646287caa2733b620ff/href">https://medium.com/media/8072b2d507bb2646287caa2733b620ff/href</a></iframe><p>The result:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*8rSZqfchMsVbWTni0Drqxg.png" /><figcaption>Rounded BottomSheetDialog fragment without dimmed NavigationBar</figcaption></figure><p>You can find all the code <a href="https://gist.github.com/ArthurNagy/1c4a64e6c8a7ddfca58638a9453e4aed">here</a>. Let me know if you have a similar or better solution. Any feedback, and of course shares and claps are more than welcome.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4e76cb5de65b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/halcyon-mobile/implementing-googles-refreshed-modal-bottom-sheet-4e76cb5de65b">Implementing Google’s refreshed modal bottom sheet</a> was originally published in <a href="https://medium.com/halcyon-mobile">The Halcyon Mobile Collection</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>