I use below code to implement tabhost:
public class MyActivity extends FragmentActivity {
private FragmentTabHost mTabHost = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mylayout);
mTabHost = (FragmentTabHost) findViewById(R.id.tabHost);
mTabHost.setup(this, getSupportFragmentManager(), android.R.id.tabcontent);
mTabHost.addTab(mTabHost.newTabSpec("A").setIndicator("A"), AFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("B").setIndicator("B"), BFragment.class, null);
}
}
It contains 2 tabs,
AFragment.class as below:
public class AFragment extends Fragment {
private MyAdapter MyAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_folder_base, container, false);
ListView ListV = (ListView)view.findViewById(R.id.listview);
FolderList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//How to implement to launnch another fragmentC under the same tab
}
});
...
MyAdapter = new MyAdapter(this.getActivity(), this.getContext());
ListV.setAdapter(MyAdapter);
return view;
}
}
I want to launch another fragment (FragmentC) when the item has been click, How can I implement it?
And how can I implement onBackPressed() function in these Fragments?
A: To add FragmentC in FragmentB, put this in FragmentB:
getActivity().getChildrenFragmentManager()
.beginTransaction()
.replace(R.id.fragmentCcontainer, new FragmentC)
.commit();
where the R.id.fragmentCcontainer is the id of the empty view placed on top of other fragmentB's views/ It is a fragment holder:
fragment_b.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Put FragmentB's Views Here-->
<FrameLayout
android:id="#+id/fragmentCcontainer"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
B: There is no onBackPressed() method in fragments. In your case, you should override activity's onBackPressed() method and implement the switch to previous tab in it;
Related
I am sending data from one fragment to another, using interface. This works absolutely fine. Now I am trying to use onSaveInstanceState() to save the value in
a Fragment and retrieving in onCreate(). however i'm getting null in Bundle of onCreate(). P.S. everything works fine when i set the Fragment directly into the activity layout in xml. but when i set the fragment through java code into the activity, the onSaveInstanceState is failing. It is not saving the last known value. Please help. Pasting the code below. You can try it out to know the exact issue.
Fragment_A :
public class Fragment_A extends Fragment implements View.OnClickListener {
Button btnAdd;
int counter = 0;
Communicator comm;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null){
counter = savedInstanceState.getInt("counter", 0);
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
comm = (Communicator) getActivity();
btnAdd = (Button) getActivity().findViewById(R.id.btnAdd);
btnAdd.setOnClickListener(this);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("counter", counter);
}
#Override
public void onClick(View v) {
counter++;
comm.sendData(counter);
}
}
interface Communicator{
void sendData(int i);
}
=====
Activity :
public class Activity_InterComm extends Activity implements Communicator{
FragmentManager manager;
FragmentTransaction transaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intercomm);
Fragment_A fragment_1 = new Fragment_A();
Fragment_B fragment_2 = new Fragment_B();
manager = getFragmentManager();
transaction = manager.beginTransaction();
transaction.add(R.id.frag_a, fragment_1, "Frag1");
transaction.add(R.id.frag_b, fragment_2, "Frag2");
transaction.commit();
}
#Override
public void sendData(int i) {
manager = getFragmentManager();
Fragment_B fragment_b = (Fragment_B) manager.findFragmentById(R.id.frag_b);
fragment_b.setData("Button has been clicked " + i + " times");
}
}
=====
Fragment_B :
public class Fragment_B extends Fragment {
TextView txtMessage;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_b, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
txtMessage = (TextView) getActivity().findViewById(R.id.txtMessage);
}
public void setData(String message){
txtMessage.setText(message);
}
}
activity_intercomm.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">
<!--<fragment
android:id="#+id/frag_a"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:name="android.learning.com.fragintercomm.Fragment_A"/>
<fragment
android:id="#+id/frag_b"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="android.learning.com.fragintercomm.Fragment_B"/>-->
<LinearLayout
android:id="#+id/frag_a"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:background="#color/colorAccent"
android:orientation="vertical"/>
<LinearLayout
android:id="#+id/frag_b"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:background="#color/colorPrimaryDark"
android:orientation="vertical"/>
</LinearLayout>
the soluion I found was using getView() instead of getActivity() while initializing the button in Fragment_A. use btnAdd = (Button) getView().findViewById(R.id.btnAdd); instead of btnAdd = (Button) getActivity().findViewById(R.id.btnAdd);.
However, you can't use getView() in Fragment_B. The Textview freezes and, onSaveInstanceStat() doesn't work. Please suggest a solution.
I have a small problem with my application which uses a FragmentStatePagerAdapter when scrolling between pages.
First I'll describe how the application is built with a stripped down version.
App description
I have one Activity which holds everything together. This Activity in turn hosts a Fragment, in this case called Pager.
This Pager-class has a ViewPager within, with a FragmentStatePagerAdapter as an inner class which is used to provide the fragments for the ViewPager. The fragments provided to the ViewPager are instances of FragmentA.
FragmentA has its own content and its own items on the ActionBar, but can also in turn open other fragments. In my "Real" application this can be done either by clicking some item in a ListView or by clicking a button on the ActionBar. In this simplified case FragmentA can open up FragmentB via a button.
So far this works just as it should.
Problem
When FragmentB is opened from any of the FragmentA-fragments it is properly displayed with its own content and menu in the ActionBar, replacing the menu of FragmentA. However, when navigating back via the back-button the ActionBar for FragmentA is never restored to the state the FragmentA-actionbar had prior to opening FragmentB, instead it's empty.
Possibly strange behaviour
When I change so that MainPagerAdapter extends FragmentPagerAdapter instead of FragmentStatePagerAdapter, all of a sudden it works just fine, and I really don't understand why this is. Also, manually calling supportInvalidateOptionsMenu() did not work at all when the Fragment was contained within a FragmentStatePagerAdapter.
I looked in to the source of both of the adaptertypes but I couldn't figure out why one of them worked while the other didn't.
MainActivity.java
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager()
.beginTransaction()
.addToBackStack("Start")
.replace(R.id.container, new Pager())
.commit();
}
public void openB() {
getSupportFragmentManager()
.beginTransaction()
.addToBackStack("Start1")
.replace(R.id.container, new FragmentB())
.commit();
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/container">
</RelativeLayout>
Pager.java
public class Pager extends Fragment {
ViewPager mViewPager;
MainPagerAdapter mainPagerAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.wrapper_layout, null);
mViewPager = (ViewPager)v.findViewById(R.id.viewpager);
mainPagerAdapter = new MainPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(mainPagerAdapter);
return v;
}
private class MainPagerAdapter extends FragmentStatePagerAdapter {
public MainPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return new FragmentA();
}
#Override
public int getCount() {
return 2;
}
}
}
wrapper_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
FragmentA.java
public class FragmentA extends Fragment {
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
menu.add("A-Menu");
}
#Override
public void onCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.a, null);
Button b = (Button)v.findViewById(R.id.button2);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().supportInvalidateOptionsMenu();
}
});
Button b2 = (Button)v.findViewById(R.id.button);
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity)getActivity()).openB();
}
});
return v;
}
}
a.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
android:id="#+id/button"
android:layout_gravity="center_horizontal"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Invalidate"
android:id="#+id/button2"
android:layout_gravity="right"
/>
</LinearLayout>
FragmentB.java
public class FragmentB extends Fragment{
#Override
public void onCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
menu.add("B-Menu");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.b, null);
return v;
}
}
Can anyone point me to an example or show me how to create a simple Tabbed Dialog in Android where the contents of each tab are Fragments? All the examples/tutorials I have found are about Fragments and Tabs, but nothing specific to DialogFragments.
The documentation for FragmentTabHost shows how to create tabs within normal fragments using getChildFragmentManager(). I'm assuming this should also work when the fragment is a DialogFragment but when I try it I get:
java.lang.IllegalStateException: Fragment does not have a view at android.support.v4.app.Fragment$1.findViewById(Fragment.java:1425)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:901)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
...
Here's my code for setting up the view (which is then passed to AlertDialog.setView()):
private void setupView(View v) {
mTabHost = (FragmentTabHost) v.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Tab1"),
MyDialogFragment.class, null);
}
Spent a lot of time to get it working, but no luck. The only solution I found is create dummy fragment tabhost and use viewpager with fragments instead of tabhost fragments
voters_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
>
<android.support.v4.app.FragmentTabHost
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tabs"
>
</android.support.v4.app.FragmentTabHost>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"/>
</LinearLayout>
Dialog class, the trick is use onCreateView not onCreateDialog
public class VotersDialog extends DialogFragment {
private FragmentTabHost mTabHost;
private ViewPager viewPager;
private VotersPagerAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.voters_dialog, container);
getDialog().setTitle(getArguments().getString("title"));
mTabHost = (FragmentTabHost) view.findViewById(R.id.tabs);
mTabHost.setup(getActivity(), getChildFragmentManager());
mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Плюсов"), Fragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Минусов"), Fragment.class, null);
adapter = new VotersPagerAdapter(getChildFragmentManager(), getArguments());
adapter.setTitles(new String[]{"Плюсов", "Минусов"});
viewPager = (ViewPager)view.findViewById(R.id.pager);
viewPager.setAdapter(adapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i2) {
}
#Override
public void onPageSelected(int i) {
mTabHost.setCurrentTab(i);
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
#Override
public void onTabChanged(String s) {
int i = mTabHost.getCurrentTab();
viewPager.setCurrentItem(i);
}
});
return view;
}
public class VotersPagerAdapter extends FragmentPagerAdapter {
Bundle bundle;
String [] titles;
public VotersPagerAdapter(FragmentManager fm) {
super(fm);
}
public VotersPagerAdapter(FragmentManager fm, Bundle bundle) {
super(fm);
this.bundle = bundle;
}
#Override
public Fragment getItem(int num) {
Fragment fragment = new VotersListFragment();
Bundle args = new Bundle();
args.putSerializable("voters",bundle.getSerializable( num == 0 ? "pros" : "cons"));
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
public void setTitles(String[] titles) {
this.titles = titles;
}
}
public static class VotersListFragment extends ListFragment {
List<String> voters;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_fragment, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
voters = (ArrayList) getArguments().getSerializable("voters");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, voters);
setListAdapter(adapter);
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getActivity(), ProfileActivity_.class);
String login = voters.get(i);
intent.putExtra("login", Utils.encodeString(login.substring(0, login.indexOf("(")).trim()));
startActivity(intent);
}
});
}
}
}
Here is result, now you can press tabs or swipe fragments
I was looking for the same solution but nothing worked out for me so I built my own Android tabbed dialog containing fragments. might be it may help someone.
you can checkout the complete source code from here
You should use a DialogFragment, TabLayout and ViewPager. For instance, your dialog fragment's view may look like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="#+id/masterViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Build your adapter and make sure you override the getPageTitleMethod, e.g:
public class CustomAdapter extends FragmentPagerAdapter {
List<Fragment> mFragmentCollection = new ArrayList<>();
List<String> mTitleCollection = new ArrayList<>();
public CustomAdapter(FragmentManager fm) {
super(fm);
}
public void addFragment(String title, Fragment fragment)
{
mTitleCollection.add(title);
mFragmentCollection.add(fragment);
}
//Needed for
#Override
public CharSequence getPageTitle(int position) {
return mTitleCollection.get(position);
}
#Override
public Fragment getItem(int position) {
return mFragmentCollection.get(position);
}
#Override
public int getCount() {
return mFragmentCollection.size();
}
}
In the OnCreateView of your dialog, you should setup your viewpager with the tabLayout:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.dialog_sample,container,false);
tabLayout = (TabLayout) rootview.findViewById(R.id.tabLayout);
viewPager = (ViewPager) rootview.findViewById(R.id.masterViewPager);
CustomAdapter adapter = new CustomAdapter(getChildFragmentManager());
adapter.addFragment("Boy",CustomFragment.createInstance("John"));
adapter.addFragment("Girl",CustomFragment.createInstance("Stacy"));
adapter.addFragment("Robot",CustomFragment.createInstance("Aeon"));
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
return rootview;
}
I have a blog post written on it here: here.
Try using DialogFragment instead and on your dialogfragment layout include a LinearLayout for fragmentTransaction.
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
String Tag = fragment.getClass().getSimpleName();
t.replace(R.id.llTabFragmentContainer, fragment, Tag);
t.commit();
fragment is your tab fragment.
cheeers
I want to show a Button and a PieChart below in a tab.
Thats the code I worked with: https://github.com/JakeWharton/ActionBarSherlock/blob/master/samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabs.java
Instead of the CountingFragment etc. I implemented my own.
I'm not sure what to
My xml:
fragment_graph_categories.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_graph_categories"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button_filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button_filter" />
</LinearLayout>
And that's my "Tab" attached to the TabManger
public class GraphCategories extends SherlockFragmentActivity {
GraphCategoriesFragment mCategoriesFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_graph_categories);
if (savedInstanceState == null) {
// Do first time initialization -- add initial fragment.
mCategoriesFragment = GraphCategoriesFragment.newInstance(1);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_graph_categories, mCategoriesFragment).commit();
} else {
//mStackLevel = savedInstanceState.getInt("level");
}
}
#Override
protected void onResume() {
if(mCategoriesFragment != null) {
//mCategoriesFragment.onResumeRedraw();
}
}
//notice Inner class
public static class GraphCategoriesFragment extends SherlockFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//View mChartView = inflater.inflate(R.layout.hello_world, container, false);
View rlayout = inflater.inflate(R.layout.fragment_graph_categories, container, false);
//? rlayout = new LinearLayout(getActivity());
return rlayout;
}
}
}
But im not sure what to inflate at the fragments onCreateView or if I need a FrameLayout in my xml?
I tried some options but don't figured it out.
I have a problem with ViewPager. It won't display any of my pre-definied fragments, it just displays a black screen. The onCreateView method is called from inside the fragments.
public class TestViewPager extends FragmentActivity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.test_view_pager);
}
}
public class TestFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.entry_layout, container, false);
return fragmentView;
}
}
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment
class="com.test.TestFragment"
android:id="#+id/embedded1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<fragment
class="com.test.AnotherTestfragment"
android:id="#+id/embedded2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.view.ViewPager>
With ViewPager you must implement a PagerAdapter and supply the fragments from there. You can not define views/fragments to be shown in the ViewPager from XML, as it will simply not draw them.
Edit: Since you want to show Fragments, you must use FragmentPagerAdapter.