Simple fragmented tabhost in android - java

I am trying to implement fragment-Tabhost in android
MainActivity.java
public class MainActivity extends Activity {
// Declare Tab Variable
ActionBar.Tab Tab1, Tab2;
Fragment fragmentTab2 = new FragmentTab2();
//Fragment fragmentTab3 = new FragmentTab3();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
// Hide Actionbar Icon
actionBar.setDisplayShowHomeEnabled(false);
// Hide Actionbar Title
actionBar.setDisplayShowTitleEnabled(false);
// Create Actionbar Tabs
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set Tab Icon and Titles
Tab1 = actionBar.newTab().setText("Tab1");
//Tab2 = actionBar.newTab().setText("Tab2");
// Set Tab Listeners
Tab1.setTabListener(new TabListener(fragmentTab2));
//Tab2.setTabListener(new TabListener(fragmentTab3));
// Add tabs to actionbar
actionBar.addTab(Tab1);
//actionBar.addTab(Tab2);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
FragmentTab2.java
public class FragmentTab2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragmenttab2, container, false);
return rootView;
}
}
FragmentTab3.java
public class FragmentTab3 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragmenttab3, container, false);
return rootView;
}
}
At present just one tab with one activity is displaying
What i am trying to do ::
click on tab1(first time) - - - - > FragmentTab2.java must display
Click on tab1(second time) - - - - > FragmentTab3.java must display
click on tab1(third time)- - - - > FragmentTab2.java must display again
This cycle must keep on repeating itself
What code changes should i need to make ?
Any IDEAS ?

I got it to work, you still need to make some adjustments, but it will get you started.
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.ActionBar.TabListener;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity implements Notify, TabListener {
ActionBar.Tab tab1;
ActionBar actionBar;
int count = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getFragmentManager().beginTransaction().replace(R.id.container, new FragmentTab2()).commit();
actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
tab1 = actionBar.newTab().setText("Tab1");
tab1.setTabListener(this);
actionBar.addTab(tab1);
}
//Callback
#Override
public void notifyTabListener() {
count++;
Tab tab = actionBar.newTab().setText("Tab" + count);
tab.setTabListener(this);
actionBar.addTab(tab);
}
//Tablistener
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.container, new FragmentTab2());
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(new FragmentTab2(), "Tab" + count);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
Notify callback:
public interface Notify {
public void notifyTabListener();
}
FragmentTab2:
public class FragmentTab2 extends Fragment implements OnClickListener {
Notify mCallback;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.f2, container, false);
LinearLayout layout = (LinearLayout) rootView.findViewById(R.id.layout2);
layout.setOnClickListener(this);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallback = (MainActivity) activity;
}
#Override
public void onClick(View v) {
mCallback.notifyTabListener();
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
</RelativeLayout>
f2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:text="Fragment2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

You need to implement TabListener and set to Tab1.setTabListener().
When onTabSelected(), repeating replace fragment1 or fragment2.

Related

swipe tablayout is not working correctly

i am using "compile 'com.android.support:design:25.1.0'" to implement swipe tablayout. My code has no syntax error but due to some logical error it is not working correctly
Problems: 1) when i slide a page it should move on next tab but it slide or move very slowly and go between two tabs
2) when i come back on privious tabs sometime it does not show even any page and sometime it show wrong page e.g on second tabs it shows third page(fragment)
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout;
String[] tabs={"SCORES","NEWS","SERIES"};
tabLayout=(TabLayout) findViewById(R.id.cricTabLayout);
tabLayout.addTab(tabLayout.newTab().setText(tabs[0]));
tabLayout.addTab(tabLayout.newTab().setText(tabs[1]));
tabLayout.addTab(tabLayout.newTab().setText(tabs[2]));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabTextColors(Color.parseColor("#627179"), Color.parseColor("#BF4A32"));
final ViewPager viewPager=(ViewPager)findViewById(R.id.cricPagerView);
final PageAdapter pageAdapter=new PageAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(pageAdapter);
// new line
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
// viewPager.clearOnPageChangeListeners();
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
// Toast.makeText(MainActivity.this,"Tab changed",Toast.LENGTH_LONG).show();
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
PageAdapter.java
public class PageAdapter extends FragmentStatePagerAdapter {
int numOfTabs;
public PageAdapter(FragmentManager fm, int numOfTabs) {
super(fm);
this.numOfTabs=numOfTabs;
}
public PageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
return new ScoreFragment();
case 1:
return new NewsFragment();
case 2:
return new SeriesFragment();
default: return null;
}
}
#Override
public int getCount() {
return numOfTabs;
}
}
ScoreFragment.java
public class ScoreFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=null;
Toast.makeText(getContext(),"Score",Toast.LENGTH_LONG).show();
return view;
}
}
SeriesFragment.java
public class ScoreFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=null;
Toast.makeText(getContext(),"Score",Toast.LENGTH_LONG).show();
return view;
}
}
NewsFragment.java
public class NewsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=null;
Toast.makeText(getContext(),"News",Toast.LENGTH_LONG).show();
return view;
}
}
MainActivity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_news"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.apple.crickapp.MainActivity"
android:layout_marginLeft="0dp">
<android.support.design.widget.TabLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:elevation="8dp"
android:background="#color/colorBlack"
android:minHeight="?attr/actionBarSize"
android:id="#+id/cricTabLayout"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="#+id/cricPagerView"
android:layout_below="#id/cricTabLayout"
>
</android.support.v4.view.ViewPager>
</RelativeLayout>

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference

I have a BlankFragment
package com.hfad.addingafragmenttoframelayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.w3c.dom.Text;
/**
* A simple {#link Fragment} subclass.
*/
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message","onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
public void setText(String textToBeSet){
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
tv.setText(textToBeSet);
}
}
and it's layout is:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.hfad.addingafragmenttoframelayout.BlankFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment"
android:id="#+id/fragmentText"/>
</FrameLayout>
Here is the MainActivity
package com.hfad.addingafragmenttoframelayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//BlankFragment bf = new BlankFragment();
//getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, bf).commit();
BlankFragment bf = new BlankFragment();
bf.setText("hello world");
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, bf).commit();
}
}
and here is the layout of MainActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.hfad.addingafragmenttoframelayout.MainActivity"
android:orientation="vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fragment_container"
/>
</LinearLayout>
In the onCreate method of activity I am adding fragment to layout. This works fine unless I try to change the Text using setText method.
And I get this error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at com.hfad.addingafragmenttoframelayout.BlankFragment.setText(BlankFragment.java:35)
at com.hfad.addingafragmenttoframelayout.MainActivity.onStart(MainActivity.java:29)
referring to this line
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
Can somebody explain what's causing this exception?
Don't
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message","onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
public void setText(String textToBeSet){
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
tv.setText(textToBeSet);
}
Do
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View RootView = inflater.inflate(R.layout.fragment_blank, container, false);
TextView tv = (TextView)RootView.findViewById(R.id.fragmentText);
tv.setText("HI");
return RootView;
}
Here:
bf.setText("hello world");
line causing issue, becuase calling setText method of Fragment before adding Fragment in FragmentManager.
Call setText method after adding bf Fragment:
getSupportFragmentManager().beginTransaction().
add(R.id.fragment_container, bf).commit();
bf.setText("hello world"); // call here
The problem is FragmentTransaction is async by default
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, BlankFragment.newInstance);
ft.disallowBackStack();
ft.commitNowAllowingStateLoss();
Then you still can't get the Fragment yet, you have to get it from the FragmentTransaction
BlankFragment bf = (BlankFragment) getSupportFragmentManager().getFragmentById(R.id.fragment_container);
bf.setText("hello world");
This article helped me to understand this problem better
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
do it in onCreateView();
You can use a temporary variable that can hold the String while the View is not yet created.
private TextView tv;
private String holder = "";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_blank, container,false);
tv = (TextView)v.findViewById(R.id.fragmentText);
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
tv.setText(holder);
}
public void setText(String textToBeSet){
if(tv != null){
tv.setText(textToBeSet);
}else{
holder = textToBeSet;
}
}
My assumption is that you want to instantiate your BlankFragment with some initial text as well as allowing the text to be set later on from your MainActivity.
In that case I would first change the the Fragment to accept an initial text like so:
public class BlankFragment extends Fragment {
private static final String ARG_INITIAL_TEXT = "arg_initial_text";
public static BlankFragment newInstance(CharSequence initialText) {
final BlankFragment fragment = new BlankFragment();
final Bundle args = new Bundle();
args.putCharSequence(ARG_INITIAL_TEXT, initialText);
fragment.setArguments(args);
return fragment;
}
public BlankFragment() {
// Required empty public constructor
}
private CharSequence mInitialText;
private TextView mText;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInitialText = getArguments().getCharSequence(ARG_INITIAL_TEXT);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message", "onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mText = view.findViewById(R.id.fragmentText);
mText.setText(mInitialText);
}
public void setText(CharSequence textToBeSet) {
mText.setText(textToBeSet);
}
}
The Activity code would then look like the following:
public class MainActivity extends AppCompatActivity {
private BlankFragment mBlankFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
final Fragment bf = BlankFragment.newInstance("hello world");
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, bf, BlankFragment.class.getName())
.commit();
}
mBlankFragment = (BlankFragment) getSupportFragmentManager()
.findFragmentByTag(BlankFragment.class.getName());
}
private void someTimeLaterWhenWantingToSetNewTextToFragmentFromActivity(CharSequence newText) {
if (mBlankFragment != null) {
mBlankFragment.setText(newText);
}
}
}
Note that the null-check of savedInstanceState is to guard for Activity-recreation for instance due to configuration changes.

How to hide and show FloatingActionButton with Fragments in a ViewPager?

I am trying to only show my FloatingActionButton on one fragment and hide in the rest. I have tried multiple answers and nothing is working. I tried this solution:
Hide a Floating Action Button of another Layout
But it isn't working. I tried adding buttons on two of the fragments, one that shows and one that hides the FAB and that works, but once I remove the button, it won't show automatically. Here is my code:
hidden_fragment.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:orientation="vertical">
</LinearLayout>
shown_fragment.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:orientation="vertical">
</LinearLayout>
HiddenFragment.java:
public class HiddenFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container == null) {
return null;
}
View view = inflater.inflate(R.layout.hidden_fragment, container, false);
final FloatingActionButton fab = ((MainActivity) getActivity()).getFloatingActionButton();
if (fab != null) {
((MainActivity) getActivity()).hideFloatingActionButton();
}
return view;
}
}
ShownFragment.java:
public class ShownFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container == null) {
return null;
}
View view = inflater.inflate(R.layout.hidden_fragment, container, false);
final FloatingActionButton fab = ((MainActivity) getActivity()).getFloatingActionButton();
if (fab != null) {
((MainActivity) getActivity()).showFloatingActionButton();
}
return view;
}
}
In my MainActivity.java I have this:
public FloatingActionButton getFloatingActionButton() {
return fab;
}
public void showFloatingActionButton() {
fab.show();
}
public void hideFloatingActionButton() {
fab.hide();
}
The way I currently have it doesn't work. When I launch the app, the first fragment launched is the HiddenFragment. But when I go to the ShownFragment, the FAB doesn't appear. I tried a different approach, I added a button to each fragment and added the showFloatingActionButton() and hideFloatingActionButton() to the buttons and that works. Does anyone know what I am doing wrong?
For showing/hiding a FloatingActionButton with Fragments in a ViewPager, just use a ViewPager.OnPageChangeListener and show the FloatingActionButton for the positions you want, and hide it for the positions you want.
This would go in the Activity:
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
switch (position) {
case 0:
fab.hide();
break;
case 1:
fab.show();
break;
case 3:
fab.hide();
break;
default:
fab.hide();
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Hide the floating button from other fragment. It work in my case.
in MainActivity.java add:
private ActivityMainBinding binding;
public FloatingActionButton getFloatingActionButton() {
return binding.fab;
}
onCreateView in SecondFragment:
private FloatingActionButton floatingButton;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
floatingButton = ((MainActivity) getActivity()).getFloatingActionButton();
floatingButton.hide();
...
}

What's wrong with my dynamically placed Fragment?

I want to rewrite my activities to dialogs, and I want to replace dialogs programmatically. I tried fragments staticaly and it is works fine. When I programmatically call fragment and debug it with breakpoints I don't understand why its lifecycle starts from onCreate() and ends on it... Why from onCreate() and don't from onAttach() like when I call it statically? here is my code, help me plz!!!
base_activity.xml `
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/base_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/base_fragment_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
`
BaseActivity.java
public class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.base_activity);
DietsFragment dietsFragment = new DietsFragment();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.base_fragment_holder, dietsFragment);
fragmentTransaction.commit();
}
}
DietsFragment.java
public class DietsFragment extends Fragment
implements AdapterView.OnItemClickListener,
View.OnClickListener {
public FragmentEventListener fragmentEventListener;
Cursor diets;
DietAdapter adapter;
DietHelper helper;
ListView listView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.activity_diets, container, false);
listView = (ListView) view.findViewById(R.id.act_diets_lv_diets);
if (listView != null) {
listView.setOnItemClickListener(this);
}
FloatingActionButton floatingActionButton = (FloatingActionButton) view.findViewById(R.id.act_diets_fab);
if (floatingActionButton != null)
floatingActionButton.setOnClickListener(this);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
setHelper(new DietHelper(getActivity()));
setDiets(getHelper().getAllTableRecordsCursor());
setAdapter(new DietAdapter(getActivity(), getDiets()));
listView.setAdapter(getAdapter());
fragmentEventListener = (FragmentEventListener) getActivity();
}
public void setDiets (Cursor diets) {
this.diets = diets;
}
public void setAdapter (DietAdapter adapter) {
this.adapter = adapter;
}
public void setHelper (DietHelper helper) {
this.helper = helper;
}
public Cursor getDiets() {
return diets;
}
public DietAdapter getAdapter() {
return adapter;
}
public DietHelper getHelper() {
return helper;
}
}
in DietsFragment and BaseActivity i hide its implementetions of OnClickListener, OnItemClickListener and FragmentEventListener, cause it works fine when i add fragment in BaseActivity statically from xml with
I've just found my mistake... I overloaded findViewbyId(int resId) in BaseActivity and that all my problem, and now i'm asking myself WHY I OVERLOAD THAT METHOD WHAT WAS I WANTED TO DO WITH IT?

ActionBarSherlock fragment showing different data than passed

Hello and thank you for trying to help!
I'm trying to build an app with ActionBarSherlcok. When I click the tabs, I would like the same fragment to instantiate but with dynamic data based on the tab I clicked.
For some reason it keeps showing me the wrong data, though the correct parameter value is passed (I verified it using breakpoints and watches).
I've read about SimpleOnPageChangeListener, getCurrentItem and of course the Fragments Tutorial.
I relied on SwipeyTabs example to create this, and built a short demo to show my problem here:
This is my MainActivity.java
package il.co.gilead.testdynamicfragments;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
public class MainActivity extends SherlockFragmentActivity {
public static ViewPager mViewPager;
private TabsAdapter mTabsAdapter;
Integer intNumOfPages = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewPager = new ViewPager(this);
mViewPager.setId(R.id.pager);
setContentView(mViewPager);
final ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mTabsAdapter = new TabsAdapter(this, mViewPager);
for (int i=1; i<=intNumOfPages; i++) {
mTabsAdapter.addTab(bar.newTab().setText("Fragment "+i),
TestFrag.class, null);
}
}
}
This is my TestFrag.java
package il.co.gilead.testdynamicfragments;
import com.actionbarsherlock.app.SherlockFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class TestFrag extends SherlockFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_test, container, false);
TextView tv = (TextView) v.findViewById(R.id.textView1);
Integer pos = (MainActivity.mViewPager.getCurrentItem() + 1);
tv.setText("Page " + pos.toString());
return v;
}
}
My activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/pager" />
</RelativeLayout>
and my test_frag.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:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
Finally my TabsAdapter
public class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener{
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo{
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args){
clss = _class;
args = _args;
}
}
public TabsAdapter(SherlockFragmentActivity fa, ViewPager pager) {
super(fa.getSupportFragmentManager());
mContext = fa;
mActionBar = fa.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args){
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
#Override
public void onPageScrollStateChanged(int state) {
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
Object tag = tab.getTag();
for (int i = 0; i<mTabs.size(); i++){
if (mTabs.get(i) == tag){
mViewPager.setCurrentItem(i);
}
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
#Override
public int getCount() {
return mTabs.size();
}
}
If you'll play around with it, you'll see that clicking tab "Fragment 2" sometimes shows "Page 1" and sometimes shows "Page 3" and sometimes shows "Page 2".
I think it has something to do with pre-loading the fragments, or fragment refresh, but at this point I am clueless...
Thanks again for your help!
Try to change this:
Integer pos = (MainActivity.mViewPager.getCurrentItem() + 1);
To this:
Integer pos = (getActivity().mViewPager.getCurrentItem() + 1);
I found out what the problem was.
I browsed through ActionBarSherlock website and looked at the sample code. The implementation was different than mine, but one thing stood up.
Here are the code changes in MainActivity.java:
for (int i=1; i<=intNumOfPages; i++)
{
Bundle args = new Bundle();
args.putInt("num", i);
mTabsAdapter.addTab(bar.newTab().setText("Fragment "+i), TestFrag.class, args);
}
Here is the addition to TestFrag.java:
public class TestFrag extends SherlockFragment {
Integer intPageNum;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null)
intPageNum = args.getInt("num");
else
intPageNum = 1;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_test, container, false);
TextView tv = (TextView) v.findViewById(R.id.textView1);
tv.setText("Page " + intPageNum.toString());
return v;
}
}
As you can see, I dropped the use of pos altogether.
Thank you all for trying to help!

Categories