I am not sure how to ask this. I tried in here, but I guess I was not clear enough. So, I thought I just write a small App to describe the situation. Please note, the App uses Googles SlidingTabLayout.
Long story short, at any point if I click Button1, the FrameLayout should contain Fragment1, removing Fragment2 (if exists). Therefore, FragmentViewPager should also be destroyed as Fragment2. However, even then if I change the orientation of my device, I get the Toast which is defined in the onCreate() method of FragmentViewPager.
Why FragmentViewPager's onCreate is called even if Fragment2 is paused/destroyed? Is it possible that, the Toast of FragmentViewPager will not be shown when Fragment2 is destroyed?
MainActivity:
package com.abdfahim.testproject;
import android.app.Fragment;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(onClickListener);
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(onClickListener);
}
private View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment;
switch (v.getId()){
case R.id.button1:
fragment = new Fragment1();
break;
case R.id.button2:
fragment = new Fragment2();
break;
default:
return;
}
getFragmentManager().beginTransaction().replace(R.id.frame_container, fragment, v.getTag().toString()).addToBackStack(null).commit();
}
};
}
Fragment1
package com.abdfahim.testproject;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment1 extends Fragment {
public Fragment1(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment1,container,false);
setHasOptionsMenu(true);
return rootView;
}
}
Fragment2
package com.abdfahim.testproject;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Fragment2 extends Fragment {
public Fragment2(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment2,container,false);
setHasOptionsMenu(true);
CharSequence titles[]= {"Tab A", "Tab B"};
// Creating The ViewPagerAdapter
ViewPagerAdapter adapter = new ViewPagerAdapter(getActivity().getFragmentManager(), titles, titles.length);
ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager);
pager.setAdapter(adapter);
// Assigning the Sliding Tab Layout View
SlidingTabLayout tabs = (SlidingTabLayout) rootView.findViewById(R.id.tabs);
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
return rootView;
}
static class ViewPagerAdapter extends FragmentStatePagerAdapter {
private CharSequence titles[];
private int numbOfTabs;
public ViewPagerAdapter(FragmentManager fm, CharSequence mTitles[], int mNumbOfTabs) {
super(fm);
this.titles = mTitles;
this.numbOfTabs = mNumbOfTabs;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
bundle.putString("displayText", "Inside Fragment 2, " + titles[position]);
FragmentViewPager fragment = new FragmentViewPager();
fragment.setArguments(bundle);
return fragment;
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return numbOfTabs;
}
}
}
FragmentViewPager
package com.abdfahim.testproject;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
public class FragmentViewPager extends Fragment {
public FragmentViewPager(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_view_pager,container,false);
setHasOptionsMenu(true);
Bundle bundle = this.getArguments();
TextView textView = (TextView) rootView.findViewById(R.id.tabText);
textView.setText(bundle.getString("displayText"));
return rootView;
}
#Override
public void onStart() {
super.onStart();
Toast.makeText(getActivity(), "This is View Pager Fragment", Toast.LENGTH_SHORT).show();
}
}
when you use fragment inside another fragment. you use getChildFragmentManager() instead of getFragmentManager. You can call setAdapter() for the ViewPager from onCreateView() or onActivityCreated()
for more detail. have a look at it
Why it is not possible to use ViewPager within a Fragment? It actually is
For every click your OnClickListener creates the instance of Fragment2 and does not create Fragment1. That is due to the misuse of View#getTag.
In MainActivity#onCreate, change the if in the definition of onClickListener to this(using this answer):
switch (v.getId()){
case R.id.button1:
fragment = new Fragment1();
break;
case R.id.button2:
fragment = new Fragment2();
break;
default:
return;
}
In your code, in the if that is checked upon a click (for example after clicking button1) android asks v (the clicked View) for its tag - but as none was set using View#setTag - it returns null which is of course not equal to the String object created for "button1", thus the if reverts to the else every time.
Related
i followed this article http://www.truiton.com/2015/06/android-tabs-example-fragments-viewpager/ to implement swipe view and it work nice. So now i want to add button on Tab1 and when clicked has to send data to Tab2.
I know there is the issue of using interface but honestly i don't know how to add it on these codes and work provide am completely new to the android.
so far i have tried my best on these links Communication between SlidingTabLayout tabs, How to pass data from one swipe tab to another? and How can I communicate/pass data through different Fragments with Swipe Tab? but i fail.
Any one help please to make it work on every stage , i mean from Tab1 ->Mainactivity->Tab2
thanks alot
Here are the codes after i edit the question
Fragment1
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class TabFragment1 extends Fragment implements AdapterView.OnItemSelectedListener{
Button send;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v= inflater.inflate(R.layout.tab_fragment_1, container, false);
send=(Button)v.findViewById(R.id.send);
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// value to be sent to the TabFragment2 on button click
String value=" My Data";
}
});
return v;
}
}
Fragment2
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class TabFragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.tab_fragment_2, container, false);
//Display value from TabFragment1
textview.setText(value);
}
}
Interface class
public Interface FragmentCommunication
{
public void printMessage(String message);
}
MainActivity
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity implements FragmentCommunication{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public void printMessage(String message)
{
Toast.makeText(MainActivity.this,message,Toast.LENGTH_LONG).show();
}
}
Adapter Class
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
public class PagerAdapter extends FragmentStatePagerAdapter {
int mNumOfTabs;
public PagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabFragment1 tab1 = new TabFragment1();
return tab1;
case 1:
TabFragment2 tab2 = new TabFragment2();
return tab2;
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
so after posting more code I'm answering:
Implement some FragmentCommunication for both your Fragments:
//public class TabFragment1 extends Fragment implements FragmentCommunication{
public class TabFragment2 extends Fragment implements FragmentCommunication{
//public static final String TAG="TabFragment1";
public static final String TAG="TabFragment2";
...
#Override
public void onActivityCreated (Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
if(getActivity() instanceOf MainActivity)
((MainActivity) getActivity()).registerFragmentCommunication(
TAG, this);
}
#Override
public void printMessage(String message){
Toast.makeText(getActivity(), TAG+" says: "+message,
Toast.LENGTH_SHORT).show();
}
}
note this line inside onActivityCreated:
((MainActivity) getActivity()).registerFragmentCommunication(TAG, this);
this means implemented FragmentCommunication, TAG will be unique key/name of Fragment and whole method is registration of your interface in Activity. so now you have to add registerFragmentCommunication method to your MainActivity and keep reference to passed interfaces, e.g. in HashMap:
HashMap<String, FragmentCommunication> fragmentCommunications =
new HashMap<String, FragmentCommunication>();
...
public void registerFragmentCommunication(String key, FragmentCommunication fc){
fragmentCommunications.put(key, fc);
}
so now you can access each FragmentCommunication of both fragments from your MainActivity, e.g by using method like this:
public void callFragmentCommunication(String key, String msg){
if(fragmentCommunications.get(key)!=null)
fragmentCommunications.get(key).printMessage();
}
callFragmentCommunication(TabFragment1.TAG, "hi!");
callFragmentCommunication(TabFragment2.TAG, "hi!");
method is public, so Fragments can call it simply like this:
//inside TabFragment1
if(isAdded() && getActivity()!=null &&
getActivity() instanceOf MainActivity &&
!getActivity().isFinishing())
((MainActivity) getActivity()).callFragmentCommunication(
TabFragment2.TAG, "hi!");
this will show Toast with text: "TabFragment2 says: hi!", which was called inside TabFragment1. now you may pass another kind of data as well :)
there is much more methods like communicating through FragmentStatePagerAdapter like here, passing Bundle arguments where fragments are initialized, additional feedback interfaces (e.g. returning true/false when message was passed) etc. Above is just very simplified way, good luck with improving it! :)
When App starts it's showing first fragment and preparing second one, when I slide to second it's preparing third... When I slide back from second to third everythink is fine but when slide 1 -> 2 -> 3 -> 2 -> 1 the first one content has been reseted... What could be a problem here?
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v7.app.AppCompatActivity;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends AppCompatActivity{
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
FoldersFragment foldersFragment = new FoldersFragment();
NowPlayingFragment nowPlayingFragment = new NowPlayingFragment();
EqFragment eqFragment = new EqFragment();
public ViewPager getMViewPager() {
return mViewPager;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
foldersFragment.setNowPlayingFragment(nowPlayingFragment);
nowPlayingFragment.setFoldersFragment(foldersFragment);
eqFragment.setMediaPlayer(nowPlayingFragment.mp);
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
System.out.println("0");
return foldersFragment;
case 1:
System.out.println("1");
return nowPlayingFragment;
case 2:
System.out.println("2");
return eqFragment;
}
return null;
}
#Override
public int getCount() {
return 3;
}
}
}
The default offscreen limit is 1 so each time you go to the next fragment it will check if there is fragment that is already been offscreen and will be restarted when you go back to it:
if you are currently at page 3
1 -> |offset| 2 -> (3) -> 4 -> |offset| 5
so page 1 and page 5 will be restarted if it is before or after the current page + the offset.
To increase the offset you can call:
mViewPager.setOffscreenPageLimit(4)
I'm dealing with and Android app using an activity and 3 fragments with a ViewPager and a FragmentPagerAdapter.
The app is working correctly but I still cannot retrieve the reference of a Fragment within the Activity.
The methods findFragmentById and findFragmentbyTag always return null.
Here's my code:
FragmentPagerAdapter:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class ViewPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
switch (position) {
// Open FragmentTab1.java
case 0:
FragmentTab1 fragmenttab1 = new FragmentTab1();
return fragmenttab1;
// Open FragmentTab2.java
case 1:
FragmentTab2 fragmenttab2 = new FragmentTab2();
return fragmenttab2;
// Open FragmentTab3.java
case 2:
FragmentTab3 fragmenttab3 = new FragmentTab3();
return fragmenttab3;
}
return null;
}
}
Fragment implementation:
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.support.v4.app.Fragment;
public class FragmentTab1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Get the view from fragmenttab1.xml
View view = inflater.inflate(R.layout.fragmenttab1, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
}
And finally my activity:
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the view from activity_main.xml
setContentView(R.layout.activity_main);
// Locate the viewpager in activity_main.xml
viewPager = (ViewPager) findViewById(R.id.pager);
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
// Set the ViewPagerAdapter into ViewPager
viewPager.setAdapter(viewPagerAdapter);
}
#Override
protected void onStart()
{
super.onStart();
InitializeVariables();
viewPager.setCurrentItem(1);
Fragment fragment = (Fragment)getSupportFragmentManager().findFragmentByTag(makeFragmentName(viewPager.getId(), 0));
}
Here is the code of MainActivity which I have written.
I am loading the list of fragment in the first screen. When the user taps on any of the list items, the planet name will be shown to the user in the detail fragment which I have defined in a separate class.
I am adding the transaction of "Fragment Planet List" -> "Fragment Planet Detail" to back stack. So what I expect is when I press the back button from the fragment of planet detail, it should load planet list in the phone. But it is not happening this way.
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.FrameLayout;
import com.meditab.fragments.fragment.FragmentPlanetDetail;
import com.meditab.fragments.fragment.FragmentPlanetList;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends ActionBarActivity implements Callback {
private FrameLayout frmPlanetList;
private FrameLayout frmPlanetDetail;
private boolean isPhone;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frmPlanetList = (FrameLayout) findViewById(R.id.frmPlanetList);
frmPlanetDetail = (FrameLayout) findViewById(R.id.frmPlanetDetail);
if (null != frmPlanetDetail) {
isPhone = false;
} else {
isPhone = true;
}
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frmPlanetList, new FragmentPlanetList());
fragmentTransaction.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onListItemClicked(int intPosition) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
List<String> lstPlanetArray = getPlanetArray();
String strPlanetName = lstPlanetArray.get(intPosition);
FragmentPlanetDetail fragmentPlanetDetail = FragmentPlanetDetail.newInstance(strPlanetName);
if (isPhone) {
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.frmPlanetList, fragmentPlanetDetail);
} else {
fragmentTransaction.replace(R.id.frmPlanetDetail, fragmentPlanetDetail);
}
fragmentTransaction.commit();
}
private List<String> getPlanetArray() {
List<String> lstPlanets = new ArrayList<>(10);
lstPlanets.add("Mercury");
lstPlanets.add("Venus");
lstPlanets.add("Earth");
lstPlanets.add("Mars");
lstPlanets.add("Jupiter");
lstPlanets.add("Saturn");
lstPlanets.add("Uranus");
lstPlanets.add("Neptune");
lstPlanets.add("Saturn");
return lstPlanets;
}
}
However if I override the backPress method and pop the back stack programatically, it works just fine.
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() != 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
Do I need to override the onBackPressed() method this way if I want to achieve this behavour?
It is not documented that you need to override this method in this link.Android Back Press Fragment Documentation
Fragment Planet Detail Class
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.meditab.fragments.R;
/**
* Created by BHARGAV on 25-Dec-14.
*/
public class FragmentPlanetDetail extends Fragment {
private String strPlanetName;
public FragmentPlanetDetail() {
}
public static FragmentPlanetDetail newInstance(String strPlanetName) {
FragmentPlanetDetail fragmentPlanetDetail = new FragmentPlanetDetail();
Bundle bundle = new Bundle();
bundle.putString("Planet_Name", strPlanetName);
fragmentPlanetDetail.setArguments(bundle);
return fragmentPlanetDetail;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
if (null != bundle) {
strPlanetName = bundle.getString("Planet_Name");
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.planet_name, container, false);
TextView txtPlanetName = (TextView) rootView.findViewById(R.id.txtPlanetName);
txtPlanetName.setText(strPlanetName);
return rootView;
}
}
Fragment Planet List Class:
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.meditab.fragments.Callback;
import com.meditab.fragments.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by BHARGAV on 25-Dec-14.
*/
public class FragmentPlanetList extends Fragment {
private ListView listView;
private ArrayAdapter<String> stringArrayAdapter;
private Callback callback;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.listview, container, false);
listView = (ListView) rootView.findViewById(R.id.listView);
stringArrayAdapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_list_item_1, getPlanetArray());
listView.setAdapter(stringArrayAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
callback.onListItemClicked(position);
}
});
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback = (Callback) activity;
}
private List<String> getPlanetArray() {
List<String> lstPlanets = new ArrayList<>(5);
lstPlanets.add("Mercury");
lstPlanets.add("Venus");
lstPlanets.add("Earth");
lstPlanets.add("Mars");
lstPlanets.add("Jupiter");
lstPlanets.add("Saturn");
lstPlanets.add("Uranus");
lstPlanets.add("Neptune");
lstPlanets.add("Saturn");
return lstPlanets;
}
}
Callback Interface:
/**
* Created by BHARGAV on 26-Dec-14.
*/
public interface Callback {
public void onListItemClicked(int intPosition);
}
Thanks. Please let me know if any additional detail or code is needed.
Ok. So the reason why it is not working is the conflict of ActionBarActivty and Activity class differences.
And the differnce between getSupportFragmentManager() and getFragmentManager() methods of FragmentTransaction.
ActionBarActivity:
I was using ActionBarActivity which is android.support.v7.app.ActionBarActivity. This means I was using v7 compat library
FragmentManager:
Fragment Manager were not from the compat library. It was directly
import android.app.FragmentManager;
import android.app.FragmentTransaction;
as you can see in the MainActivity class.
Fragment:
android.app.Fragment; is the class which is imported in the separate fragment classes.
So once I changed from ActionBarActivity to Activity class, things were working fine.
The same holds true when I changed the FragmentManager,FragmentTransaction and Fragment classes to support library classes.
So after any of the modification, things started working normally.
Thanks.
Of course you don't need to override the onBackPressed() method. It's just a hack.
Your this condition is messing it up.
if (isPhone) {
fragmentTransaction.addToBackStack(null);
why don't you use this statement without condition once to see if it works. You can keep rest as it is. Just move this statement outside of the if condition.
Wierd, but I think
addToBackStack(null)
is the problem
Try replcing it with
addToBackStack("planetDetail");
You are using actionbar activity which extends fragment activity. Now, to have perfect behaviour, you need support fragments to work with actionbar activity.
Here you are using actionbar activity with normal fragments (not support v4 fragments) and that's what is causing the issue. So to have perfect behaviour, change your fragments to support fragments and it should work fine.
Let me know if that doesn't work.
Well I was having the same problem with you. What worked for me and I think its the solution for you too is to change the :
1.fragment with the fragment from the support library :
import android.support.v4.app.Fragment;
and
getFragmentManager() with the getSupportFragmentManager() :
so I have tested this code on a newer android and when I test it on an older version and click on a button to take me to a page with SwipeView and tabs, I get an error:
The application has stopped unexpectedly. Please try again.
I have set the minimumSDK level in the android manifest to 7. I'm not sure why it won't work on the older android phone.
Here's my code for the SwipeView class:
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import android.app.ActionBar;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.NavUtils;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class SwipeMode extends SherlockFragmentActivity{
DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.swipemode);
mDemoCollectionPagerAdapter = new DemoCollectionPagerAdapter(getSupportFragmentManager());
// Set up action bar.
final ActionBar actionBar = getActionBar();
// Specify that the Home button should show an "Up" caret, indicating that touching the
// button will take the user one step up in the application's hierarchy.
actionBar.setDisplayHomeAsUpEnabled(true);
// Set up the ViewPager, attaching the adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mDemoCollectionPagerAdapter);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This is called when the Home (Up) button is pressed in the action bar.
// Create a simple intent that starts the hierarchical parent activity and
// use NavUtils in the Support Package to ensure proper handling of Up.
Intent upIntent = new Intent(this, MainActivity.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
// This activity is not part of the application's task, so create a new task
// with a synthesized back stack.
TaskStackBuilder.from(this)
// If there are ancestor activities, they should be added here.
.addNextIntent(upIntent)
.startActivities();
finish();
} else {
// This activity is part of the application's task, so simply
// navigate up to the hierarchical parent activity.
NavUtils.navigateUpTo(this, upIntent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
public static class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {
public DemoCollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
//unimplemented methods were automatically added
#Override
public Fragment getItem(int i) {
// TODO Auto-generated method stub
Fragment fragment = new DemoObjectFragment();
Bundle args = new Bundle();
args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1); // Our object is just an integer :-P
fragment.setArguments(args);
return fragment;
}
//number of pages
#Override
public int getCount() {
// TODO Auto-generated method stub
return 5;
}
#Override
public CharSequence getPageTitle(int position) {
return "OBJECT " + (position + 1);
}
}
public static class DemoObjectFragment extends Fragment {
public static final String ARG_OBJECT = "object";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.text_object, container, false);
Bundle args = getArguments();
//This part sets the integer to string text on the layouts
((TextView) rootView.findViewById(android.R.id.text1)).setText(
Integer.toString(args.getInt(ARG_OBJECT)));
return rootView;
}
}
}
Use getSupportActionBar() instead of getActionBar().
getActionBar() is supported from API lvl 11+