Apr 5 | 3:55 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Ed T. | has entered the room |
Mark M. |
hello, Ed!
|
Mark M. |
how can I help you today?
|
Ed T. |
Hi Mark!
|
Apr 5 | 4:00 PM |
Ed T. |
Struggling with something on ConstraintLayout this week
|
Ed T. |
I've got a bunch of label-data rows
|
Ed T. |
trying to get it to collapse an absorb the space
|
Ed T. |
if I set the row to INVISIBLE or GONE
|
Ed T. |
it doesn't fill the space
|
Mark M. |
what is "the row"? do you mean two widgets that are children of the ConstraintLayout?
|
Ed T. |
yes, I have a bunch of TextView items
|
Ed T. |
and under certain scenarios an option might not be valid
|
Ed T. |
so imagine a 'SWITCH' widget
|
gonzobrains | has entered the room |
Ed T. |
if you turn it off fields go away and the view collapses
|
Ed T. |
turn it on and they show up and the layout expands
|
Mark M. |
(BTW, hello gonzobrains -- I will be with you shortly!)
|
gonzobrains |
Hi, everyone.
|
gonzobrains |
okay, thanks.
|
Mark M. |
do the things that you expect to fill the space have 0dp for the desired axis?
|
Apr 5 | 4:05 PM |
Ed T. |
looking
|
Mark M. |
basically, you need the things that are to fill the space have flexible sizing
|
Mark M. |
if they have a fixed size (dimension or wrap_content), then it doesn't matter what happens around them
|
Mark M. |
while you're looking, let me take a question from gonzobrains, and I'll be back with you in a bit
|
Mark M. |
gonzobrains: your turn! do you have a question?
|
gonzobrains |
I'm writing it right now.
|
Ed T. | |
Ed T. |
that should collapse in the white space.... checking what you suggested... thanks
|
gonzobrains |
I have a problem where an AlertDialog remains on the screen after the user resumes an app from device sleep. I have tried to dismiss the dialog in the OnPause() of its containing fragment, however the OnPause() is not getting called. I notice that the fragment's OnPause() doesn't get called if the fragment is is displayed from another fragment, but if I allow the user to view this fragment from an option in the sidebar menu, the OnPause() method gets called.
|
gonzobrains |
That's the only difference I can seem to find between fragment's that have OnPause() called and those that do not, ie. where they are called from.
|
gonzobrains |
There is only one activity in this application, and the previous developer created a "hamburger menu" for displaying fragments and also allows fragments to display other fragments.
|
Apr 5 | 4:10 PM |
gonzobrains |
they are all full-screen and only one fragment is displayed at any time.
|
Mark M. |
it's possible that you are encountering some issue with nested fragments
|
gonzobrains |
Does nesting have anything to do with the backstack?
|
Mark M. |
um, presumably
|
gonzobrains |
I'm trying to figure out the previous developer's navigation setup. He disabled the back button and forces navigation through the hamburger menu and other fragments.
|
Mark M. |
insofar as if the parent is popped off the back stack, it should pop its children
|
Mark M. |
ick
|
gonzobrains |
I've tried forcing everything on the stack to be popped off when the sole activity's OnPause() is called, but nothing happens.
|
Mark M. |
I'm not sure what to tell you
|
Mark M. |
in the scenario where the child fragment is not getting called with onPause(), is its parent fragment being called with onPause()?
|
gonzobrains |
what is a good resource, besides developer.android.com, I could use to understand more about fragments and navigation?
|
Mark M. |
frankly, after the docs and experimentation, we're down to ouija boards and reading the future in tea leaves
|
Mark M. |
this stuff can get fractally complicated
|
gonzobrains |
hmm, parent fragment. I'll have to look into that because the way I see this should work is only one fragment at any given time associated with the main activity since the back button has been disabled.
|
Apr 5 | 4:15 PM |
Mark M. |
I thought your problem case was where the DialogFragment was shown by another fragment
|
gonzobrains |
the code calls supportfragmentmanager.begintransaction().replace().addtobackstack().Commit() all in one go.
|
gonzobrains |
ahh, no I solved that problem after your last office hour.
|
Mark M. |
"I have tried to dismiss the dialog in the OnPause() of its containing fragment, however the OnPause() is not getting called"
|
Mark M. |
that's in today's chat
|
gonzobrains |
this is kind of separate. not to do with DialogFragment. In this situation, a fragment is calling an AlertDialog. It's similar though.
|
Mark M. |
all dialogs should be wrapped in a DialogFragment
|
gonzobrains |
oh, well, I'm not using DialogFragment here. It is an AlertDialog that's not getting dismissed.
|
Mark M. |
otherwise, you're unlikely to get configuration changes correct
|
Mark M. |
so, try wrapping this dialog in a DialogFragment, and see if that helps your case any
|
gonzobrains |
could you elaborate? This codebase seems to make ample use of AlertDialog.
|
gonzobrains |
Do I have to replace all of them with DialogFragment?
|
Mark M. |
I wouldn't say "replace" as much as "wrap"
|
Mark M. |
have your DialogFragment override onCreateDialog(), and in there put your AlertDialog code
|
Mark M. |
then, show() the DialogFragment
|
gonzobrains |
I will need to research that.
|
gonzobrains |
so any dialogs that are displayed from a fragment should be wrapped in DialogFragment then?
|
Mark M. |
any dialogs *period* should be wrapped in a DialogFragment
|
Mark M. |
(note: a few ancient book examples of mine need updating in this regard)
|
Mark M. |
again: otherwise, you lose the dialog on a configuration change (e.g., screen rotation)
|
Mark M. |
unless this code is using the long-since-deprecated managed dialog stuff
|
gonzobrains |
This AlertDialog class appears to be derived from AppCompatDialog (support v7).
|
Apr 5 | 4:20 PM |
gonzobrains |
Does your busy coder's guide have an example of how to do what you suggest?
|
Mark M. |
I think that only ensures that your Theme.AppCompat-based themes work,
|
Mark M. | |
Mark M. |
let me switch back to Ed for a bit, and I'll return to you shortly
|
Mark M. |
Ed: back to you!
|
Mark M. |
Ed, if you have follow-up from the earlier stuff, or another question, let me know and I can turn back to you
|
Mark M. |
gonzobrains: back to you in the interim
|
gonzobrains |
ok.
|
Ed T. |
I'm here
|
Apr 5 | 4:25 PM |
Mark M. |
Ed: your turn! do you have any follow-up from the earlier stuff, or another question?
|
Mark M. |
in your screenshot, what is the second heading (the "CREDIT CHECK" one) anchored to for its top edge?
|
Ed T. |
A divider
|
Mark M. |
oh, those horizontal bars are separate widgets
|
Mark M. |
what is the upper divider anchored to for its top edge?
|
Ed T. | |
Ed T. |
so it will go white when I throw the switch off and on
|
Ed T. |
but I was expecting it to collapse
|
Ed T. |
like it does in the other layouts
|
Ed T. |
a LinearLayout would collapse
|
Ed T. |
this doesn't. :-)
|
Ed T. |
:-(
|
Mark M. |
so, the divider above "NO CREDIT CHECK REQUIRED!" -- what is its top edge connected to, via a constraint?
|
Ed T. |
A Text View
|
Mark M. |
the "Down Payment $" one?
|
Ed T. |
Everything has a vertical constraint flowing from the top... down
|
Apr 5 | 4:30 PM |
Ed T. |
to the item above it
|
Mark M. |
OK, and so you're saying that when you make all the widgets between "Finance this plan at 0% interest" to the divider above "NO CREDIT CHECK REQUIRED!" set to View.GONE, that the layout is not collapsing?
|
Mark M. |
if you set it to View.INVISIBLE, then I would expect the results that you're seeing
|
Mark M. |
in principle, if those constraints are set up as you describe, GONE should work
|
Ed T. |
testing it now
|
Ed T. |
that got it!
|
Ed T. |
woot!
|
Ed T. |
thanks Mark
|
Mark M. |
um, you're welcome!
|
Mark M. |
I guess I misunderstood what you tried before, because I thought you had tried that and it didn't work
|
Mark M. |
but, if you have working code, that's all that matters right now
|
Ed T. |
I did try it earlier and it didn't work
|
Ed T. |
but I'm betting I didn't have 'wrap_contents' the last time I tried it
|
Ed T. |
lot of moving pieces there
|
Mark M. |
OK
|
Mark M. |
anyway, glad it is working!
|
Ed T. |
so easy to move a TextView and it switch to a size on you
|
Apr 5 | 4:35 PM |
Ed T. |
:-(
|
Apr 5 | 4:35 PM |
Mark M. |
ah, OK
|
Mark M. |
yes, the drag-and-drop editing has its issues, even with ConstraintLayout
|
Ed T. |
if you're not careful
|
Ed T. |
I moved them around a lot
|
Mark M. |
let me switch back to gonzobrains, and I'll return to you in a bit
|
Mark M. |
gonzobrains: back to you!
|
Ed T. |
sure thing
|
gonzobrains |
I'm just researching all the options now.
|
Mark M. |
OK
|
gonzobrains |
I'm not completely convinced the navigation is set up right, especially because the back button is programmatically disabled.
|
Mark M. |
I can understand that
|
Mark M. |
I agree that the user should be able to get around without the BACK button, but disabling it seems harsh
|
gonzobrains |
Can you explain the reason for wrapping with DialogFragment?
|
Mark M. |
configuration changes
|
Mark M. |
by default, rotating the screen, etc. destroys and recreates the activity
|
Mark M. |
that wipes out any dialog you were displaying
|
gonzobrains |
configuration as in the user rotating the screen to landscape or something else?
|
Mark M. |
right
|
Mark M. |
or any one of the configuration changes, though that's the most common one for mobile devies
|
Mark M. |
er, devices
|
gonzobrains |
ahh, okay. I need to see if the app even permits that. it is an in-house corporate app for use on a single device, so it may be forcing portrait.
|
gonzobrains |
but it's good to know that anyway for future reference.
|
Mark M. |
the recommended approach is to show all dialogs via a DialogFragment
|
gonzobrains |
i will look into that.
|
Mark M. |
then, when the fragment is recreated after the configuration change, it will re-display the dialog
|
gonzobrains |
basically, the app disables the back button to force the user to navigate through the hamburger menu.
|
gonzobrains |
I think it was a "cheating" way to avoid more complicated navigation issues.
|
gonzobrains |
will this re-create the dialog when the device's screen is turned off?
|
Apr 5 | 4:40 PM |
Mark M. |
if needed, yes, it should
|
gonzobrains |
what's happening is that my yes/no alert dialog still remains even though the underlying fragment that created it went away. when the user taps the "yes" button it crashes.
|
Mark M. |
what does "went away" mean?
|
gonzobrains |
I'm still thinking that I need to find a way for the underlying "parent" fragment to get its OnPause() called so I can call the dialog fragment's Dismiss() method.
|
gonzobrains |
something with the navigation just isn't right, as if there are two backstacks being created by virtue of how the fragments are being displayed.
|
gonzobrains |
I'm not sure.
|
Mark M. |
ah, OK
|
Mark M. |
what is the expected behavior? is the dialog supposed to be there at that point (and work), or not?
|
gonzobrains |
"went away" = the user presses the power button to make the screen go off.
|
Mark M. |
well, that doesn't directly affect a fragment
|
Mark M. |
any more than it directly affects a TextView
|
Mark M. |
so, a fragment won't "go away" just because the power button is pressed
|
Mark M. |
IIRC, it *should* get paused, as its containing activity is paused
|
gonzobrains |
I see the Main Activity's OnPause() being called, but this particular fragment doesn't get it's OnPause() called if it was displayed by another fragment displaying it. but if I put a menu option for this fragment in the side navbar, it will get its OnPause() called.
|
gonzobrains |
The exact same fragment, just shown a different way and its OnPause() works.
|
Mark M. |
OK, let's give some names here
|
gonzobrains |
sure.
|
Apr 5 | 4:45 PM |
Mark M. |
can you give me a name (fake or real) for the fragment that is giving you trouble, and for the fragment that is the "another fragment" in the phrase "if it was displayed by another fragment displaying it"?
|
gonzobrains |
I have one activity named MainActivity. Then there is a list of completed purchase orders in a fragment called PoListFragment.
|
Mark M. |
I mean, we can use A and B for all I care -- I just want us to agree on the names :-)
|
gonzobrains |
If you touch on a PO in the listview within PoListFragment, the PO will open up in PrintPreviewFragment.
|
gonzobrains |
I choose the print button in PrintPreviewFragment, and a printing progress dialog comes up. if there is a printing error (no printer connected), another yes/no alert comes up and asks if you want to go to the settings screen.
|
gonzobrains |
at that point, if the user turns of the screen and turns the screen back on, the application will resume with the main fragment that starts up every time the app starts, but this yes/no dialog remains on the screen.
|
Mark M. |
OK, stop there for a moment
|
gonzobrains |
ok.
|
Mark M. |
isn't the bug that your PrintPreviewFragment went away?
|
Mark M. |
IOW, shouldn't your app be in the same state after the screen turns back on as it was just before the screen was turned off?
|
gonzobrains |
well, yes and no. I agree with you that the menu should allow the user to resume where they left off, but as the app is currently designed the user is supposed to be forced back to the main screen.
|
Mark M. |
oy
|
gonzobrains |
so for the time being I have to work with that restriction.
|
gonzobrains |
sorry, i meant "that the app should"
|
Apr 5 | 4:50 PM |
Mark M. |
OK, so, what exactly is causing PrintPreviewFragment to go away? are you specifically running a FragmentTransaction to detach/hide/replace/whatever it?
|
Mark M. |
or popping the back stack?
|
gonzobrains |
lemme check.
|
Mark M. |
dismissing the dialog should be tied to whatever happened to the fragment
|
Mark M. |
so, if the fragment was detached, you'd dismiss the dialog in onDetach()
|
gonzobrains |
ahh, I see that OnStart() for the activity navigates to the start fragment by popping the back stack (inclusive) and then beginning a new transaction to add the "home" fragment to the backstack.
|
Mark M. |
OK, so, your PrintPreviewFragment should be getting a callback at that point
|
Mark M. |
what callback would depend a bit on the transaction that caused it to be displayed
|
Apr 5 | 4:55 PM |
Mark M. |
worst-case, temporarily override all the "negative" callbacks (onDetach(), onDestroy(), onDestroyView(), onHiddenChanged()), see which are getting invoked, then choose the best candidate in which to dismiss the dialog
|
gonzobrains |
yeah, but that doesn't happen if PrintPreviewFragment is called from PoListFragment. It does if I started it from the side-drawer. I see there are two different methods depending on whether another fragment shows a new fragment of if the side-drawer started it. I will try to compare the two.
|
gonzobrains |
okay, lemme soak that in.
|
Mark M. |
when PoListFragment shows PrintPreviewFragment, which FragmentManager is it using? getSupportFragmentManager() or getChildFragmentManager()?
|
gonzobrains |
ahh, I haven't tried all of them. I think I only tried onDetach() and onDestroy(). if OnHiddenChanged() works, then that will fix this dialog problem in the short-term, but I should still see if the code is abusing this navigation/backstack system.
|
gonzobrains |
getSupportFragmentManager()
|
Mark M. |
oh, it probably is :-)
|
Mark M. |
hmmm, OK, that's the same as what MainActivity is using, so it's not a nested fragment issue
|
gonzobrains |
you know, I solved my last problem i discussed with you a few days ago by invoking the DialogFragments using getChildFragmentManager() though.
|
gonzobrains |
I didn't think I should use child in this case though.
|
Mark M. |
it doesn't feel like it is a child fragment scenario to me either
|
Mark M. |
but, I don't know much about your code base
|
Mark M. |
BTW, Ed: any quick final questions?
|
Ed T. |
it's a simple one if you have time
|
gonzobrains |
I was wondering, since the back button is disabled, if I should just pop whatever is currently on the backstack before navigating to any new fragment.
|
Ed T. |
if not... you can cal lit
|
Ed T. |
'call it'
|
gonzobrains |
go for it, Ed.
|
Mark M. |
Ed: go ahead
|
Apr 5 | 5:00 PM |
Ed T. |
is there an easy way to do a "%S Customers"
|
Ed T. |
where that is a var passed in
|
Ed T. |
to a strings.xml resource
|
Ed T. |
or would you advise against it?
|
Mark M. |
no, that's fine
|
Mark M. |
use a lowercase s
|
Mark M. |
"%s Customers"
|
Ed T. |
will do
|
Ed T. |
thanks!
|
Ed T. |
have a great evening
|
Mark M. |
and there's a variant of getString() that takes a varargs that can be used to fill in the %s, akin to String.format()
|
Ed T. |
ty
|
Mark M. |
you might also look into plural resources, since you wouldn't want "1 Customers"
|
Ed T. |
have a great evening Mark!
|
Ed T. |
cheers
|
Ed T. | has left the room |
Mark M. |
OK, that's a wrap for today's chat
|
gonzobrains |
thanks again!
|
Mark M. |
you're welcome!
|
Mark M. |
the transcript will go up on https://commonsware.com/office-hours/ shortly
|
gonzobrains |
ok.
|
Mark M. |
the next chat is Monday at 9am US Eastern
|
Mark M. |
have a pleasant day!
|
gonzobrains |
cool, thanks.
|
gonzobrains | has left the room |
Mark M. | turned off guest access |