Problems replacing an android fragment - android

What I have:
I am using the latest Android support and design libraries on API 22. I have a fragment called ProgressFragment which I only run when my app is first installed as follows:
mProgressFragment = new ProgressFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_container, mProgressFragment, TAG_TASK_FRAGMENT)
.commit();
This is the layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/progress_frag"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/toolbar"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
>
<ProgressBar
android:id="#+id/build_lib_progressbar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/progress_msg1"
android:layout_gravity="center"
android:textSize="22sp"
android:textColor="#color/text_primary"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/progress_msg2"
android:layout_gravity="center"
android:paddingTop="10dp"
android:textColor="#color/text_secondary"/>
</LinearLayout>
</LinearLayout>
This fragment contains an AsyncTask. When it completes, it is replaced by another fragment (called MainFragment) in MainActivity inside the AsyncTask callback onPostExecute() like so:
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_container, new MainFragment())
.commit();
This is the MainFragment layout:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/main_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.AppBarLayout
android:id="#+id/main_appbar_layout"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<include layout="#layout/toolbar" />
<android.support.design.widget.TabLayout
android:id="#+id/main_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabIndicatorHeight="4dp"
app:tabTextColor="#color/white"/>
</android.support.design.widget.AppBarLayout>
EDIT:
And this is MainActivity's layout:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fab="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Main content displayed here -->
<FrameLayout
android:id="#+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Navigation Drawer -->
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_drawer_header"
app:menu="#menu/nav_view_menu"
android:background="#ffffff"
app:itemTextColor="#color/text_tertiary"
app:itemIconTint="#8b8b8b"
/>
The Problem:
When the AsyncTask in ProgressFragment completes and is replaced by MainFragment, the TabLayout view does not display tabs:
My application has 2 possible paths at startup. It either:
Adds the ProgressFragment (if first run) -> then replaced by MainFragment
Adds MainFragment otherwise (tabs show up fine here)
Both Fragment replacements happen in MainActivity.
The problem deals with path 1
EDIT 2:
Calling recreate() in MainActivity "fixes" this for now. Though I wouldn't call it a solution. Will come back to it later.

UPDATE: It was a bug on v22.2.1, solved on newer releases
Found the problem here: https://code.google.com/p/android/issues/detail?id=180462
Simple workaround:
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});

Related

ViewPager is blank when returning to it using back button

My application is pretty simple.
I have 1 Activity, and three fragments.
When activity is being loaded it loads fragment that consist of ViewPager.
I use ViewPager to show news, first fragment in ViewPager shows new news, the second shows read news.
Everything works good, but when I click on news and open ContentFragment to show it and then click back button to return to fragment with ViewPager. ContentFragment disappear but Fragment with ViewPager remains blank. I debugged and made sure that methods like onCreateView and etc. are being called, but fragment is still blank, I'm confused.
What is wrong with it?
MainActivity
<androidx.drawerlayout.widget.DrawerLayout
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=".activity.MainActivity"
android:id="#+id/activity_main_layout_id">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_content">
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
android:id="#+id/navigation_view">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/swipe_refresh_layout">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawer_recycler">
</androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
On startup it shows Fragment with ViewPager
private fun showList() {
val fragmentTransaction = supportFragmentManager.beginTransaction()
val newsPagerFragment = NewsPagerFragment()
fragmentTransaction.replace(R.id.main_content, newsPagerFragment)
fragmentTransaction.commit()
}
NewsPagerFragment
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.NewsPagerFragment"
android:orientation="vertical"
android:id="#+id/news_list_fragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/swipe_refresh_layout">
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.viewpager.widget.ViewPager>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<com.google.android.gms.ads.AdView
android:id="#+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
ads:adUnitId="#string/ads_banner_id_test"
ads:adSize="BANNER" />
</LinearLayout>
NewsListDataFragment used in ViewPager to show news.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_height="match_parent"
tools:context=".fragment.NewsPagerFragment"
android:orientation="vertical"
android:id="#+id/news_list_fragment">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/news_list_recycler"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
And when we click on some news it calls
private fun onPreviewNewsClick(news: PostEntity) {
val contentFragment = NewsContentFragment()
val transaction = fragmentManager.beginTransaction()
transaction.replace(R.id.main_content, contentFragment)
transaction.commit()
}
NewsContentFragment
<FrameLayout 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=".fragment.NewsContentFragment"
android:padding="5dp"
>
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/news_content_webview"
>
</WebView>
</FrameLayout>

Getting blank space in tabbed activity fragment launch

This is my first fragment that is getting launched in the first tab. This fragment has a button clicking which I am supposed to launch this fragment with a new fragment. But while I do so the new fragment gets launched but there is a space on the top.
See the below picture:
In fact, the entire replaced fragment got slid down and went out of the screen below.
Those who are assuming that I have added a marginTop or paddingTop, to inform I have not added anything like that. In fact, if I replace the new fragment with some other fragment also the black space is still there on top. So it's not about the fragment with which I am replacing it.
Please help.
main_activity.xml
<android.support.design.widget.CoordinatorLayout 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/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.moodoff.AllTabs">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#FFC300"
app:tabIndicatorHeight="5dp"
android:background="#C70039"
app:tabGravity="fill"
/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="0dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
first_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/allmoods"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:orientation="vertical"
android:background="#color/black"
tools:context="com.moodoff.Moods">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/firstRowOfMoods"
android:background="#color/black"
android:layout_weight="1"
android:layout_marginTop="5dp"
>
<!--- SOME BUTTONS --->
</LinearLayout>
</LinearLayout>

How to call a Class(Tabfragment.java) to another Fragment(DeliveryTab.java?

I created a Tabs one for Footer menu and another for just a fragment class inside this i have 3 Tabs.
I want to call Footer menu (Tabfragment.java)in another fragment(DeliveryTab.java).
I search it on google and revise the stackoverflow's question but none are helping me..
Here i post complete code.
activity_deliverytab.xml
<LinearLayout 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=".TabFragment"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs_delivery"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#color/tabMedium" />
<include
layout="#layout/tabfragment"></include>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager_delivery"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white">
</android.support.v4.view.ViewPager>
</LinearLayout>
You should include Fragment in your layout using the fragment tag. Like this:
<LinearLayout 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=".TabFragment"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs_delivery"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#color/tabMedium" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager_delivery"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white">
</android.support.v4.view.ViewPager>
<!-- Since you want it to be in the footer -->
<fragment android:name="xyz.xyz.xyz.TabFragment"
android:id="#+id/tabFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Hi i am not sure but you can try like this
inside DeliveryTab.java
ParentActivity activity = (ParentActivity) getActivity();
(ParentActivity is name of your activity which calls both TabsFragment and DeliveryTab )
Now get TabsFragment from FrameLayout or fragment whatever you set your TabsFragment like
((TabsFragment ) getSupportFragmentManager().findFragmentById(R.id.FragmentContainer))
How to add tag to Fragment see this -https://stackoverflow.com/a/23370128/4741746
Now you have TabsFragment now get ViewPager
mViewPager.setCurrentItem(getPosition);

ViewPager vanishes after getting back to the containing fragment

I have an activity which have a complex structure of Fragments. The Activity have two containers, each for a NavigationDrawerFragment and a Main Content Fragment(HomeTabFragment). The Main Content Fragment has TabLayout+ViewPager structure containing two child Fragments(Search and News). This has been working well, untill I need to replace Main Content Fragment with another Fragment (Settings). This also worked well, but when I want to get back to the same Main Content Fragment, the ViewPager, along with the child fragments vanishes.
This is structure. HomeTabFragment is replaced by SettingsFragment via a button (In LeftDrawerFragment) and SettingsFragment is again replaced by HomeTabFragment via a button (In LeftDrawerFragment or a hardware back key)
HomeActivity
|-LeftDrawerFragment
|-HomeTabFragment
| |-ViewPager
| |-HomeSearchFragment
| |-HomeNewsFragment
|-SettingsFragment
Here's the HomeActivity layout -
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!--<include layout="#layout/content_home"/>-->
<android.support.v4.widget.DrawerLayout android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Toolbar-->
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="center_horizontal"
android:background="?attr/colorPrimary"
android:gravity="center_horizontal"
app:layout_scrollFlags="enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:subtitle="Your Medi-buddy"
app:title="#string/app_name">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#null"
android:onClick="onHomeMenuClick"
android:padding="5dp"
android:src="#drawable/ic_menu_white" />
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/app_name"
android:textAppearance="#android:style/TextAppearance.Holo.Large" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<!-- The main content view -->
<FrameLayout
android:id="#+id/tab_frag_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
<!-- The navigation drawer -->
<FrameLayout
android:id="#+id/left_drawer_container"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111" />
</android.support.v4.widget.DrawerLayout>
</android.support.design.widget.CoordinatorLayout>
Following is the layout of my HomeTabFragment
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="#android:color/white"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabSelectedTextColor="#color/colorPrimaryDark"
app:tabTextColor="#color/colorPrimary" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_search_white" />
</android.support.design.widget.CoordinatorLayout>
This is how I am changing back and forth between HomeTabFragment and SettingsFragment
public void onLeftDrawerSettingsClick(View view) {
mDrawerLayout.closeDrawer(Gravity.LEFT);
getSupportFragmentManager().beginTransaction().replace(R.id.tab_frag_container, mApp.getFragmentController().getSettingsFragment()).addToBackStack("Drawer").commit();
}
public void onLeftDrawerHomeClick(View view) {
mDrawerLayout.closeDrawer(Gravity.LEFT);
getSupportFragmentManager().beginTransaction().replace(R.id.tab_frag_container, mApp.getFragmentController().getHomeTabFragment()).commit();
}
I am unable to understand why the ViewPager is getting affected by the replace transaction. I found out that it has something to do with not allowing Child fragments in API Level 15 or lower, however this has been fixed in the latest support library and I don't think it can be an issue.
Is there any way I can replace the HomeTabFragment with SettingsFragment and vice-versa, without affecting the other functionalities? Or is it something I am doing wrong?
A quick solution was to not create the complete view of the fragment when it loads the second time. For that I put following code in the onCreateView() of HomeTabFragment
if (mParent != null)
return mParent;
// Inflate the layout for this fragment
mParent = inflater.inflate(R.layout.fragment_home_tab, container, false);
Though the solution works, but I am still unable to explain why is it happening? Posting it as an answer, in case someone is looking for a solution. Please provide a better solution with explanation, if you can.

How to use fragments of ViewPager?

I have one MainActivity and ViewPagerAdapter and 3 Tab fragments which I am displaying in my MainActivity with ViewPager in it.(Im using navigation drawer also but its ok.)
As a beginner in android fragments I do not understand how to send data from MainActivity to Tab1,Tab2,Tab3 of ViewPager.
I tried to use this Send data from activity to fragment in android method to send data from MainActivity to Tab1 but application crashes with NullPointerException.
So how can I use fragments such that I can send data from MainActivity to Tab1 (Which is fragment.) and setText and Image in it and update that fragment in Viewpager?
MainActivity.xml
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.thewelp.materialtoolbartest1.MainActivity">
<include
android:id="#+id/app_bar"
layout="#layout/app_bar">
</include>
<org.technoarena.tabs.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:layout_below="#+id/app_bar"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_below="#+id/tabs"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
>
</android.support.v4.view.ViewPager>
</RelativeLayout>
<fragment
android:layout_width="#dimen/drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:id="#+id/fragment_drawer"
app:layout="#layout/fragment_navigation_drawer"
android:name="org.technoarena.technoarena2015.NavigationDrawer"
tools:layout="#layout/fragment_navigation_drawer">
</fragment>
</android.support.v4.widget.DrawerLayout>
Tab1.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="You Are In Tab 1"
android:id="#+id/textView"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
You can have a List for data and pass the data to viewpager adapter in constructor and in view pager you can pass the data to fragment in getItem() function.

Categories

Resources