Android - How to use the ActionBar to navigate between Fragments - java

New to ActionBar and Fragments but familiar with Android in general.
I have been following a few tutorial. So far I have the following:
3 Fragments that I want to navigate between (each has an overriden onCreateView() and loads a simple view)
A custom TabListener for the ActionBar (I believe the problem is there, see bottom of post for code)
A hosting Activity in which this is all performed
The Activity code:
public class Activity_Home extends Activity
{
ActionBar actionBar;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
actionBar = getActionBar(); // Get reference to ActionBar
// Add some navigation tabs...
// 1. Enable ActionBar navigation tabs
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
// 2. Add the tabs
Tab programTab = actionBar.newTab();
Tab settingsTab = actionBar.newTab();
Tab historyTab = actionBar.newTab();
programTab.setText("Program")
.setTabListener(new TabListener<Fragment_Program>(
this, R.id.fragmentParent, Fragment_Program.class));
settingsTab.setText("Settings")
.setTabListener(new TabListener<Fragment_Settings>(
this, R.id.fragmentParent, Fragment_Settings.class));
historyTab.setText("History")
.setTabListener(new TabListener<Fragment_History>(
this, R.id.fragmentParent, Fragment_History.class));
actionBar.addTab(programTab);
actionBar.addTab(settingsTab);
actionBar.addTab(historyTab);
}
}
My Fragments:
public class Fragment_Program extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_program, null);
}
}
..
public class Fragment_History extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_history, null);
}
}
..
public class Fragment_Settings extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_settings, null);
}
}
Lastly, my TabListener which has been pretty much based on the official Google example. The fragmentContainer (int) is the XML resource ID of the LinearLayout in the Activities layout that is the direct parent of all of these Fragments.
public class TabListener <T extends Fragment> implements ActionBar.TabListener
{
private Fragment fragment;
private int fragmentContainer;
private final Activity activity;
private final Class<T> fragmentClass;
/** Constructor used each time a new tab is created.
* #param activity The host Activity, used to instantiate the fragment
* #param tag The identifier tag for the fragment
* #param fragmentClass The fragment's Class, used to instantiate the fragment
*/
public TabListener(Activity activity, int fragmentContainer, Class<T> fragmentClass)
{
this.activity = activity;
this.fragmentContainer = fragmentContainer;
this.fragmentClass = fragmentClass;
}
#Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1)
{
// User selected the already selected tab. Usually do nothing.
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
// Check if the fragment is already intialized
if (fragment == null)
{
// If not, instatiate and add it to the Activity
fragment = Fragment.instantiate(activity, fragmentClass.getName());
ft.add(fragmentContainer, fragment);
}
else
{
ft.attach(fragment);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
if (fragment != null)
{
// Detach the fragment, because another one is being attached
ft.detach(fragment);
}
}
}
So the app loads, the tabs are there, I can select them but they don't seem to be linked to each other and I am not really sure how to proceed.
Any suggestions would be great!
Cheers
BONUS QUESTION: The ActionBar is also below the existing ActionBar.. goal was to replace it, not make another one underneath.. again any suggestions would be great!

Fixed it!
I changed my approach from using the Fragment Container ID (which did make and does still make more sense to me..) with String tags as per this example Good complete Fragment and ActionBar example and the official Google example.

I imagine that you want the tabs to be connected in a way that you can swipe between tabs, in order to accomplish this, you should consider a ViewPager.
Here's the XML by the way:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
Here's some sample code you can use:
public class MyTabActivity extends FragmentActivity implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
//What item on the pager is being displayed
private int mCurPagerItem = 0;
//This will be set to the pageer to handle navigation
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
final ActionBar mActionBar = getActionBar();
mActionBar.setDisplayShowHomeEnabled(false);
mActionBar.setDisplayShowTitleEnabled(false);
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//add the tabs
mActionBar.addTab(mActionBar.newTab().setIcon(R.drawable.your_icon).setTabListener(this));
mActionBar.addTab(mActionBar.newTab().setIcon(R.drawable.your_icon2).setTabListener(this));
mActionBar.addTab(mActionBar.newTab().setIcon(R.drawable.your_icon3).setTabListener(this));
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(this);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Fragment one = new Fragment_Program();
return one ;
case 1:
Fragment two = new Fragment_Settings();
return two ;
case 2:
Fragment three = new Fragment_History();
return three ;
default:
break;
}
return null;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.title_one);
case 1:
return getString(R.string.title_two);
case 2:
return getString(R.string.title_three);
}
return null;
}
}
#Override
public void onPageScrollStateChanged(int arg0) {}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
#Override
public void onPageSelected(int arg0) {
//When a Page is selected, make that the current navigation item
getActionBar().setSelectedNavigationItem(arg0);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
//Back to top maybe?
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
//get the position
final int pos = tab.getPosition();
//Tell the viewpager to scroll to that page
mViewPager.setCurrentItem(pos);
mCurPagerItem = pos;
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
To answer your bonus question, on your Manifest, try adding the following line withing the specified activity tag:
android:uiOptions="splitActionBarWhenNarrow"

Related

Switch tabs inside a Fragment from Drawer Menu

I have a TabLayout in a Fragment. I’m trying to switch tabs using DrawerLayout item. Not sure how to access the TabLayout from the parent Activity. Checked everywhere, to no avail.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize Toolbar and set it as the Action Bar
mToolbar = (Toolbar) findViewById(R.id.mToolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
// Inflate the TabFragment as the first one
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.containerView, new TabFragment()).commit();
// Initialize Drawer Menu
mDrawerLayout = (DrawerLayout) findViewById(R.id.mDrawerLayout);
mNavigationView = (NavigationView) findViewById(R.id.mNavigationView);
headerLayout = mNavigationView.getHeaderView(0);
// Set click events for the Drawer Menu items
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// Close the Drawer Menu when an item is clicked
mDrawerLayout.closeDrawers();
switch (menuItem.getItemId()) {
case R.id.menuLessons:
return true;
case R.id.menuCheatSheet:
return true;
case R.id.menuMyProfile:
startActivity(new Intent(MainActivity.this, MyProfileActivity.class));
overridePendingTransition(R.anim.zoom_in, R.anim.fade_out);
return true;
default:
return true;
}
}
});
}
}
TabFragment.java
public class TabFragment extends Fragment {
public TabLayout mTabLayout;
public ViewPager mViewPager;
public static int int_items = 2;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the Tab Layout and setup View Pager
View x = inflater.inflate(R.layout.layout_tabs, null);
mTabLayout = (TabLayout) x.findViewById(R.id.mTabLayout);
mViewPager = (ViewPager) x.findViewById(R.id.mViewPager);
// Setup Adapter for the View Pager
mViewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
return x;
}
private class MyAdapter extends FragmentPagerAdapter {
MyAdapter(FragmentManager fm) {
super(fm);
}
// Return Fragment with respect to position
#Override
public Fragment getItem(int position) {
switch(position) {
case 0 : return new LessonsFragment();
case 1 : return new CheatSheetFragment();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
// Return title of the tab according to the position
#Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0 :
return "Lessons";
case 1 :
return "Cheat Sheet";
}
return null;
}
}
public void setCurrentTab(int tab_index) {
FragmentTabHost mTabHost = (FragmentTabHost)getActivity().findViewById(android.R.id.tabhost);
mTabHost.setCurrentTab(tab_index);
}
}
To get an instance to a Fragment in an activity, use:
Fragment tabFragment = (TabFragment) getSupportFragmentManager().findFragmentById(R.id.containerView);
Once you have this, you can then call your method:
tabFragment.setCurrentTab(/*tab index*/);
That answers the question, however I would consider using a ViewPager or simply sticking with tapping tabs to move to them instead of doing it view the nav drawer.

Tabs with Fragment life cycle

in my app i have a Tabs with fragment classes. i trying to refresh listView in "fragment a" with the new data i insert.
In "fragment b" i have EditText and Button ,that inserting text to the database.
in "fragment a" i have the ListView with the dataBase rows. when "fragment a" is "OnCreateView" i just put the dataBase on a "ArrayList" and past it to my baseAdapter.
but "onCreateView" not refreshing my new data every time i get into the "fragment a" else i goes to "fragment c" and "onDestroy" call on "fragment a".
so my result it was to call : "setUserVisibleHint" override method, and check if it is visible and refreshing the list.
but i dont think it is the good practice .
what should i do?
Class a
public class ListFragment extends Fragment{
basAdapterCustom adapter;
ListView lv;
ArrayList<Clock> list;
private DbHandler hand;
Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.list_fragment, container, false);
context = getActivity();
Log.d(TAG, "onCreateView");
hand = new DbHandler(context);
list = new ArrayList<Clock>();
lv = (ListView) v.findViewById(R.id.listOfShifts);
adapter = new basAdapterCustom(list, getActivity());
lv.setAdapter(adapter);
refreshList();
return v;
}
//like on "resume":
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
// Make sure that we are currently visible
if (this.isVisible()) {
refreshList();
if (!isVisibleToUser) {
// TODO stop
}
}
}
private void refreshList() {
list = hand.getByWorkName();
adapter = new basAdapterCustom(list,getActivity());
lv.setAdapter(adapter);
}
class b:
public class ClockFragment extends Fragment{
DbHandler hand;
Context context;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.clock, container,false);
context = getActivity();
hand = new DbHandler(context);
return v;
}
// ADD to .Db
public void addToDb(View v){
hand.add(new Clock(0, dateDay));
}
}
class mainActivity:
public class MainActivity extends FragmentActivity implements ActionBar.TabListener, OnPageChangeListener{
public static final String TAG = "myClock";
String[] tabMenu = {"FRAG A","FRAG B","FRAG C"};
private ViewPager viewPager;
private TabPagerAdapter mAdapter;
private ActionBar actionBar;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(MainActivity.TAG, "OnCreate = MainActivity (Pager");
viewPager = (ViewPager) findViewById(R.id.pager );
actionBar = getActionBar();
mAdapter = new TabPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (String tabsNames : tabMenu) {
actionBar.addTab(actionBar.newTab().setText(tabsNames).setTabListener(this));
}
viewPager.setOnPageChangeListener(this);
}
// public void transDialog(){
// Dialog mDialog = new Dialog(this, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
// }
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
}
PagetAdapter.class
public class TabPagerAdapter extends FragmentPagerAdapter {
private static final String TAG = "myClock";
public TabPagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
#Override
public Fragment getItem(int index) {
Log.d(TAG, " CLASS : TabPagerAdapter");
switch (index) {
case 0:
return new ListFragment();
case 1:
return new ClockFragment();
case 2:
return new SettingFragment();
default:
break;
}
Log.d(TAG, " CLASS : TabPagerAdapter = "+index);
return null;
}
#Override
public int getCount() {
return 3;
}
}
Please help me i hope you are understand my problem...
You want to update listView in fragment A, after insert data in fragment b? Then  you have a few solutions to choose:
1. Implement communications between fragments via activity. Then B insert date, it send message to activity, that data need to be updated. Then fragment A started, it's ask activity to need update data. For details on implementing this communication check link.
2. Use some bus library, EventBus for example. Then fragment B insert data, it post 'data changed' event to bus. Fragment A checks on start if this event occurs.
3. Use Loaders which "monitor the source of their data and deliver new results when the content changes."

Android IllegalStateException: Fragment not attached to Activity webview

So I'm new to android app writing, and I am trying to work on a practice app that I can hopefully turn into something later. I had 3 tabs in the actionbar that ran fine before I decided to try to add webview to one of them. Now it crashes with an IllegalStateException. And since I don't know too much about android at the moment, I can't seem to figure out what is wrong.
The main activity:
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
private String[] tabs = { "Web", "Facebook", "Twitter" };
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs)
{
actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override
public void onPageSelected(int position)
{
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
}
#Override
public void onPageScrollStateChanged(int arg0)
{
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft)
{
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
}
The WebFragment with the webview:
public class WebFragment extends Fragment
{
private String url = getString(R.string.website);
//#Override
//public void onActivityCreated(Bundle savedInstanceState)
//{
//super.onActivityCreated(savedInstanceState);
//}
#SuppressLint("SetJavaScriptEnabled")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.web_fragment, container, false);
WebView tolerableWebView = (WebView) getView().findViewById(R.id.webview);
tolerableWebView.getSettings().setJavaScriptEnabled(true);
tolerableWebView.loadUrl(url);
return rootView;
}
}
the TabsPagerAdapter:
public class TabsPagerAdapter extends FragmentPagerAdapter
{
public TabsPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int index)
{
switch (index) {
case 0:
// Top Rated fragment activity
return new WebFragment();
case 1:
// Games fragment activity
return new FacebookFragment();
case 2:
// Movies fragment activity
return new TwitterFragment();
}
return null;
}
#Override
public int getCount()
{
// get item count - equal to number of tabs
return 3;
}
}
The webfragment xml
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</WebView>
The main activity xml:
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Any help would be great! Thanks
Generally you get that error when you try to perform work after the Fragment is no longer attached to the Activity. In the callback that triggers the IllegalStateException add a check for isAdded: http://developer.android.com/reference/android/app/Fragment.html#isAdded()
if(!isAdded()) {
return;
}

View controls remain after listfragment is replaced by nested fragment

I have a tabbed view activity with 3 tabs and one fragment in each tab. Those fragments are managed by a FragmentPageAdapter linked to a viewpager.
Everything works fine until I try to have a 4th fragment (ServiceSpecifNotListFragment) that would be a nested fragment of one of the fragments (ServicesListFragment) managed by the FragmentPageAdapter.
When I try to replace the ServicesListFragment by the ServiceSpecifNotListFragment. I manage to replace only the list element from ServicesListFragment by the ServiceSpecifNotListFragment, the other view controller (a button) from ServicesListFragment remains....
I have been wondering if the problem lies in the fact that the method I use to replace the fragment by its subfragment is transaction.replace(R.id.service_list_fragment, newFragment).commit(); and service_list_fragment is the id of the listfragment main linear layout which contains the listview defined with the id: #id/android:list
The closest Q&A I found to this was this one but as far as I understood I am using the fragment container id correctly.
Here is the code and layout:
Layout of ServicesListFragment (the parent of the nested fragment)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/service_list_fragment">
<Button
android:id="#+id/addServiceButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="AddService" />
<ListView android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
<TextView android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No data"/>
</LinearLayout>
Layout of ServiceSpecifNotListFragment(the fragment to be nested)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/service_notif_list_fragment" >
<ListView android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
<TextView android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No data"/>
</LinearLayout>
Main activity xml layout (it is basically a reference to the pager):
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
Source code of ServiceListFragment, the call for the nesting of fragments is in the onListItemClick :
public class ServicesListFragment extends ListFragment {
private final String TAG = "ServicesListFragment";
Button addButton = null;
ServiceNotifRowAdapter adapter;
ArrayList<NotifService> list = new ArrayList<NotifService>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Activity parent = getActivity();
// some ommited code for populating adapter with list of stored subscriptions
adapter = new ServiceNotifRowAdapter(getActivity().getApplicationContext(),list);
setListAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.servicelist_fragment, container, false);
addButton = (Button) rootView.findViewById(R.id.addServiceButton);
MainActivity m = (MainActivity) getActivity();
addButton.setOnClickListener(m);
return rootView;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
NotifService item = (NotifService) getListAdapter().getItem(position);
Log.d(TAG, "selected service " + item.getServiceURI());
Fragment newFragment = new ServiceSpecifNotListFragment();
Bundle bundle = new Bundle();
bundle.putString("service", item.getServiceURI());
newFragment.setArguments(bundle);
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.service_list_fragment, newFragment).commit();
}
Main activity java code
public class MainActivity extends FragmentActivity implements TabListener, AddServiceDialogFragmentListener
, OnClickListener{
private final String TAG = "MQTT main activity";
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, StatusListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ServicesListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ConfigFragment.class.getName()));
mAdapter = new TabsPagerAdapter(getSupportFragmentManager(),fragments);
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : MqttApplication.tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
// lock the screen in portrait mode
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
Tabs page adapter
public class TabsPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
private FragmentManager fm;
private final String TAG = "TabsPagerAdapter";
public TabsPagerAdapter(FragmentManager fm,List<Fragment> fragments) {
super(fm);
this.fm = fm;
this.fragments = fragments;
}
#Override
public Fragment getItem(int index) {
return this.fragments.get(index);
}
#Override
public int getCount() {
return this.fragments.size();
}
// 0 - Status, 1 Service, 2 Config (due to the order in which they have been added)
public Fragment findFragmentByPosition(int position) {
return fm.findFragmentByTag(
"android:switcher:" + R.id.pager + ":"
+ this.getItemId(position));
}
}
Just an alternate solution : implemented callbacks in your code and asked your view pager to load SpecificListNotFragment when item clicked in ServiceListFragment. Have a look and try it!
public class ServicesListFragment extends ListFragment {
private final String TAG = "ServicesListFragment";
Button addButton = null;
ServiceNotifRowAdapter adapter;
ArrayList<NotifService> list = new ArrayList<NotifService>();
private onListItemClickCallbackListener mCallback;
public interface onListItemClickCallbackListener {
public void replaceFragmentToServiveListNot();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Activity parent = getActivity();
mCallback = parent; // remember to imlement onListItemClickCallbackListener in activity else it will give error
// some ommited code for populating adapter with list of stored subscriptions
adapter = new ServiceNotifRowAdapter(getActivity().getApplicationContext(),list);
setListAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.servicelist_fragment, container, false);
addButton = (Button) rootView.findViewById(R.id.addServiceButton);
MainActivity m = (MainActivity) getActivity();
addButton.setOnClickListener(m);
return rootView;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
NotifService item = (NotifService) getListAdapter().getItem(position);
Log.d(TAG, "selected service " + item.getServiceURI());
mCallback.replaceFragmentToServiveListNot();
}
}
public class MainActivity extends FragmentActivity implements TabListener, AddServiceDialogFragmentListener
, OnClickListener,onListItemClickCallbackListener {
private final String TAG = "MQTT main activity";
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
List<Fragment> fragments;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, StatusListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ServicesListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ConfigFragment.class.getName()));
mAdapter = new TabsPagerAdapter(getSupportFragmentManager(),fragments);
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : MqttApplication.tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
// lock the screen in portrait mode
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void replaceFragmentToServiveListNot() {
fragments.removeAll(fragments);
fragments.add(Fragment.instantiate(this, StatusListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ServiceSpecifNotListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ConfigFragment.class.getName()));
mAdapter.notifyDataSetChanged();
}
}

Bug in Action Bar tabs when changing orientation

So I wrote this simple tab navigation. It has two tabs called "Fragment 1" and "Fragment 2". If you hit either one, it should display respective texts "Fragment 1" or "Fragment 2" in the content area. My code works fine at the start.
However, when I turn the device to change into landscape orientation, the text messes up. It displays Fragment with a combination of 1 and 2 on the same spot. I think both texts are being displayed at the same time. The text remains that way I try to change tabs after this bug occurs. This also happens when I change from landscape to portrait. What is causing this?
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar ab = getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab = ab.newTab().setText(R.string.frag1).setTabListener(new MyTabListener(this, Fragment1.class.getName()));
ab.addTab(tab);
tab = ab.newTab().setText(R.string.frag2).setTabListener(new MyTabListener(this, Fragment2.class.getName()));
ab.addTab(tab);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class MyTabListener implements ActionBar.TabListener
{
private Fragment mFragment;
private final Activity mActivity;
private final String mFragName;
public MyTabListener(Activity activity, String fragName) {
mActivity = activity;
mFragName = fragName;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mFragment = Fragment.instantiate(mActivity, mFragName);
ft.add(android.R.id.content, mFragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(mFragment);
mFragment = null;
}
}
Fragment1.java
public class Fragment1 extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
return inflater.inflate(R.layout.frag1, container, false);
}
}
Fragment2.java
public class Fragment2 extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
return inflater.inflate(R.layout.frag2, container, false);
}
}
You need to use replace() instead of add() method in your onTabSelected() method.

Categories

Resources