I used ActionBarSherlock to get some Holo Themed Tabs and an ActionBar on my app and created a Fragment to handle the behavior on each tab. I wanted the tabs and a button along the bottom to "sandwich" the fragments do at the bottom of the screen there would be a button that would have one click listener across both fragments.
In my Activity I created the tabs like this.
public class InviteFriendsActivity extends SherlockFragmentActivity implements ActionBar.TabListener
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = bar.newTab();
tab1.setText("Tab 1");
tab1.setTabListener(this);
ActionBar.Tab tab2 = bar.newTab();
tab2.setText("Tab 2");
tab2.setTabListener(this);
bar.addTab(tab1);
bar.addTab(tab2);
}
}
And then I created the onTabSelected
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
if (tab.getPosition() == 0)
{
Fragment1 frag = new Fragment1();
ft.replace(android.R.id.content, frag);
}
else if (tab.getPosition() == 1)
{
Fragment2 frag = new Fragment2();
ft.replace(android.R.id.content, frag);
}
}
I have no problem getting the tabs to display or change, but I can't seem to figure out how to get a button the would line the bottom of the screen and stay static while inside this activity and still allow me to switch between the two fragments.
You want a button which is displayed through every fragment and each tab?
This can easily done by using a fragmentcontainer which displays your fragments.
For example use a layout like this:
<?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" >
<fragment
android:name="com.example.yourfragmentcontainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/button1"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:text="Button" />
</RelativeLayout>
For help how to setup a ActonBar using a fragmentcontainer take a look at this tutorial: http://arvid-g.de/12/android-4-actionbar-with-tabs-example
Related
I try to create an application that has two pages. First page is a tabbed page and second page is a detail page.
I create a tapped page using this guide. I have a mainactivity that contains view pager and 3 tabs(Tab1, Tab2, Tab3). Tab3 contains a button to navigate detail page. Each tab has own .java(extends Fragment) and .xml file. I edit fragmentThree.xml layout :
<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"
android:id="#+id/fragmentThree"]>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/goToDetail"
android:text="GO TO DETAIL" />
I create a new fragment for detail page. I set onclick method inside of Tab3.java;
goToDetail.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.mainActivity, new Detail());
transaction.commit();
}
});
When I press the button, it doesn't do anything. I don't replace the fragment.
Use you viewpager id instead of main layout id, where you set the tab layout fragment.
transaction.replace(R.id.viewpager, new Detail());
use Frame layout in Main Activity
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/parent">
In clicklistiner :-
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.parent, new Detail());
transaction.commit();
I followed how to create tabs in the Action Bar using Fragments in Android from this site. While the tabs turned out fine, the TextView that's supposed to appear in the middle of the Fragments is nowhere to be seen. I've looked at other StackOverflow questions that relate to this but none solved my problem.
FragmentTab1.java:
public class FragmentTab1 extends Fragment {
final String TAG = "FRAGMENT_TAB_1";
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tab, container, false);
TextView textview = (TextView) view.findViewById(R.id.txtvwTab);
textview.setText("one");
Log.i(TAG, "textview's text: " + textview.getText());
return view;
}
}
The strangest thing about this is that, while the TextView is not visible, when I look at the LogCat, it still says "textview's text: one". Clearly, the TextView is still getting created. There are no error messages at all.
tab.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"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/txtvwTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" //added later
android:textColor="#color/Black" //added later
android:textSize="40sp" //added later
android:alpha="1" //added later
android:text="DEFAULT" //added later
/>
</RelativeLayout>
In the original code, I couldn't see the "one" displayed, so I tried editing the XML file. I tried changing where it's displayed. I tried specifying its color, its text size, its alpha, and even its default text. Nothing worked!
So what am I still missing? Why is the TextView clearly present and is getting its text set while not actually being visible?
EDIT (more code):
Main.java:
public class Main extends Activity {
ActionBar.Tab tab1, tab2, tab3;
Fragment fragmentTab1 = new FragmentTab1();
Fragment fragmentTab2 = new FragmentTab2();
Fragment fragmentTab3 = new FragmentTab3();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove status bar
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
tab1 = actionBar.newTab().setText("1");
tab2 = actionBar.newTab().setText("2");
tab3 = actionBar.newTab().setText("3");
tab1.setTabListener(new TabListener(fragmentTab1));
tab2.setTabListener(new TabListener(fragmentTab2));
tab3.setTabListener(new TabListener(fragmentTab3));
actionBar.addTab(tab1);
actionBar.addTab(tab2);
actionBar.addTab(tab3);
}
activity_main.xml:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.novoloc.upup2.Main" />
TabListener.java:
public class TabListener implements ActionBar.TabListener {
Fragment fragment;
public TabListener(Fragment fragment) {
this.fragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// nothing done here
}
}
I am facing the similar problem. But i have figured out that the textview is there but it is hiding under the extended toolbar/actionbar(because of including the tablayout in it). Give your textview a margintop of 100dp or 200dp and give it a background color and you will be able to see that it is there but hidden under the actionBar. Or you can even contract the ActionBar by sliding on it upward to reveal your textview.
See the question below for how to solve this :
Fragment from View Pager hiding behind Tab Bar
Been having a headache over this, finally found a simple solution. Set your ViewPager height to an absolute value instead of android:layout_height="match_parent" or android:layout_height="wrap_content"
Try android:layout_height="300dp or some preferred value.
I want to call an fragment method from my activity, describe like in this SO-question: FindByID
TestFragment testFrag = (TestFragment) getFragmentManager().getFragmentById(R.id.testfragment);
if(testFrag != null && testFrag.isAdded())
testFrag.testMethod("Test");
As seen they identify the fragment by ID which is set in the xml. As I only have a fragment container none of my fragment layouts have a ID.
So my seconds thought was using the function getFragmentByTag `like in Tags
fragmentTransaction.replace(R.id.frameTitle, casinodetailFragment, "fragmentTag");
but as I use an action bar with tabs I don't have any tags:
My activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragmentcontainer);
// ActionBar gets initiated
ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Define Tabs
ActionBar.Tab BasicInfoTab = actionbar.newTab().setText(
R.string.tab_BaseInfo);
..
// Define Fragments
PlantBasicInfoFragment BasicInfoFragment = new PlantBasicInfoFragment();
..
// Set TabListeners
BasicInfoTab.setTabListener(new TabListener(BasicInfoFragment));
..
// Add tabs to Actionbar
actionbar.addTab(BasicInfoTab);
..
// Icon clickable
actionbar.setDisplayHomeAsUpEnabled(true);
}
and its layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<LinearLayout
android:orientation="horizontal"
android:id="#+id/LabeledObjectHeaderInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<!-- ... -->
</LinearLayout >
<!-- fragment container -->
<LinearLayout
android:orientation="horizontal"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</LinearLayout>
</LinearLayout>
One of my fragments:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:id="#+id/table">
<TableRow>
<!-- ... -->
</TableRow>
<!-- ... -->
</TableLayout>
and finally my tab listener
public class TabListener implements ActionBar.TabListener {
public Fragment fragment;
public TabListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
So how can I identify my current fragment?
Thanks in advance
P.S. The whole tab switching works perfectly, but now I want to build an addional feature inside the activity!
Add a tag while creating tabs.
ActionBar.Tab BasicInfoTab = actionbar.newTab().setText(R.string.tab_BaseInfo);
BasicInfoTab.setTag("tab1");
And in the listener class, retrieve the tag upon event.
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
String tabId = tab.getTag().toString();
}
This way you get the current tag. To identify the current fragment, you can keep a stack of fragments and pick the right one on tab change.
Edit
The tabId, aforementioned, identifies which tab is which. In order to set a fragment id/tag, there are many ways depending on your needs. One method is to replace your actual fragment layout with an intermediate layout.
For instance, A be the fragment you want to add to fragment container. Create another fragment class called IntermediateFragment with the following layout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:baselineAligned="false">
<fragment
android:id="#+id/fragmentId"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="classA" />
</LinearLayout>
Now assign the layout you mentioned in the post (containing table) as a new one and add it to fragment class A. Now add Intermediate fragment to container which in turn pulls fragment A. Identify fragment A by id/tag added in the layout.
Hope it makes some sense!
Finally I got my solution by changing the TabListener, so I can add the fragment with an tag and then use the findFragmentByTag() function.
So my TabListener now looks like this (only constructor and onTabSelected changed)
public TabListener(Fragment fragment, String tag) {
this.fragment = fragment;
this.fragmentTag = tag;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment, fragmentTag);
}
With this I only need to add a string (as tag) when adding the TabListener to my fragments and don't have to do further changes.
I have got some sample FragmentTabHost project. And I made some modifications which are required for my project.
my tab bar xml (bottom_tabs.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" >
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
<android.support.v4.app.FragmentTabHost
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0" />
</android.support.v4.app.FragmentTabHost>
</LinearLayout>
oncreate() - FragmentActivity
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
Bundle b = new Bundle();
b.putString("key", "Simple");
mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),
Fragment1.class, b);
//
b = new Bundle();
b.putString("key", "Contacts");
mTabHost.addTab(mTabHost.newTabSpec("contacts")
.setIndicator("Contacts"), Fragment2.class, b);
b = new Bundle();
b.putString("key", "Custom");
mTabHost.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"),
Fragment3.class, b);
Fragment3 class
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_3,
null);
Button b = (Button) root.findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Fragment f;
f = (Fragment) new Fragment4();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.realtabcontent, f);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
});
return root;
}
The Problems:
**
1) If I press goto1 button in Fragment3 , It redirects to Fragment4.
No Issues
2) Then I press the tabs, the layout of the Fragment4 is overlapped
in all the screens
3) If I press goto 2nd tab button, How to redirect to Fragment2 and
same time 2nd tab should be highlighted.
**
Please provide me the best way to do this.
To change tabs your should use the FragmentTabHost.setCurrentTab() method instead of using FragmentTransaction yourself (it is handled internally). The reason your Fragment4 is appearing overlapped is because it is never removed when you change tabs.
This is what is happening:
You navigate to tab 3.
You press the goto fragment4 button which causes your code to replace fragment3 with fragment4
You press another tab indicator. This causes the FragmentTabHost to remove the current fragment (which it still thinks is Fragment3) and add the new Fragment. The Fragment4, which you added manually, is still there. To avoid this you could add a listener for tab change events and explicitly remove Fragment4 if it is there.. Or even better you could add Fragment4 as a child fragment of Fragment3. That way when you leave Tab3 it will go away, and it will appear again when you return to Tab3. It just depends on what you are trying to accomplish.
I have an application which has a TabHost set up with 5 tabs. These tabs are fragment activities. In each of these fragment activities, there is are several fragments set up.
My Main class sets up the tabHost and fragment activities like so
public class Main extends TabActivity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
Resources res = getResources();
tabHost = getTabHost();
TabHost.TabSpec spec;
Intent intent;
intent = new Intent().setClass(this,
Tab1.class);
spec = tabHost
.newTabSpec("home")
.setIndicator("Home",
res.getDrawable(R.drawable.tabhome))
.setContent(intent);
tabHost.addTab(spec);
//and do this for the other 4 tabs
tabHost.setCurrentTab(0);
}
}
Then my fragmentActivities are set up like this
public class Tab1 extends FragmentActivity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
FragmentTransaction fragmentTransaction = getSupportFragmentManager()
.beginTransaction();
// Fragments
Fragment fragOne = new FragmentOne();
Fragment fragTwo = new FragmentTwo();
Fragment fragThree = new FragmentThree();
fragmentTransaction.replace(R.id.fragmentOne, fragOne);
fragmentTransaction.replace(R.id.fragmentTwo, fragTwo);
fragmentTransaction.replace(R.id.fragmentThree, fragThree);
fragmentTransaction.commit();
}
}
Tab1 Fragment Activity has 3 fragments as you can see above. Each Fragment, FragmentOne, FragmentTwo and FragmentThree each contain a next button inside the fragments.
What I would like to know is how do I set it up so they transition between each fragment within the class. E.g.
Frag1 (in Frag1 click next button ), Frag 2 transitions from the right (in Frag2 here click next button) Frag3 transitions in from the right (in Frag3, click next button) Frag1 transitions in from the right.
Any assistance would be much appreciated!!!
Edit: Will also paste how the fragments are set up in the home.xml layout file incase your wondering how I set it up.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/homeMain"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<RelativeLayout
android:id="#+id/FragmentOneRL"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/fragmentOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</FrameLayout>
</RelativeLayout>
<RelativeLayout
android:id="#+id/FragmentTwoRL"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_below="#+id/FragmentOneRL"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/fragmentTwo"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</FrameLayout>
</RelativeLayout>
<RelativeLayout
android:id="#+id/FragmentThreeRL"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_below="#+id/FragmentTwoRL"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/fragmentThree"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</FrameLayout>
</RelativeLayout>
</RelativeLayout>
I eventually figured it out, I changed the XML file to this
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/TheFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</FrameLayout>
</RelativeLayout>
And then in the FragmentActivity I created this method
protected void changeFragment(Fragment removeFrag, Fragment f)
{
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(R.anim.view_transition_in_left,
R.anim.view_transition_out_left);
ft.replace(R.id.TheFragment, f);
ft.remove(removeFrag);
ft.addToBackStack(null);
ft.commit();
}
Then in each fragment when user clicked next button would do something like this
Fragment f = ((Tab1) getActivity()).fragTwo;
Fragment rf = ((Tab1) getActivity()).fragOne;
((Tab1) getActivity()).changeFragment(rf, f);