May 7 | 8:50 AM |
Mark M. | has entered the room |
May 7 | 8:55 AM |
Mark M. | turned on guest access |
May 7 | 9:10 AM |
Leora | has entered the room |
Mark M. |
hello, Leora!
|
Mark M. |
how can I help you today?
|
Leora |
Heya Mark!
|
Leora |
How are you?
|
Mark M. |
OK, and you?
|
Leora |
Not bad not bad hhhhhh
|
Leora |
So I got permission to rewrite an old project I had worked on
|
Leora |
And the simplest thing has stumped me ----- the layout!
|
Leora |
It is a gameboard - calculator style you might say
|
May 7 | 9:15 AM |
Leora |
and was written as a gridview with a BaseAdapter
|
Mark M. |
ooooo... retro! :-)
|
Leora |
And me, being so wise and experienced and all tried to turn it into recycler view, which i realized quickly is wrong in this case since it doesn't scroll and doesn't recycle
|
Leora |
or grid layout which is completely inflexible....
|
Leora |
since in the settings the user can change the item number to 4, 6, 9, or the default 12
|
Mark M. |
that controls the numbers of rows? columns? both?
|
Leora |
So....should i leave it as gridview (gasp)??
|
Leora |
yes both
|
Leora |
each column or row can be 2 or 3 span
|
Mark | has entered the room |
Mark M. |
for a fixed number of alternatives like that, I would consider creating individual ConstraintLayout-based layouts for each, and using the right one based on user selection
|
Leora |
or 4 hhhh
|
Mark M. |
(BTW, hello Mark -- I will be with you shortly!)
|
Mark |
hello
|
Leora |
hmmmm i didn't think you would say that :)
|
Mark M. |
Leora: GridView is also set up for scrolling and recycling, so IMHO RecyclerView is also a viable option, though the ConstraintLayout approach would give you per-gameboard design flexibility
|
Mark M. |
I would not use GridView or GridLayout -- I would expect them to be deprecated one of these years
|
Leora |
with the constraint layouts option i would be copy/pasting 12 views! (gasp)
|
May 7 | 9:20 AM |
Mark M. |
it's possible you could do it with fewer layouts and using View.GONE visibility for some of the cells
|
Leora |
deprecated eh
|
Leora |
the items will also need to be shuffled when the user shakes the device
|
Leora |
and smooshed a bit when a banner ad is presented
|
Mark M. |
one advantage of RecyclerView is that if you use ListAdapter, you get automatic animations on a shuffle, to move the items around your board
|
Mark M. |
(here by "ListAdapter" I mean the RecyclerView one, not the old AdapterView subclass)
|
Leora |
oh i didn't know that
|
Leora |
yes but it's really hacky to get recyclerview not to scroll
|
Leora |
i think you even commented on that in SO once
|
Leora |
i think it has to be in a nested layout
|
Mark M. |
¯\_(ツ)_/¯
|
Mark M. |
at a high level, if you want to use pre-existing UI things, I'd lean towards RecyclerView and/or ConstraintLayout, but in the end, it is up to you
|
Mark M. |
let me take a question from Mark, and I'll be back with you shortly
|
Mark M. |
Mark: your turn! do you have a question?
|
Leora |
i was tempted to leave it as is, already has shuffle functionality written and all that, but if you think those layouts' days are numbered then....
|
Leora |
ok
|
May 7 | 9:25 AM |
Mark M. |
(Leora: you could leave them alone if you prefer -- your next rewrite may need to consider changes, though)
|
Leora |
then i rather consider them now :)
|
Mark M. |
Mark: your turn! do you have a question?
|
Mark |
I created a productFlavor called "liveScores". In the Android Studio Project View, I see app/src/liveScores/kotlin/com.sports.mobile/info. I see the same directory structure in the debug build type: app/src/debug/kotlin/com.sports.mobile/info. When I CMD+SHIFT+O for a file in the info directory I see app/src/liveScores/kotlin/com.sports.mobile/info and app/src/debug/kotlin/com/sports/mobile/info
|
Mark M. |
Android Studio shows packages using dot notation, to/limit/the/number/of/nested/directories/
|
Mark |
but why would it appear differently between debug and liveScores
|
Mark M. |
oh, wait
|
Mark |
com.sports.mobile is one directory in the project window. if I search for a file the paths are different
|
Mark M. |
to be clear: CMD+SHIFT+O brings up a file explorer for that directory? (I use Linux and forget my macOS UI...)
|
May 7 | 9:30 AM |
Mark |
global search for files
|
Mark |
so it lists a path from app. debug shows the package split up while livescores shows it as one package
|
Mark M. |
OK, if you use Finder or something, and look at the app/src/liveScores/kotlin/ directory, do you see a com/ directory or a com.sports.mobile/ directory?
|
Mark |
but project view shows both as com.sports.mobile
|
Mark |
finder shows it as com.sports.mobile
|
Mark M. |
OK, that's wrong
|
Mark |
finder shows it as separate directories for the debug
|
Mark M. |
I'm not certain how you got into that state, but you need that as com/sports/mobile/, not com.sports.mobile/
|
Mark M. |
you may have difficulty fixing this directly from within Android Studio -- I would close the project in Studio, fix the filesystem using Finder or something, then reopen the project
|
May 7 | 9:35 AM |
Mark M. |
Android Studio's behavior of showing packages as dot.delimited.strings normally is fine, but in this case masked a real problem in the directory structure
|
Mark M. |
let me take another question from Leora, and I will return to you in a bit
|
Mark M. |
Leora: do you have another question?
|
Leora |
errr same question
|
Mark |
View paste
|
Mark M. |
ummm... same answer? :-)
|
Mark |
OK
|
Mark M. |
(Mark: that should be OK)
|
Leora |
i thought you would be vehemently opposed to me using recyclerview since it doesn't recycle
|
Leora |
but if i have your blessing...
|
Mark M. |
you do not gain as much value from RecyclerView if you do not need recycling
|
Mark M. |
but they have added enough stuff to RecyclerView and its related classes that it is not unreasonable to use it even in places where you do not expect to recycle stuff
|
Leora |
i see
|
May 7 | 9:40 AM |
Leora |
so that or different layouts yeah?
|
Mark M. |
those would seem to be the two main options, for using modern existing UI constructs
|
Mark M. |
you could always roll your own custom ViewGroup, if you wanted, but I find those to be kinda complex
|
Leora |
nah :)
|
Mark M. |
or, since this is a game, you could change approaches entirely and switch to a game UI framework
|
Leora |
as in, no thanks
|
Leora |
game UI?
|
Leora |
it's a toddler game. they click a card and it opens up
|
Mark M. |
most Android games are not written using the View hierarchy -- they use various game toolkits
|
Leora |
not too complicated
|
Mark M. |
the best known is Unity 3D, though that's probably overkill here
|
Leora |
it would be nice to know but yeah overkill
|
Leora |
ok great thanks for your input Mark!
|
Mark M. |
happy to help!
|
Leora |
as always
|
Mark M. |
let me take another question from Mark, and I'll return to you in a bit
|
Leora |
peace
|
Mark M. |
Mark: back to you! do you have another question?
|
Mark |
for my liveScores product flavor I have my own version of files originally in src/main/com/sports/mobile/info that I moved into src/liveScores/com/sports/mobile/info. I want the app to use different files of the same name depending on the product flavor or build type. The file has a build error on the class name complaining Redeclaration
|
May 7 | 9:45 AM |
Mark M. |
View paste
|
Mark M. |
but you cannot have different class implementations for the same class for both build types and product flavors, other than by organizing them via build variants
|
Mark |
I just want my product flavor to use its own version of the activity
|
Mark M. |
you have more than one flavor, as you cannot just have a single flavor (other than to have no flavors at all)
|
Mark M. |
(unless they added single-flavor support when they started forcing flavorDimension... actually haven't tried that recently...)
|
Mark |
I created my own flavor
|
Mark |
should i move the activity out of debug and into main
|
Mark M. |
if you only wanted resources/assets/manifest entries to vary, then having just one flavor might work
|
Mark M. |
but if you want classes to vary, you need two flavors (liveScores and, um, deadScores), with your class implementations in each
|
Mark M. |
you cannot have the same class in main/ or in debug/
|
Mark |
no this is an Activity. Originally it was in main. I want my own version in liveScores
|
Mark |
ok let me try deleting it from the debug build type
|
Mark M. |
then you need liveScores/ and deadScores/, each with their own version of the activity
|
Mark M. |
and you need to remove the activity class from other places (main/, debug/, etc.)
|
Mark |
what is deadScores
|
Mark M. |
another flavor in the same dimension as the dimension that you have set up for liveScores
|
Mark |
ok i can try that
|
Mark |
thanks
|
Mark M. |
(though I suppose undeadScores/ would allow you to have Walking Dead and Game of Thrones tie-ins... :-)
|
May 7 | 9:50 AM |
Mark |
haha
|
Leora |
hhhh no spoilers! didn't see ep 4 yet
|
Mark M. |
OK, we're running out of chat time -- if either of you have additional questions, ask away!
|
Leora |
bye mark and mark, may the undead be with you
|
Leora | has left the room |
Mark |
before we go, how would I go about obscuring a module from deadScores, which I assume has the same source files as main?
|
Mark M. |
what do you mean by "obscuring a module"?
|
Mark M. |
deadScores/ has no source files by default, just as liveScores/ has no source files by default
|
Mark |
I have an app module and an api module. liveScores depends on new code in api module. I would like to hide that code from deadScores
|
Mark M. |
use liveScoresApi
|
Mark M. |
so, liveScoresApi "your.artifact.group:your.artifact.id:1.3.3.7"
|
Mark M. |
(or liveScoresImplementation)
|
Mark M. |
that says "use this dependency only for builds for the liveScores flavor"
|
Mark |
I unfortunately it is not in artifcatory, it is a separate module in the app
|
Mark M. |
so, liveScoresImplementation project(":whatever")
|
Mark |
yes
|
Mark M. |
(or liveScoresApi)
|
May 7 | 9:55 AM |
Mark |
im not sure I follow, they both need the module but liveScores only should have the liveScores api functionality built in the final apk
|
Mark M. |
what is "the liveScores api"?
|
Mark M. |
if you mean "code in liveScores/", then by definition only liveScores builds will have that code
|
Mark M. |
an undeadScores build will not have the liveScores/ code in it
|
Mark M. |
they both will have main/ code, plus code for the build type (e.g., debug/ or release/)
|
Mark |
I have 2 modules in the same project, app and api. Before liveScores app still uses api. WIth liveScores I have new app code inside liveScores AND new code inside api module
|
Mark M. |
you will need another module then, AFAIK
|
Mark M. |
the api module would be split into the common stuff that both flavors use and a liveScores-specific api module
|
Mark M. |
and you would only add the liveScores-specific api module to liveScores builds, via liveScoresImplementatino
|
Mark M. |
er, liveScoresImplementation
|
Mark |
do modules have flavors? couldnt I create a flavor in api and reference it somehow specifically in liveScores product flavor from the app
|
Mark |
what is liveScoresImplemenation?
|
Mark M. |
"do modules have flavors?" -- um, possibly, I forget the details there
|
May 7 | 10:00 AM |
Mark M. |
implementation project(":whatever") says "add this module to all builds"
|
Mark M. |
liveScoresImplementation project(":whatever") says "add this module only to liveScores builds"
|
Mark M. |
you might wish to reconsider whether having a separate api module is worthwhile
|
Mark |
OK I can create a submodule within api called liveScoresApi. Then in app's build.gradle say liveScoresImplementation project(":liveScoresApi")?
|
Mark M. |
yes
|
Mark |
yeah
|
Mark |
great!
|
Mark M. |
and that's a wrap for today's chat
|
Mark |
have a wonderful day!
|
Mark M. |
the transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark |
see ya
|
Mark M. |
have a pleasant day!
|
Mark | has left the room |
Mark M. | turned off guest access |