AsyncTask is re-executing while switching between fragments - android

I have a MainActivity.class which extends from Activity . I created a tab like structure . on clicking any of the image . new fragment is displayed. My first fragment is Article. it has a AsyncTask associate with it.
when i go to another fragment and comeback to it .asyncTask call again. And the whole listView is recreated . I simply want to disable AsyncTask for calling again and save the previous state of the fragment.
I have addToBackStack(null); while adding fragments.
getFragmentManager().beginTransaction().replace(R.id.container, new Article()).addToBackStack(null).commit();
where Article is a fragment and container is the frameLayout in the mainActivity.xml
I want to show the fragment where i left off. Like we do in Activities by setting LaunchMode+"Single" or something . I am not clearing backStack.
I simply need to switch between Activities like we do in TabActivity. in TabActivity if we want to repeat the AsyncTask we have to specify it in onResume(). otherwise it will not called
Article Fragment
public class Article extends Fragment
{
ListView listView;
Activity context;
ArrayList<HashMap<String,String>> art_list;
ArticleAdapter adapter;
String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View V = inflater.inflate(R.layout.article, container, false);
context = getActivity();
listView = (ListView) V.findViewById(R.id.art_listview);
new ArticleTask(getActivity(), url, listView).execute(url);
return V;
}
}
MainActivity
public class MainActivity extends Activity //implements FragmentDelegate,FragmentManager.OnBackStackChangedListener
{
public LinearLayout Tab1,Tab2,Tab3,Tab4;
public ImageView img1,img2,img3,img4;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.practicing);
init();
}
private void init()
{
Tab1 = (LinearLayout) findViewById(R.id.tab1);
Tab2 = (LinearLayout) findViewById(R.id.tab2);
Tab3 = (LinearLayout) findViewById(R.id.tab3);
Tab4 = (LinearLayout) findViewById(R.id.tab4);
img1 = (ImageView)findViewById(R.id.tab_img1);
img2 = (ImageView)findViewById(R.id.tab_img2);
img3 = (ImageView)findViewById(R.id.tab_img3);
img4 = (ImageView)findViewById(R.id.tab_img4);
getFragmentManager().beginTransaction().replace(R.id.container, new Article()).addToBackStack(null).commit();
}
public void selectFrag(View view) {
Fragment fr = null;
if (view == findViewById(R.id.tab1))
{
img1.setBackgroundResource(R.drawable.articles_on);
img2.setBackgroundResource(R.drawable.forum_off);
img3.setBackgroundResource(R.drawable.video_off);
img4.setBackgroundResource(R.drawable.profile_off);
fr = new Article();
}
else if(view == findViewById(R.id.tab2))
{
img1.setBackgroundResource(R.drawable.articles_off);
img2.setBackgroundResource(R.drawable.forum_on);
img3.setBackgroundResource(R.drawable.video_off);
img4.setBackgroundResource(R.drawable.profile_off);
fr = new Forum();
}
else if(view == findViewById(R.id.tab3))
{
img1.setBackgroundResource(R.drawable.articles_off);
img2.setBackgroundResource(R.drawable.forum_off);
img3.setBackgroundResource(R.drawable.video_on);
img4.setBackgroundResource(R.drawable.profile_off);
fr = new Medias();
}
else if(view == findViewById(R.id.tab4))
{
img1.setBackgroundResource(R.drawable.articles_off);
img2.setBackgroundResource(R.drawable.forum_off);
img3.setBackgroundResource(R.drawable.video_off);
img4.setBackgroundResource(R.drawable.profile_on);
fr = new Profile();
}
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.container, fr);
fragmentTransaction.addToBackStack(null);//MainActivity.TAG);//.addToBackStack(null);
fragmentTransaction.commit();
}
}
and practicing.xml is
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottom" />
<LinearLayout
android:id="#+id/bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/tab1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:onClick="selectFrag"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/tab_img1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/articles_on"
android:padding="10dp"
android:scaleType="center" />
</LinearLayout>
<LinearLayout
android:id="#+id/tab2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:onClick="selectFrag"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/tab_img2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/forum_off"
android:padding="10dp"
android:scaleType="center" />
</LinearLayout>
<LinearLayout
android:id="#+id/tab3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:onClick="selectFrag"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/tab_img3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/video_off"
android:padding="10dp"
android:scaleType="fitXY" />
</LinearLayout>
<LinearLayout
android:id="#+id/tab4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:onClick="selectFrag"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/tab_img4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/profile_off"
android:padding="10dp"
android:scaleType="fitXY" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

Try adding your fragment instead of replacing.

What addToBackStack() does is: it adds the fragment transaction to its stack, so it knows that when you press back, it should show your first fragment. So t does exactly that, and shows your first fragment again and the fragment's onCreatView() is called again. Here in your onCreateView, all initialization occurs and the AsyncTask is called. This is why it happens everytime you change between fragments.
The solution I implemented for this problem is:
1) Keep view of fragment as a class variable.
2) Perform all actions in onCreateView() only if the view is null.
So you should change:
public class Article extends Fragment
{
ListView listView;
Activity context;
ArrayList<HashMap<String,String>> art_list;
ArticleAdapter adapter;
String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View V = inflater.inflate(R.layout.article, container, false);
context = getActivity();
listView = (ListView) V.findViewById(R.id.art_listview);
new ArticleTask(getActivity(), url, listView).execute(url);
return V;
}
}
to:
public class Article extends Fragment
{
ListView listView;
Activity context;
ArrayList<HashMap<String,String>> art_list;
ArticleAdapter adapter;
String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";
View V; //SET THE FRAGMENTS VIEW AS A CLASS VARIABLE HERE
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{ //CHECK IF FRAGMENT IS INSTANTIATED BEFORE. IF IT IS NOT, CREATE NEW VIEW
if(V == null){
V = inflater.inflate(R.layout.article, container, false);
context = getActivity();
listView = (ListView) V.findViewById(R.id.art_listview);
new ArticleTask(getActivity(), url, listView).execute(url);
}
else{ //IF ALREADY INSTANTIATED USE SAME OLD V
((ViewGroup)V.getParent()).removeView(V);
}
return V;
}
}
Here, we move View V outside and make it a class variable. So if it is the first time the fragment is called, it is null and the initialization occurs, otherwise it goes to else black. Else block is required because onCreateView() adds whatever it returns as a child of the view's parent, so since V is already there, we remove it and onCreateView automatically adds it again.

Related

Fragment inside ViewPager inside ViewGroup

Problem
As shown in the figure below, I have two tabs called "température" which are created in the same way (see mainFragment). In this two tabs, I have a viewpager to get previous graphics ( 05 august, 04 august,...).
The first tab works well but in the second, nothing appears. When debugging, I can see that the fragment is created in both cases. It's only on the second tab where the problem is. Even more, I can see the viewpager working when sliding to the left or right end.
I'm seeking since hours now and I don't understand where the problem is. Why the fragments don't appear ?
I'm using android.support.v13.app.FragmentStatePagerAdapter for the adapter.
Here is a short movie to show the problem :
https://www.dropbox.com/s/vf8qlrd75mdwijp/device-2017-08-06-214510.mp4?dl=0
Code
MainFragment
public class MainFragment extends Fragment implements BTListener {
// the different ID for the views.
private final static int ID_TEMPERATURE = 1;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.main,container,false);
final ViewGroup mainContainer = (ViewGroup) rootView.findViewById(R.id.main_container);
createTemperatureTab(mainContainer);
createTemperatureTab(mainContainer);
return rootView;
}
private void createTemperatureTab(ViewGroup mainContainer){
//inflate the view
ViewGroup view = (ViewGroup) LayoutInflater.from(getActivity()).inflate(R.layout.main_list,mainContainer,false);
((TextView)view.findViewById(R.id.title_main_list)).setText("Température");
((TextView)view.findViewById(R.id.information_main_list)).setText("°C");
final ExpandableLayout expandableLayout = (ExpandableLayout) view.findViewById(R.id.expandable_layout);
CustomPager viewPager = (CustomPager) view.findViewById(R.id.viewpager);
LinearGraphAdapter linearGraphAdapter = new LinearGraphAdapter(getChildFragmentManager());
viewPager.setAdapter(linearGraphAdapter);
viewPager.setCurrentItem(linearGraphAdapter.getCount());
expandableLayout.setExpanded(false);
expandableLayout.setDuration(500);
expandableLayout.setInterpolator(new DecelerateInterpolator());
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(expandableLayout.isExpanded()) {
expandableLayout.collapse();
}
else {
expandableLayout.expand();
}
}
});
mainContainer.addView(view);
}
}
main_list
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/title_main_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:textSize="20sp" />
<TextView
android:id="#+id/information_main_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="80dp"
android:textSize="20sp" />
</LinearLayout>
<net.cachapa.expandablelayout.ExpandableLayout
android:id="#+id/expandable_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.renaud.aquariumslinding.adapter.CustomPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.example.renaud.aquariumslinding.adapter.CustomPager>
</net.cachapa.expandablelayout.ExpandableLayout>
</LinearLayout>
LineGraphFragment
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.linear_graph_layout,container,false);
lineChart = (LineChart) rootView.findViewById(R.id.linear_graph);
initiateChart(lineChart); // not important for this case
drawChart(lineChart,dayOfYear); // not important for this case
return rootView;
}
linear_graph_layout
<?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="wrap_content">
<TextView
android:id="#+id/linear_graph_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:elevation="4dp"
android:textColor="#fff" />
<com.github.mikephil.charting.charts.LineChart
android:id="#+id/linear_graph"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
LinearGraphAdapter
public class LinearGraphAdapter extends FragmentStatePagerAdapter {
public static int MAXIMUM_COUNT_PAGER = 7;
private int mCurrentPosition = -1;
public LinearGraphAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
#Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
bundle.putInt(Constant.CUSTOM_PAGER_NUMBER,MAXIMUM_COUNT_PAGER-position);
Fragment fragment = new LinearGraphFragment();
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return MAXIMUM_COUNT_PAGER;
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if (position != mCurrentPosition) {
Fragment fragment = (Fragment) object;
CustomPager pager = (CustomPager) container;
if (fragment != null && fragment.getView() != null) {
mCurrentPosition = position;
pager.measureCurrentView(fragment.getView());
}
}
}
}
Ok, after a night of research and reading the API I figured it out. I don't understand everything but it seems the v13 and v4 library have a conflict.
To override it, firstly :
Make sure that you called getChildFragmentManager() instead of getFragmentManager()
Create a different ID for all the different viewpageryou have. Those IDs must have at least 4 digits. Of course, it is better to have those in R.String
Set your ID in every viewpager by calling setID()
If it doesn't work, please clean and rebuild your project.
And finally, the reward :
I hope that it will help.

Switching 2 fragments within one activity - Android

I'm trying to replace one fragment with another following a button click (onClick) event. I'm new to fragments so if I'm going about this the wrong way please let me know.
At run time a frame layout (container) is loaded. A fragment is then added to it dynamically. This works fine. If I add in the setOnClickListener I get a NullPointerException. Here's the Java:
public class WelcomeActivity extends ActionBarActivity {
FrameLayout container;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
//setContentView(R.layout.welcome_fragment);
container = (FrameLayout)findViewById(R.id.mainContainer);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.mainContainer) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
addWelcomeFragment();
}
//NPE at the below line
Button submitUser = (Button) findViewById(R.id.submitUser);
submitUser.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view){
addExpedFragment();
}
});
}
Through researching fragments I'm using static class within the WelcomeActivity class to load the fragments. They are here:
public static class WelcomeFragment extends Fragment {
public static Fragment newInstance(){
Fragment wFrag = new WelcomeFragment();
return wFrag;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.welcome_fragment, null);
return v;
}
}
//-----------------------------------------------------------------------------------------------------//
public static class ExpedFragment extends Fragment {
public static Fragment secondInstance(){
Fragment eFrag = new ExpedFragment();
return eFrag;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.exped_fragment, null);
return v;
}
}
And the methods to invoke these are also with WelcomeActivity here:
private void addWelcomeFragment(){
Fragment welcome = WelcomeFragment.newInstance();
FragmentTransaction fTrans = getSupportFragmentManager().beginTransaction();
fTrans.add(R.id.mainContainer, welcome);
fTrans.addToBackStack(null);
fTrans.commit();
}
private void addExpedFragment(){
Fragment exped = ExpedFragment.secondInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.mainContainer, exped).commit();
}
I have a feeling that the problem is to do with trying to find the button view id "submitUser" from the first fragment. My xmls look like this.
The first empty FrameLayout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="#+id/mainContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</FrameLayout>
</RelativeLayout>
The first fragment loaded in at runtime:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/welcome_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
tools:context=".WelcomeActivity" >
<TextView
android:id="#+id/welcome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/welcome1"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="#+id/userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/welcome"
android:layout_alignRight="#+id/welcome"
android:layout_below="#+id/welcome"
android:layout_marginTop="32dp"
android:ems="10"
android:hint="#string/userHint"
android:inputType="textPersonName" >
<requestFocus />
</EditText>
<Button
android:id="#+id/submitUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/userName"
android:layout_alignRight="#+id/userName"
android:layout_below="#+id/userName"
android:layout_marginTop="16dp"
android:text="#string/Done" />
<FrameLayout
android:id="#+id/mainContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</FrameLayout>
</RelativeLayout>
The second fragment to replace the first with the onClick event:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/exped_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
tools:context=".WelcomeActivity" >
<TextView
android:id="#+id/expedText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/exped"
android:textAppearance="?android:attr/textAppearanceLarge">
</TextView>
<FrameLayout
android:id="#+id/mainContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</FrameLayout>
</RelativeLayout>
IF I forget loading the first fragment at runtime and setContentView(first fragment) there is no NullPointerException but the two fragments overlay each other when the button is pressed rather than replacing.
So my question is, how do I reference the active fragment to properly set the OnClickListener and avoid the NullPointerException?
Button submitUser = (Button) findViewById(R.id.submitUser);
gives the NPE
Problem:
Button submitUser = (Button) findViewById(R.id.submitUser);
The submitUser is located in your WelcomeFragment's layout not in your Activity's layout that is why it is null.
solution:
Instead of initializing it in your activity class you need to initialize it within your Welcome fragment view.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.welcome_fragment, null);
Button submitUser = (Button) v.findViewById(R.id.submitUser);
submitUser.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view){
addExpedFragment();
}
});
return v;
}
EDIT:
private void addExpedFragment(){
Fragment exped = ExpedFragment.secondInstance();
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.mainContainer, exped).commit();
}

Android: Fragment

When frButton is clicked FragmentOne should open and MainActivity should be hidden but Components of MainActivity is still accessible in FragmentOne, which is unwanted.
How to fix it?
code for MainActivity:
public void gofag1(View v) {
// TODO Auto-generated method stub
FragmentOne frag = new FragmentOne();
FragmentManager fm = getFragmentManager(); // import
FragmentTransaction ftr = fm.beginTransaction(); // import
ftr.add(R.id.mainlayout, frag, "keyFrag");
ftr.addToBackStack(null);
ftr.commit();
}
code for FragmentOne:
public class FragmentOne extends Fragment {
public FragmentOne() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_one, container,
false);
return v;
}
}
code for FragmentOne layout... R.layout.fragment_one
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context="com.megavb.le.FragmentOne" >
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/tOnOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="22dp"
android:text="#string/a1" />
<ToggleButton
android:id="#+id/toggleButton1"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:onClick="reedToggleValue"
android:text="ToggleButton"
android:textSize="30sp" />
code for MainActivity layout.... R.id.mainlayout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:onClick="gofag1"
android:text="fOne" />
</RelativeLayout>
Please see the picture for better understanding...
So, you should be using ftr.replace instead of ftr.add
public void gofag1(View v) {
// TODO Auto-generated method stub
FragmentOne frag = new FragmentOne();
FragmentManager fm = getFragmentManager(); // import
FragmentTransaction ftr = fm.beginTransaction(); // import
//Notice the change here
ftr.replace(R.id.mainlayout, frag, "keyFrag");
ftr.addToBackStack(null);
ftr.commit();
}
Hope this helps!
EDIT: Well, without more information I'm going to take another stab at this.
In your mainlayout.xml you need to define a Fragment Container a simple method of doing this would be to use a layout file like the one that follows as a base for your Activity.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container">
</FrameLayout>
after defining this new fragment container you can programmatically add fragments to it by referencing it's ID.
The next step is to move your original MainActivty code into a new fragment!
This is the code for fragment_main
<?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">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/button"
android:onClick="gofag1"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Here we create a new layout that simply contains a button.
Next we create the actual fragment
public class FragmentMain extends Fragment {
public FragmentMain() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_main, container,
false);
}
From here we can change our Main activity OnCreate code to
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlayout);
FragmentMain frag = new FragmentMain();
FragmentManager fm = getFragmentManager(); // import
FragmentTransaction ftr = fm.beginTransaction(); // import
ftr.add(R.id.fragment_container, frag, "keyFrag");
ftr.addToBackStack(null);
ftr.commit();
}

Custom Adapter within a Nested Fragment

I have a ViewPager which holds multiple base fragments, each base fragment have four more nested fragments and each nested fragment is a combination of 5 imageViews and textView.
(This is what I intended to do)
I have created a sample application but I am not able to implement that properly. I cannot see any view in the nested fragment or the base fragment.
Here's the code for the sample application
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<fragment android:name="com.example.nestedfragments.BaseFragment"
android:id="#+id/left_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity.java
package com.example.nestedfragments;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
base_fragment.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"
android:gravity="center">
<Button
android:id="#+id/button1"
android:text="Launch Nested Fragment"
android:gravity="center"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingBottom="10dp"/>
</RelativeLayout>
BaseFragment.java
public class BaseFragment extends Fragment {
Button doNestingButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// set the view
View root = inflater.inflate(R.layout.base_fragment, container, false);
doNestingButton = (Button) root.findViewById(R.id.button1);
doNestingButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment videoFragment = new NestedFragment();
// we get the 'childFragmentManager' for our transaction
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
// make the back button return to the main screen
// and supply the tag 'left' to the backstack
transaction.addToBackStack("left");
// add our new nested fragment
transaction.add(getId(), videoFragment, "left");
// commit the transaction
transaction.commit();
}
});
return root;
}
}
nested_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="154dp"
android:layout_height="154dp"
android:id="#+id/imageView" android:layout_gravity="left|center_vertical"
android:src="#drawable/ic_splash"/>
</LinearLayout>
NestedFragment.java
public class NestedFragment extends Fragment {
public NestedFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.nested_fragment, container, false);
ImageView doNestingButton = (ImageView) root.findViewById(R.id.imageView);
return root;
}
Once again this is a sample application, please guide me.
From your above code, you have not used the fragment container layout such as FrameLayout in base_fragment.xml .So add the frame layout for nested fragment inbase_fragment.xml

Navigate among fragments within one activity

I would like to use one Activity which holds several fragments and navigate among the fragments. For example, in the activity, there is a list view which is a fragment, when user select one item from the list, the view will navigate to another fragment, How could this be implemented?
I know there is a nice tutorial on the developer site, but it handles the tablet screen in which two pane layout with one list fragment and one detailed fragment showing in one screen. I only want to navigate among fragments without show two fragments in one screen.
Are there tutorials can teach me how to do it?
In the nutshell the answer to your question is to notify your host activity and then have your host activity replace your current fragment container using FragmentManager.
One of the approach is to make an interface in your first fragment, have your host activity register/listen (implement) to this interface and then have your FragmentManager to replace the container content with the second fragment on listener callback.
I'm not sure about tutorial but here is my snippet:
First Fragment
public class First extends Fragment{
private static onMySignalListener listener;
//call this function from whatever you like i.e button onClickListener
public void switchWindow() {
if(listener != null){
listener.onMySignal();
}
}
public interface onMySignalListener {
//customize this to your liking
//plain without argument
void onMySignal();
//with argument
void onMySignalWithNum(int mNum);
}
public static void setOnMySignalListener(onMySignalListener listener) {
First.listener = listener;
}}
Host Activity
public class HostActivity extends FragmentActivity implements onMySignalListener{
private final String ADD_TAG_IF_NECESSARY = "mTag";
#Override
public void onCreate(Bundle ssi) {
setContentLayout(R.layout.main);
FirstFragment.setOnMySignalListener(this);
}
#Override
public void onMySignal() {
//if you're using compat library
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
//initialize your second fragment
sfragment = SecondFragment.newInstance(null);
//replace your current container being most of the time as FrameLayout
transaction.replace(R.id.container, fragment, ADD_TAG_IF_NECESSARY);
transaction.commit();
}
#Override
public void onMySignalWithNum(int mNum) {
//you can do the same like the above probably with your own customization
}}
This is only an example on how you'd implement interface, kindly tidy it up by yourself. And please be noted though that this is not effective if you have a lot of fragment wanting to notify your host activity about something. doing so will lead you to implement various listener to your host activity.
I think this will be useful for you. It is example of two fragments in one screen works independently.
MainActivity :
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Fragment newFragment = new Test();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.UprLayout, newFragment);
// transaction.addToBackStack(null);
transaction.commit();
Fragment newFragment2 = new TestRight();
FragmentTransaction transaction2 = getFragmentManager().beginTransaction();
transaction2.add(R.id.dwnLayout, newFragment2);
// transaction.addToBackStack(null);
transaction2.commit();
}
}
main_activity.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|center_horizontal"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/UprLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical" />
<LinearLayout
android:id="#+id/dwnLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical" />
</LinearLayout>
Fragment Test :
public class Test extends Fragment {
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.test, container, false);
return view;
}
}
Fragment TestRight :
public class TestRight extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.test_right, container, false);
return view;
}
#Override
public void onStart() {
super.onStart();
Button button = (Button)getActivity().findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Fragment newFragment = new Right2nd();
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
transaction.replace(R.id.dwnLayout, newFragment);
transaction.addToBackStack("aa");
transaction.commit();
//transaction.add(R.id.frag, newFragment).commit();
}
});
}
}
test.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="test"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="50sp" />
</LinearLayout>
test_right.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test right"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="45sp" />
</LinearLayout>
Fragment Right2nd :
public class Right2nd extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View vw = inflater.inflate(R.layout.right_2nd, container, false);
return vw;
}
}
right_2nd.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Right 2nd"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="50sp" />
</LinearLayout>
I know this is quite old question but this is currently implemented in Navigation Component https://developer.android.com/guide/navigation/
Here is a very nice tutorial about it. MULTIPLE FRAGMENTS STACK IN EACH VIEWPAGER TAB
I think ChildFragment
would do the job for you. Ignore the Tab ViewPager. It's performing the same thing in multiple tabs. Hope this helps a bit.

Categories

Resources