My App is supposed to show a plain LinearLayout with a ListView and TextView when in portrait, but a SwipeView with three tabs when in landscape. The layout is to be changed whenever the orientation of the phone is changed.
I get that normally you'd just have two layout files for portrait and lanndscape but I feel that won't be sufficient in my case. After all the Tab and Swipe functionality requires more than just an XML file. While looking for solutions to my problem it was suggested starting a new activity in the onConfigurationChanged() method, but at the same time this was stated to be very bad practice leading to all sorts of problems.
Now I thought about adding a whole lot of if-else statements to my TagActivity.java always checking what the current orientation is and spawning whatever is needed. Would this be a good way to do it? Is it possible to have multiple onCreate() Methods, one for each orientation?
Any input would be greatly appreciated!
The tutorial I used to implement the TabActivity was the one from androidhive:
http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/
I did something similar in a recent project. We ended up using a view pager with PagerSlidingTabStrip (https://github.com/astuetz/PagerSlidingTabStrip/issues/5). In portrait only show one fragment in the view pager and hide the tabs, and in landscape populate out the view pager and tabs. Not sure if this works in your particular situation (it seems like it would), but food for thought.
Related
What I would like to achieve: Have a ViewPager with TabLayout where each Tab contains a new Fragment that has a RecyclerView layout out horizontally and managed by a FragmentPagerAdapter.
What I am struggling with: The default behaviour is that when you get end of the list on one of the tabs, it switches Tabs and snaps (snapping means if you pull over 50% of the viewport, it jumps to either direction). I want it to free-flow and not to snap. Sort of like how it happens in iOS by default.
I got inspired for this setup by the following two CodePath guide:
https://guides.codepath.com/android/google-play-style-tabs-using-tablayout
https://guides.codepath.com/android/ViewPager-with-FragmentPagerAdapter
How should I approach this problem (preferably without any other libraries)?
What I would do is use HorizontalScrollView instead of a ViewPager. The only caveat is that the view pager sends the lifecycle events to fragments as you scroll between them, whereas for HorizontalScrollView you will have to add them initially, and then they will be continuously active unless you manually change that. Also you may have an option to not use the fragments and use simple views depending on what you use the fragments for.
I would definitely not override the touch events for the ViewPager because it does some cleanup when it detects the UP motion, so just swallowing it is not a correct thing to do.
I am trying to create a layout in an activity that will look different in landscape and portrait, however it will contain the same sections, just in different places on the screen.
Most examples I find on fragments is always the list and detail, which is not what I'm looking at.
In my example I have, amongst others,
a scrolling image section (carousel)
a page title with some brief details
a carousel of thumbnails
two buttons
full details of the page
Now in the landscape layout, the image section will always be on the left side with down the right side, the page title, carousel of thumbs, two buttons and full details.
In the Portrait the title will appear at top, with image carousel beneath, then thumbs, then buttons etc.
The way it works in my head, is that each section should be a fragment, and then depending on the layout file in the respective res/layout folder corresponding to land/port, the fragments are arranged accordingly. But I'm also thinking is each section a whole fragment? Or could it be a separate view that get's loaded in, but just in a different order depending on the screen orientation.
I hope that made sense?
Does anyone have any good tutorials that explain exactly when you should and shouldn't use fragments. All the usual suspects just list the list/detail example, which is not applicable in my case.
tl;dr Can I use fragments as modules/blocks in various layouts or should I just create other layouts and display them inside the main layouts.
Fragments can be used to have split screen and to store previous state unlike views. It is difficult to manage back button with views
If you just want to change how the screen is laid out, the answer is neither. You can define orientation-specific resources (either a separate layout file for each orientation or different dimensions/constraints for each orientation) and the system will just provide you with the correct resource set for the current orientation.
That said, it sounds like you may be describing a modified version of master/detail flow. If this is the case, fragments are a good way to go since the landscape view is actually several separate screens in the portrait version of the app, so each section needs it's own state and lifecycle, which fragments provide.
Now, I know you said you wanted an example beyond a list and detail view, so here's some more details on when to use fragments:
Fragment, like activities, have state and lifecycle. Custom views do not have lifecycle and are completely dependent on the activity or fragment containing them.
You might use a custom view when you have a widget on screen that is used in multiple places and is just like any other view – bound to the activity when the layout is inflated and controlled from there. It's a way to either reduce duplicating combinations of views in your layout or to draw a custom view that doesn't exist yet.
Fragments are good when you need some state or lifecycle for a section of the app that might get used in multiple places or shouldn't be logically connected to the activity it is contained in. If you use the new Navigation Component, you actually just define one activity and then each screen in the navigation tree is a fragment that gets swapped out as the user navigates around the app. Here each child component on the screen (each "screen" that the user navigates to) has it's own lifecycle, business logic, etc, so mixing the code for all of that in the activity wouldn't make sense.
So the question comes down to what you are trying to build, and this may be a case where the best way to learn the difference is to try each option out as bit. The differences become more clear with practice using them. As a general rule of thumb, personally, I only really use custom views when I am trying to make a new view that doesn't exist elsewhere. If what I'm trying to do is simply a matter of laying out existing views in a new way, the answer is probably some trick in the layout file or layout code inside the activity. If I'm trying to make a stand-alone piece of the app that does stuff, especially if it also appears in multiple places in the app, I'll probably be building a fragment.
The problem is ive got sort of book reader, landscape shows two pages and portrait just one. For some reason I blocked destroying activities on config change. the story is pretty much the same like here ViewPager + FragmentStatePagerAdapter + orientation change. Although the question is bit different - Id wish to store not 3 but 5 fragments. its about rendering time, Im easily handling swipe stuffs with adding +-1 in portrait and +-2 in landscape, though the problem is, in landscape orientation, it wont render proper next / previous fragments. As obviously its rendering +1 and -1 items, I want +2/-2 items to be instantiated instead. So theres either some kind of solution that changes positions to instantiate in landscape (which im not aware of though), or storing 5 items in an adapter instead of just 3.
Anyone with any sort of proper solution?
You can store 5 items in the adapter by setting the OffscreenPageLimit of the ViewPager to 4:
viewPager.setOffscreenPageLimit(4);
hope that I've helped you.
try this:
mViewPager.setOffscreenPageLimit(4);
I am using fragments in combination with tabs to display some content. One of those fragments displays data that gets updated with an async task. Since I want to keep the content that was generated on configuration change, I set android:configChanges="orientation" in my manifest file.
This works just fine for the fragment.However, now I have got another problem: One of my other fragments uses a custom landscape layout. This landscape layout is not set on configuration change. I guess it is because I defined in my manifest to handle the configuration change.
Now, how can I force my fragment that uses the custom landscape layout to use the landscape layout on configuration change? What do I have to put in my onConfigurationChanged() method?
I haven't hit this situation myself, so I'm not sure (I've hit it with Activities, and the answer was to call setContentView again, then transfer over the data/state needed). But have you tried deattaching then reattaching the fragment, so it gets to recreate its view? Then you can re-inflate the view, which should inflate in the new mode.
If the differences are minor between the two layouts, another technique is to put both in 1 layout file and fiddle with visibilities on orientation change.
I have a question related to fragments, the only solution to change the fragment layout it's if I remove the old instance and replace with new one?
I have two layout's one for portrait and one for landscape - I want to keep all the information's(data) and only replace the layout the onConfigurationChanged() method is called, but I can't force the fragment to recreate the layout.
Thanks, Lorand
I don't know whether you can only change your layout without reloading your data.
My solution is
Don't put android:configuration='orientation'
in the manifest.xml.
When rotating screen, normally onCreateActivity will be call and it'll take the good layout AND RELOAD your data.