CoordinatorLayout with different Toolbar behaviour - toolbar

I'm having difficulty in implementing CoordinatorLayout as how to implement the Toolbar if some of my Fragments have a different Toolbar behaviour. Say, that I have 5 fragments that would be shown in just one Activity (one fragment at a time). 2 of them would have a auto-hide Toolbar when scrolled, 1 with a simple Toolbar that's always showing even when scrolled, and 2 having Toolbar with ImageView inside AppBarLayout for parallax effect.
This link only cover the auto-hide part, but not the parallax with image.
Some solutions that I could think of :
Have one AppBarLayout with Toolbar and ImageView in Activity. So if it displays a fragment that doesn't need the parallax effect, just set the ImageView's visibility to GONE. But is it okay to do this? Because I got the feeling that it's not an appropiate solution.
Define CoordinatorLayout and Toolbar in each fragments' layout. But then I have to call setSupportActionBar everytime I'm displaying my fragment, when some of them actually have the same Toolbar.
Which is the best approach? Or maybe there is a better one than those two?
UPDATE
So, I ended up with number 2. I just add toolbars to each fragments' xml just like usual, nothing special. And in my BaseActivity I create a method to set the toolbar as action bar with some default configuration, so I won't have to duplicate the syntax to each of my fragments. Here's the method:
public void setToolbar(Toolbar toolbar, String title){
if(toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(title != null);
if (title != null) setActionBarTitle(title);
}
}

Related

SwiftUI Buttons and their tappable areas shifted away and doesn't cover anymore

I have the problems with views and especially buttons as they can be tapped (but it applies to all views) that they tappable (focus area) shifted a bit from rendered views.
Layout stays ok but if you want to tap at the button its tappable area is shifted downward and to the right. So instead of clicking at the button you click a bit downa and right to it. Otherwise there is no action executed.
The best it can be seen on this view from Debug view hierarchy. It happend after returning from modal presentation. But I cannot see any clue in code way that can happen. We on which it happens seems to be no different from other views that work absolutly right.
I can see that wrapping VStack inside ScrollView breaks this view, but it doesn't happan on other similar views.
var body: some View {
NavigationView {
ScrollView(.vertical, showsIndicators: false) {
Group {
contentView
contentView
contentView
contentView
contentView
contentView
contentView
contentView
}
contentView
contentView
contentView
contentView
}
.padding(.horizontal)
}
.navigationViewStyle(.stack)
}
Ok I found it. The problem was that content of this view depends on #Published property like shoulDisplayView1Or2. And depending whether it was true or false it displayed view1 or view2.
Moreover this property was set in the same time when presented modal view (sheet) was dismissing. Like after some action do to things 1. dismiss modal and set new value of shouldDisplayView1Or2. And this sheet dismissal and adjuting view1 or view2 based on shouldDisplayView1Or2 flag caused that this buttons rendered areas and their tappable areas become shifted away.
What fixed this issue was addition of DispatchQueue.main in Combine subscription or DispatchQueue.main.async { } in regular code in place where this flag shouldDisplayView1Or2 was setting. This way I suppose dismissing comes first and adjusting view1 or views with its rendering second, and overall layout wast rendered correctly with tappable areas on its place.

UITabBarController in UISplitViewController with Storyboard

I have UISplitViewController with UITabBarController as its master. UITabBarController contains one UINavigationController with UITableViewController as its root (it is main menu of my app).
After tapping on any cell in main menu, in UISplitViewController's detail part another UITableViewController should be presented (let's call it detail view).
In landscape mode everything works OK.
But in portrait, whet I tap on cell in main menu, the detail view is presented modally, and not pushed, like it supposed to. Also, when rotating from landscape to portrait, the main menu is presented instead of detail view, and after I click on main menu's position to show detail view, it is presented modally with no possibility to rotate or to go back.
Removing UITabBarController and setting UINavigationController as UISplitViewController's master works as I want (in landscape mode we have menu|detail views side by side and in portrait mode controllers behave like they were on regular UINavigationController). But then the UITabBarController is gone.
What I've tried:
every possible segue type - none of them works the way I want
subclassing UIStoryboardSegue to implement custom behavior depending on UISplitViewController's viewControllers param (in portrait mode it has only one view controller - master) - but I couldn't recognise classes (thank you Swift!)
What I want is to do it entirely in Storyboard (OK, custom segues doesn't count) - I want an elegant solution and I refuse to believe it's impossible.
Working on iOS 8 SDK, Xcode 6.2, iPhone 6 Plus
Unfortunately there is no absolutely elegant solution to this one (as far as I've managed to accomplish). Hoping that Apple will eventually sort it out, but in the meantime, this is the nicest way possible:
Place one custom segue instead of Show Detail
In perform method of your custom segue have something like:
- (void)perform
{
MasterViewController *source = self.sourceViewController;
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
UISplitViewController *splitViewController = appDelegate.splitViewController;
if ([splitViewController.viewControllers count] > 1) {
[source performSegueWithIdentifier:#"showDetail" sender:source];
if (appDelegate.masterPopoverController) {
[appDelegate.masterPopoverController dismissPopoverAnimated:YES];
}
} else {
[source performSegueWithIdentifier:#"showDetailSmallDevice" sender:source];
}
}
[splitViewController.viewControllers count] is here just to separate large devices (iPads & iPhone 6 Plus) and the other, smaller ones
In your Storyboard, wire up one segue named showDetail which is actually a showDetail, to the detail navigation controller, and directly to the contents view controller another showDetailSmallDevice which is actually Show
(Push)
See the example:
http://i.stack.imgur.com/GQpg3.png
EDIT: SplitViewController needs two Navigation Controllers. The solution is that you need to insert another Navigation Controller between the SplitViewController and the DatailViewController. Then, from the TableView, preform a Segue directly to the second Navigation Controller. The SplitViewControllers wants two Navigation Controllers...
Maybe a good way could be to start a new SplitViewController project on IB. There are various default methods and properties to manage a SplitViewController. You can find something in appDelegate class, it could be a good starting point.
OLD: I like Mateusz's answer, just a point that is possible to use self.splitViewController.isCollapsed for testing if DetailViewController is or it could be shown on screen. With this property there is no need to count viewControllers.
#property(nonatomic, readonly, getter=isCollapsed) BOOL collapsed
From documentation: A Boolean value indicating whether only one of the child view controllers is displayed. This property is set to YES when the split view controller content is semantically collapsed into a single container. Collapsing happens when the split view controller transitions from a horizontally regular to a horizontally compact environment. After it has been collapsed, the split view controller reports having only one child view controller in its viewControllers property.

UI Layout, fragments and different content

I'm studying fragments and "Multiple devices support". Depending on device type, orientation and dimension, it's possible to define multiple layout using fragments and re-using written code. During the develop of an app, I wrote down my desired UI for tablet devices, as described in the following screenshot:
The activity contains two fragments and displays TAB menu navigation. Every TAB menu navigation contains different menu entry (listview).
When clicking on a menu's item on fragment 1, I need to refresh the fragment number 2.
Fragment 2 is composed by a presentation and, below, a listview or another presentation.
Every menu's item could have different layout:
1-Presentation, image, another presentation
2-No presentation, listview
3-Presentation, listview
4-etc.
Studying examples (samples) provided with google-sdk, fragment 2 have always the same layout. How it's possible to tell fragment 2 to load different layout depending on menu's item clicked?
My answer is: I need a fragment class for every different layout. When the user click on an item of fragment 1, the fragment manager should replace and commit the correct fragment. Is this answer correct?
All fragment logic will be on my activity, replacing the correct fragment depending on item selected (position and category); simple ex:
#Override
public void onItemSelected(int category, int position) {
if (position==0){
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content_frag, new FirstActionFragment(), "FirstMenuClicked");
ft.commit();
}
else {
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content_frag, new SecondActionFragment(), "secondMenuClicked");
ft.commit();
}
}
Is my layout idea improvable? Should I change something on my design to correctly implement fragmentation?
Here is the solution of your problem
https://github.com/theomega/ActivatedStateDemo

Trouble with Flex 3 PopupManager

I'm trying to use the PopupManager class in a Flex3 AIR app to open different kinds of panels but I'm running into some problems with it. I'm using a method like the following with which all panels are opened ..
private function createPopUp(clazz:Class, modal:Boolean = false):IFlexDisplayObject
{
var p:IFlexDisplayObject = IFlexDisplayObject(PopUpManager.createPopUp(_windowParent, clazz, modal));
PopUpManager.centerPopUp(p);
return p;
}
_windowParent is a reference to the application's WindowedApplication root object. I'm running into two kinds of problems with this:
Not all popups appear modal, even if I set the modal parameter to true. This seems to happen if I open a popup panel from within another popup panel.
In some of the popup panels are ComboBoxes and the popdown menu of the comboboxes opens underneath of their parent panel (i.e. under the depth of the panel) so the menu of the combobox becomes partly or fully obstructed.
I've tried different parameters for the PopUpManager.createPopUp() childList parameter (e.g. PopUpManagerChildList.APPLICATION) but that did not change anything.
Hoping that anyone has some tips on these problems!
Nevermind! Figured out I some code that would change the depth of panels that was messing this up.

Autorotate with a UINavigationController

I am a little unclear on how to rotate views that are sitting on a UINavigationController.
I have overridden the UINavigationController object with one of my own that overrides:
(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { return YES; }
I have one view on the stack on the controller and that view is loaded from a xib with two views in it. I want to switch from portrait to landscape. Normally I would handle this by changing the view from within the nib files of the view itself. Do I have to implement the rotational code within the Navigation Controller or just within my view code?
(void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
That willAnimate code is what I'm used to using in the view itself, but I'm still not seeing the view being changed, and I'm thinking it may be that I need to access the view in the NavigationController and change that, or even override the same method in the Navigation Controller and do my view switching there.
Any suggestions? I've never actually done this before and just found out the TabViewControllers and NavigationControllers are both portrait mode only by default.
Turns out it wasn't possible to change the view because I was trying to changes the RootView on the Navigation Controller. I got around this by placing my own pseudo root view controller that never gets seen in the root spot on the Navigation stack. I overrode a few of the navigation controls to account for this so the functionality would continue the same and I'd be able to change my desired perceived root view as I needed to.
A start in the right direction can be found in this link:
http://starterstep.wordpress.com/2009/03/05/changing-a-uinavigationcontroller’s-root-view-controller/

Resources