Apr 24

Perhaps not broken, but documented inadequately. In http://developer.android.com/training/implementing-navigation/temporal.html there’s a simple guide on how to set up back stack navigation when opening an app e.g. from a notification using a “deep link” to an activity that is not the topmost one in the app, so that the user can navigate upwards in the stack by pressing the back key.

Having wasted a couple of hours trying to make this work in LoanShark, I finally noticed a warning in LogCat:

W/ActivityManager﹕ Permission Denial: starting Intent [...] not exported from uid 10131

What the documentation forgot to mention is that you need to set the activity you want to jump to from e.g. a notification as exported. I added the attribute and encountered no more problems. The weird thing is that it did actually sometimes work even without the exported attribute… strange indeed. But now it works 100% of the time, fortunately.

Apr 16

I’m currently in the process of making the landscape support in LoanShark more robust. When in portrait mode, the main activity displays a list of loans, while the view loan activity, opened by selecting an item from the list, displays the selected loans’ details. In landscape orientation both views are visible. These are all implemented using fragments, i.e. the activities themselves only provide the layout to glue the fragments together.

When holding the device in portrait mode, the loan view displays loan details using the same fragment class as is used on the right-hand side in landscape orientation. When the user is viewing a loan in portrait (view loan activity), and rotates the device to landscape (to main activity), the same loan is displayed.

The problem I’ve come across is that since fragment objects belong to a single Activity (stored in the Activity object’s own FragmentManager instance), there’s no way to reuse the fragment that’s seen in portrait mode of the view loan activity on the right-hand side of the landscape layout in the main activity. The reason is that when the user rotates from portrait to landscape, the activity hosting the loan details is destroyed, which in turn destroys the fragment as well.

To keep my fragment implementations modular (to break direct dependencies between them), I’ve utilized callbacks to the hosting activity class when loaders have finished their jobs. This way I’m able to know e.g. when a loan’s details have been finished so that the fragment can be created.

My initial implementation (and the one being used in version 2.2.0) is that the old fragment that was created when in landscape mode is displayed briefly before being replaced with the loan that was selected in portrait mode. This is clearly suboptimal because there’s a clear visual anomaly, however brief, when rotating the device. I considered patching the problem by hiding the existing fragment in landscape,  thus preventing the old fragment from being shown before fading in the fragment when then the new loan would have been loaded. That wouldn’t have been a solution I would’ve been satisfied with, so clearly more thinking was needed.

When a loan has been loaded in portrait mode and is about to be displayed in the view loan activity, I store the loan data in the main activity as well (and make sure it’s saved in onSaveInstanceState() in case the activity is destroyed while viewing the loan data). Then, if the user rotates the device to landscape, I check if the view loan fragment already exists (in case the device has been in landscape mode previously, it does). In such a case, I set the selected loan’s data to the existing fragment. When the activity’s onCreate() finishes, the fragment’s onCreateView() is called, and it’s there that the loan data can then be reused.

Nothing of this sort is mentioned in documentation concerning fragments. Also, it’s quite difficult to find solutions to fragment problems by googling them; all you seem to get is countless beginner tutorials on how to use fragments. I came across this solution after spending a couple of nights figuring out how the fragment management works internally, and from there I had an idea how to go on about solving the problem.

Apr 03

TextView with italics text gets cropped at the rightmost edge when the view is set to wrap_content. Reportedly this affects when the content is set to have gravity=”right” as well.

http://stackoverflow.com/q/4353836

I haven’t plunged into the source code on this one, but it seems that Android’s layout engine evaluates the TextView’s width based on the text baseline, and does not take into account the fact that skewing the text may result in the projected baseline at the top (whatever it could be called) may not be the same. The solution is to simply add a space character at the end of the string.

I ran into this problem when designing the card layout for LoanShark loans. I wonder how many applications’ layouts would break if there was to be an actual fix to this problem…

preload preload preload