I have a long question about programmatic vs desig...
# android
t
I have a long question about programmatic vs design/xml UI using kotlin in Android; coming from an iOS/Swift background. I’ll post the body of the question as a threaded reply to this to avoid a ginormous post here.
This may be more of a general android (studio) question than kotlin specifically. But I don’t know where else to start. A colleague, new to app development, put together an app using kotlin on android. Being frustrated and not having a lot of a good mentors and interested in just accomplishing something, he messed around with the wysiwyg design/xml tools, but eventually abandoned it and just did all of the view construction in code. A network friend told me we really should be using the design tool more (primarily). So there’s a small subscreen (layout) that I thought I’d like to experiment with because it needs some visual updates. After a bit of trial and error, I was able to get the design tool to show things the way I want. My top level component is a ConstraintLayout. My file is called flow_verification_layout.xml. Opposite of that, is the original kotlin class file that defines a FlowVerificationSettingsPanel which is a subclass of ConstraintLayout. 80% of the code in that is an
init
block that builds up all of the subview structure and hooks up actions for buttons and stuff. What is the basic pattern for replacing all of that view construction code with my xml designed UI? Can I do this without rewriting the entire app and just restrict it to this corner of the app? If there’s a basic tutorial somewhere that would help me see the big picture here, that would be great. An explanation of the pieces as seen from iOS/Swift would be awesome too, since I’m pretty comfortable with storyboards, UIKit, outlets, etc.
r
s
You won’t need to rewrite the whole app, but you will need to redo how the connections to the View/Fragment/Activity are done
t
I tried adding viewBinding { enabled = true } to my build.gradle (Module:app) file as that page suggests. but then that just blows up
Could not find method viewBinding() for arguments [build_epgt9mufy5of61p0aisu2b2dd$_run_closure1$_closure5@5c8457d7] on object of type com.android.build.gradle.internal.dsl.BaseAppModuleExtension.
r
ah, sorry view binding is still in early development. Use databinding in the meantime. It’s very similar. https://developer.android.com/topic/libraries/data-binding
w
class file that defines a FlowVerificationSettingsPanel which is a subclass of ConstraintLayout
How is this class used? Because you really want to substitute usages of this class by your new xml layout, do I understand correctly? What’s important is: how is instance of this class obtained, and roughly how the listeners are being hooked up. You can create an instance of your layout by writing
LayoutInflater.from(context).inflate(R.layout.viewId, parent, [true|false])
, where
parent
is the view to which the original
FlowVerificationSettingsPanel
was added. For example if it was added in another layout defined in Kotlin, you’d simply call this this
LayoutInflater#inflate
there.
As for hooking up listeners and stuff, you have two options: manually retrieve every subview of the new xml layout (either fully manually by calling
findViewById
or by using Butterknife, Kotterknife, Kotlinx Android synthetic view extension, by using Databinding or the new ViewBinding if you’re on AGP 3.6-alpha10+ Ithink) and call appropriate methods like
setOnClickListener
. I personally strongly recommend looking into how you can incorporate DataBinding into the XML you have, for example by encapsulating view’s contract in a separate class. It helps a lot in terms of reducing boilerplate of finding views and setting proper listeners
t
@wasyl. so for the first part (your first response), do I need the databindings for that? Or is databindings more of a “and once you do that, you’re going to want to use something like databindings” ?
w
@Travis Griggs these two separate things. First you need to inflate the XML, as a result of which you will get a reference to the view. Then, to set up all the listeners, you need to find subviews and call appropriate methods.
t
thanks. that clarifies
w
To find those subviews you can use range of utility libraries that I mentioned, one of which is DataBinding. But DataBinding helps with the boilerplate of not only finding the view, but setting the listeners as well.
r
Another alternative is ButterKnife, it accomplishes the same goal without the listeners.
w
On an unrelated note, I don’t know a single developer who uses the wysiwyg tool, even for views based on the ConstraintLayout. We all write XML files directly and just use the preview tool to verify they’re correct (i.e. nobody drags and drops components etc.)
4
t
but you do use the xml files. in this app i’m playing with, it’s currently all done imperatively with code
w
That’s correct. I just thought it’s worth mentioning 🙂
t
i appreciate it; it’s nice to receive some guidance. the android world seems very difficult to discern best practice/common/idiomatic. googling stuff turns up all kinds of things. often people say are dead/no longer used, but still seem to be (e.g. are Fragments good or bad? Dead?)
w
I can definitely see that. Even worse — you will ask opinion from two knowledgeable Android devs, and one will swear DataBinding is amazing, the other will advise to never touch it, same about mvp vs mvvm vs mvi, the same thing about RxJava vs Flow (or Coroutines, but saying “RxJava” and “Coroutines” in the same sentence is just asking for someone stepping in to say “actually these are not mutually exclusive”, even though it’s the case for majority of people). My point is, you will find people saying literally anything. Best to find some that you trust and value their opinion more 😉 As for Fragments — they’re definitely not dead. They’re “bad” in that they’re massive in terms of functionality and the API surface, and the implementation is buggy at times. Google still considers them 1st party for the purpose of new libraries like navigation component. I’d say vast majority of devs use Fragments. But you’ll find devs advocating for Conductor or similar libraries, which essentially rewrite custom stack but with views instead of fragments. That’s fine too, it works for them obviously, but I guess I find some people being too 🤔 strict with their opinions.
s
Part of the thing is that, for the longest time, Google refused to have any kind of opinion regarding how apps should be structured, and so lots of different camps sprung up in it’s place
t
Is there a camp that makes the most sense for a guy who’s pretty comfortable with Swift/iOS/UIKit to adhere to? 😄
i’m making progress with Inflater. This was the magic bit I needed to see
w
Is there a camp that makes the most sense for a guy who’s pretty comfortable with Swift/iOS/UIKit to adhere to?
No 😄 I mean, I don’t think you’ll find lots of similar patterns that touch the framework, because they’re too different in those places that matter — for example in iOS you can create view and push onto a stack manually (I suppose maybe Conductor would be interesting, then? I haven’t used it), on Android it’s one of the bigger points of discussion without clear winner. And overall I think most of the system has just different philosophy. But these are just observations from the iOS code I see written by colleagues, so perhaps someone with more experience will chime in.
I’d say the closest thing you get to iOS development is Kotlin 😄
Part of the thing is that, for the longest time, Google refused to have any kind of opinion
Definitely true, at some point developing new frameworks became popular. That said I feel like now even with Google’s opinion you get even more discussion, because now people will strongly feel Google’s way is right or wrong 😄
l
I didn't read the whole thread, but I'll just say that some people in Android do programmatic UIs already, and I'm one of those. I made #splitties Views DSL after trying #anko, and other people are using it, because having Kotlin instead of xml brings some advantages. Note that Splitties Views DSL supports IDE preview. That said, more people use xml for UIs in Android, because Android xml is dramatically more readable than XIB/NIB in iOS world (though less readable than what I can do with Splitties IMO).
👍 1
r
So to answer your question. If you did all of the view programmatically, by subclassing a ViewGroup(i.e: constraint layout), than that's what's known in the Android dev world as a Custom/Compound views. If you have a app that's fully of custom views , and all your views are added programmatically I wouldn't waste time converting all of them to XML. It serves no benefit at that time. Just moving forward if you have completely new screens to add you can venture into the XML world
Both xml and UI done programmatically are fine. Just like in IOS. However our design tool is abit better than IOS, so people use it more because.. We dont have the same drawbacks like IOS has when it comes to writing UI in xml. And in most production code base you will always see XML when it comes to UI design.
t
Fascinating and thank you all. I can’t say that I’ve come over to the “XML is wonderful” yet camp. I really like doing wysiwyg constraint layout in iOS storyboards. To date, I’ve found ConstraintLayout makes me scratch my head more often. When people do do programmatic construction, is it preferable to use ConstraintLayout there. I’ve gotten the impression that I’m supposed to basically “ignore all of those other layouts, they’re so yesteryear, just use constraint for everything”
s
I honestly don’t see why one would use ConstraintLayout if they’re doing all their UI in code. It’s much, much easier to do it in the XML. Plus, you get a better preview of what it’ll look like as you’re writing it (read: any preview at all)
w
I’m in the other camp 😄 constraint is great because I can easily refer to every view within the hierarchy. With nested linear layouts etc. it’s a bit more complex. And I think I haven’t found layout that I can’t do with ConstraintLayout yet (other than things like having common background for a set of views, which is only possible since recently).
s
I’m absolutely saying use ConstraintLayout. I’m just saying I don’t know why you’d do it in code instead of in the XML
w
Ooh. Then yeah, I agree. Well, definitely not without assistance of any library like the one LouisCAD mentioned or e.g. Contour
l
Xml is not a programming language. No extensions (unless you hack with databinding…), no real reuse (not talking about
<include/>
), no preview of things you do in code. Many arguments against xml linked in Splitties Views DSL README and in Countour (by Square/CashApp) README as well.
On Android, I use LinearLayout, FrameLayout and ConstraintLayout, all three in code with Splitties Views DSL extensions. Next version of Splitties will provide
above
,
below
,
before
and
after
extensions as alternatives to
bottomToTopOf
and all, along with
lastChild
extension property. With these two things, layout code will be even more readable, but will also support reordering seamlessly. (This is currently in the develop branch) It might be a matter of preferences. I'm happy with what I use, and I tried both (plus Anko).
s
I just cannot stand writing UI stuff without a preview. I absolutely abhor the cycle of “code something, compile, see if it looks good, go back, make an adjustment, start again”
l
In production code, I have a UI only module (not kapt and other compilation slowing down stuff), and I run the
compileDebugKotlin
Gradle task. Most of the time, it runs in less than 2 seconds and refreshes the xml preview automatically.
👌 1
407 Views