I'm using a standard ViewPager inside an Activity. Very basic stuff:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/toolbar" />
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/new_teal"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Now, in my acitivity's code, I have an OnPageChangeListener which I'm using to switch the title in the toolbar whenever the viewpager's views are paged through.
I'm also calling setTitle(...) to set the title for the initial screen.
The issue with all of this is that I'm setting setOffscreenPageLimit(...), and when I do, that initial call to setTitle(...) gets overridden or hidden or something. The title just disappears!!!
If I remove setOffscreenPageLimit(...), then the entire thing misbehaves, as expected.
Any ideas???
For a effective solution we need to see your fragment's code but if you do not set a offScreenPageLimit to a view pager it create 1 previous and one next fragment of your current fragment. All these three fragments gets created and calls default fragment lifecycle methods such as onCreate, onViewCreated and etc.
If you are changing your title in one of your fragments which will be created when you set offScreenPageLimit to 2 or more, you can get this behave.
For example let's say your current Fragment is C and your view pager contains a b C d e and you change title in a or e fragments or other fragments in second or more position.
I hope this'll help you.
Related
My App uses a single activity architecture which has a NestedScrollView in the activity layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.navigationadvancedsample.MainActivity">
<androidx.core.widget.NestedScrollView
android:id="#+id/app_scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true">
<FrameLayout
android:id="#+id/nav_host_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</androidx.core.widget.NestedScrollView>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="#menu/bottom_nav"/>
</LinearLayout>
My issue is that that when I scroll a fragment, then navigate to another, then go back, the scroll position is reset. I've seen another answer which stated that adding IDs to the layouts should fix the issue, but it hasn't for me. Also, interestingly, the scroll position saves fine on configuration change.
I'm using NavigationComponents, could this be related? Here's a sample project that reproduces the issue (based on Google's NavigationAdvancedSample)
NestedScrollView has wrapped the Navigation Container in the activity_main layout. So it is the activity that saves the scroll state. There are 3 fragments. Home fragment has fixed height, Leaderboard and Register fragments are scrolling. When you scroll in the Leaderboard or Register and switch to the other one the scroll state does not change(since both can scroll to roughly the same height) but if you switch to home fragment scroll state resets because it has fixed height(size of the screen). Replacing NestedScrollView with the ScrollView didn't change anything as I examined it.
I think the right design is to wrap each fragment with NestedScrollView and set and get scroll state for each fragment.
Navigation component does not add the fragment to the activity state but replace it. So fragments get recreated after by switching between them. So you see scroll state is being reset. You can check it yourself by putting some log in the onCreateView of first fragment and see the log appears twice.
I have a tab-based app. I am using A TabLayout for my tabs and a subclass of FragmentStatePagerAdapter to instantiate the fragment for the selected tab. I have disabled swiping between tabs. I am still seeing a callback to create a fragment for tabs adjacent to the selected tab. In other words, if the tab at index 0 is activated, I also see a callback to GetItem for the tab at index 1.
I want to disable that behaviour. In other words, it should only request a fragment for the active tab. Is that possible?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/root">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabPaddingStart="0dp"
app:tabPaddingEnd="0dp"
app:tabPaddingTop="0dp"
app:tabMode="fixed"
app:tabGravity="fill" />
<jockusch.calculator.droid.AndroidViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
The reason this is happening is due to you using a ViewPager.
ViewPager, by default, will auto-create the adjacent Fragments because this allows the user to swipe to them whenever they wish. Creating them only when they're ready to swipe might cause lag or some unpleasant visual effects.
ViewPager has a method called setOffscreenPageLimit(int limit) which can limit the amount of adjacent it keeps in memory, however I believe it's not possible to decrease it to 0 due to ViewPager's innate behavior.
If you've already disabled swiping between tabs, then it sounds like what you want isn't a ViewPager. Consider just using FragmentTransactions to replace the active Fragment.
viewPager.setOffscreenPageLimit(0)
is what you are looking for.
But a ViewPager doesn't allow offscreen limit less than 1.
source
Use something else than a viewPager to get your desired effect. One way of doing it without viewPager would be to have a frameLayout instead and inflate a new fragment and destroy the previous one when a tab is selected.
My app has a log_in activity, a main activity, and a settings activity.
The main activity is currently working by flowing between multiple fragments:
In the first fragment, the user selects a topic (from a dynamically-populated recyclerview of cardviews), the topic is then parceled and sent to the second fragment.
The second fragment displays the appropriate list (another dynamically-populated recyclerview of cardviews (formatted very differently, with different cardviews). The user can go back to the first fragment and choose another topic, and that choice is again parceled and sent to the second fragment to display the relevant list etc.
I want to set up the 2nd "page" so that it has 1 fragment at the top, which covers the top 80% of the screen, and 1 fragment at the bottom, which covers the bottom 20% of the screen, while still having only 1 fragment on the first "page" that covers 100% of the screen.
This is how I'm switching between each fragment in the flow right now:
main.java
bundle = new Bundle();
bundle.putParcelable("itemlist", itemlist);
fragment = new fragment_2();
fragment.setArguments(bundle);
fragmentManager = getSupportFragmentManager();
transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment).commit();
And my activity_main.xml (for the main activity) has this layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/ColorBG"
tools:context="com.app.activity.main">
<FrameLayout
android:id="#+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>
So main_container is the FrameLayout that I'm replacing with the relevant fragment.
I can't find any clean example of a way to do this, can anyone show me?
The only thing I can think of is to have 2 FrameLayouts in the activity_main.xml, and have the 2nd container start as layout_width="0" and layout_height="0", but I feel this is a bad way to do it. Is there any way to replace the LinearLayout itself with another LinearLayout that has 2 FrameLayouts in it, and then assign the appropriate fragments to those containers?
Or what is the best way to do it?
I want to do things "the right way" (so I do not want to have separate activities) and I'm targeting API 16, but I may be willing to go up to API 23/24.
You can use weightSum property of LinearLayout to divide in 80:20 ratio.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3"
android:orientation="vertical">
<FrameLayout
android:id="#+id/frame1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"/>
<FrameLayout
android:id="#+id/frame2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
For using the same layout where you want to give 100% you can set the visibility of frame2 to GONE and can dynamically set the layout of frame1 to 3 (total of weightSum which will make it 100%).
I have a layout in my head that should look like that: http://i.imgur.com/H1nTRvd.png
Only part that will be dynamic is the blue one. I don't know the number of tabs that will be created before I load the activity, hence the number is acquired from server (could be either 5 or 24 for all I know).
The bottom buttons should not move when I swipe and the blue area changed.
Currently I have this implemented w/o tabs list using embedded fragment in my activity and gesture listener. There's no good looking transaction animation between fragments.
#Nick Pakhomov: You can use PagerTabStrip
PagerTabStrip
is intended to be used as a child view of a ViewPager widget in your XML layout. PagerTabStrip is most often used with fragment, which is a convenient way to supply and manage the Lifecycle of each fragment.
So here’s how a ViewPager with a PagerTabStrip in it would look like in the layout file:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTabStrip
android:id="#+id/pager_tab_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:textColor="#fff"
/>
</android.support.v4.view.ViewPager>
Please check this PagerSlidingTabStrip demo . I hope it will helps you .
I have a viewpager in my main activity, and viewpager contains a few pages (exactly a few fragments). I want to go from my viewpager to another fragment which isn't in viewpager. How can I do this?
Here is my activity_main.xml :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.slpd.Activities.SLPDActivity">
<com.slpd.SlpdViewPager
android:id="#+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
Why do you want to go to another fragment?
If there is one or more fragments you want to transition to, simply add a new activity which looks like your SLDPActivity and inflates a layout with another ViewPager.
If it is only one fragment you want to transition to, why not simply making it a new activity in the first place?