I am trying to create a scrollable tabs using fragment.
Tabs are showing and scrolling also. But the problem is the tab content is not showing.
I am using fragments to show the contents. I am new in this topic : fragment. Am I missing anything in this code?
Please help me.
public class SrollableTab extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.addTab(createTab("Tab 1"));
bar.addTab(createTab("Tab 2"));
bar.addTab(createTab("Tab 3"));
bar.addTab(createTab("Tab 4"));
bar.addTab(createTab("Tab 5"));
bar.addTab(createTab("Tab 6"));
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
public Tab createTab(String tabTitle)
{
ActionBar bar = getActionBar();
Tab tab = bar.newTab().setText(tabTitle).setTabListener(new TabFragment());
return tab;
}
class TabFragment extends Fragment implements TabListener
{
#Override
public void onCreate(Bundle fragmentState)
{
super.onCreate(fragmentState);
}
#Override
public View onCreateView(LayoutInflater inflator, ViewGroup container, Bundle savedState)
{
View view = inflator.inflate(R.layout.tab_content, container, false);
TextView t = (TextView)view.findViewById(R.id.txtTab);
t.setText("tab content");
return view;
}
#Override
public void onActivityCreated(Bundle savedState)
{
super.onActivityCreated(savedState);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
}
tab_content.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"
android:background="#ffffff" >
<TextView android:id="#+id/txtTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello"
android:textColor="#ff0000"/>
</LinearLayout>
This may be old but found my own solution on this.
I've use PagerSlidingTabStrip for a while now until I start using the new material TabLayout. Both works on Activity, but not on Fragments. This are some discussion about the bug on fragments.
The fix I've come up with is, on settings viewpager's adater (usually extended with FragmentPagerAdapter) on its constructor parameter it needs FragmentManager, instead of using the activity's FragmentManager use the fragment's one instead which is getChildFragmentManager().
That fix it. Android bugs still annoys me though.
Cheers
Related
I have a main Activity with a navigation drawer and I'm trying to realize a layout like Play Music App with tabs.
The MainActivity has a FrameLayout like a container:
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
and I want to put inside the #+id/container a Fragment with Tabs.
How's the best way to do this?
I thought I can create a MyFragment which extends Fragment and implements TabListener.
The associated layout could be like
<?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>
But then how can I proceed?
Try following the following steps:
First, create your activity and extend FragmentActivity and implement TabListener
Secondly, create your TabsPagerAdapter
Thirdly, create your fragment (or fragments if more than one is needed).
You can then set the adapter in your activity after requesting navigation mode to tabs.
Code Sample
public class SampleActivity extends FragmentActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private ActionBar actionBar;
private TabsPagerAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.gd_pager);
getActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
String [] tabs = new String[]{"Tab1", "Tab2", "Tab3", "Tab3"};
for(String tab : tabs)
{
actionBar.addTab(actionBar.newTab()
.setText(tab)
.setTabListener(this));
}
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
{
viewPager.setCurrentItem(tab.getPosition());
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override
public void onPageSelected(int position)
{
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
}
#Override
public void onPageScrollStateChanged(int arg0)
{
}
});
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}
I put some tabs in the action bar with the following code. Everything looks fine. There are 5 tabs here. I coded each tab to open a new layout. But the problem is only the first tab works fine. Second tab opens the fifth layout and third, fouth, fifth tabs are not working. When I remove the fifth tab, then second tab opens the fourth layout and, other buttons are not woking, I couldn't silve this problem. Please help me. Thank you!
Here is my codings,
main class file;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
android.app.ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
// show the given tab
}
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction ft) {
// hide the given tab
}
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction ft) {
// probably ignore this event
}
};
ActionBar.Tab baby = actionbar.newTab().setText("Baby")
.setTabListener(tabListener);
ActionBar.Tab books = actionbar.newTab().setText("Books")
.setTabListener(tabListener);
ActionBar.Tab electronics = actionbar.newTab().setText("Electronics")
.setTabListener(tabListener);
ActionBar.Tab health = actionbar.newTab().setText("Health and Beauty")
.setTabListener(tabListener);
ActionBar.Tab sports = actionbar.newTab().setText("Sports")
.setTabListener(tabListener);
Fragment babyFragment = new Baby();
Fragment booksFragment = new Books();
Fragment electronicsFragment = new Electronics();
Fragment healthFragment = new Health();
//Fragment sportsFragment = new Sports();
baby.setTabListener(new MyTabsListener(babyFragment));
books.setTabListener(new MyTabsListener(booksFragment));
books.setTabListener(new MyTabsListener(electronicsFragment));
books.setTabListener(new MyTabsListener(healthFragment));
//books.setTabListener(new MyTabsListener(sportsFragment));
actionbar.addTab(baby);
actionbar.addTab(books);
actionbar.addTab(electronics);
actionbar.addTab(health);
actionbar.addTab(sports);
}
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(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);
}
}
every other other java file looks like this;
public class Baby extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.baby, container, false);
}
}
main xml file;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_gravity="center">
<LinearLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</LinearLayout>
</LinearLayout>
Pleease help me to solve this problem.
The error seems to be here:
baby.setTabListener(new MyTabsListener(babyFragment)); // OK
books.setTabListener(new MyTabsListener(booksFragment)); // OK
books.setTabListener(new MyTabsListener(electronicsFragment)); // !!
books.setTabListener(new MyTabsListener(healthFragment)); // !!
You are setting the different listeners to the same tab (that's why the "books" shows the "health" fragment, and the others do nothing).
So recently I needed to implement action bar tabs that would swap out the current fragment with a new fragment. Despite hours of intensive searching I was unable to find a clear solution, so I thought I would present how I solved the problem here. Two of the fragments contained list views, which turned out to be a major complicating factor.
First create an Activity to which you want to attach the fragments. In the XML file for that Activity add a linear layout like so:
<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:orientation="vertical"
tools:context=".WoodenSideProject" >
<LinearLayout
android:id="#+id/fragment_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
Do not add anything else to the XML file. Not even the tab host that is preloaded with Eclipse.
Next create your fragments. First build the UI for your fragment how you want it using the fragment's XML file. I will show how to create a fragment with a List View:
public class Fragment1Name extends Fragment
{
public static String TAG="DirectionsFragment";
private String[] list_items = {"Put the list of Strings you want here"};
ListView lView1;
/*#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, list_items);
setListAdapter(adapter);
}*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_XML_title, container, false);
createListView(view);
// Inflate the layout for this fragment
return view;
}
private void createListView(View view)
{
lView1 = (ListView) view.findViewById(R.id.ListViewID);
//Set option as Multiple Choice. So that user can able to select more the one option from list
lView1.setAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, list_items));
}
}
Some people suggest extending ListFragment for a fragment that uses a List View. My experience has been that is more trouble than it's worth.
Set up the Activity's java file as follows:
public class ActivityName extends FragmentActivity {
public static Context appContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_project);
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
setTitle("WoodenSideProject");
ActionBar.Tab tab1 = actionBar.newTab().setText("Tab1");
ActionBar.Tab tab2 = actionBar.newTab().setText("Tab2");
ActionBar.Tab tab3 = actionBar.newTab().setText("Tab3");
Fragment Fragment1Name = new Fragment1Name();
Fragment Fragment2Name = new Fragment2Name();
Fragment Fragment3Name = new Fragment3Name();
tab1.setTabListener(new MyTabsListener(Fragment1Name));
tab2.setTabListener(new MyTabsListener(Fragment2Name));
tab3.setTabListener(new MyTabsListener(Fragment3Name));
actionBar.addTab(tab1);
actionBar.addTab(tab2);
actionBar.addTab(tab3);
}
Within the same Activity create the following class:
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
//do what you want when tab is reselected, I do nothing
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_placeholder, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
I don't know if others have had as much trouble as I implementing action bar tabs with fragments, but if they are I hope this helps. Any suggestions for better implementations would be greatly appreciated.
I am using a ViewPager to swipe between 4 tabs. I'd love to align the tabs where the current tab is in the aligned middle and there is one tab (if available) on far right, and one on far left.
I know you can do some tricky stuff like that with some of the Third party libraries (for example, by Jake Wharton). But can I have this control with the native ViewPager? (I am also using Support Library v4.)
At the very least, my question is, can I define how many tabs show up on the screen? I have 4, and would like 3 at any given time.
Here is my layout
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="horizontal" />
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
The normal view of a tabbed app has three tabs on the top, and you are allowed to swipe through them. If you have more tabs in your viewpager, you can scroll through as many as you like.
The implementation would be similar to this:
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
private ViewPager ViewPager;
private TabsPagerAdapter SectionsPagerAdapter;
private ActionBar actionBar;
private String[] tabs = { "Event Details", "Line-up", "Donations", "Concert"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialisation
ViewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
SectionsPagerAdapter = new TabsPagerAdapter(getSupportFragmentManager());
ViewPager.setAdapter(SectionsPagerAdapter);
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));
}
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, android.app.FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
ViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
}
}
Hope this helps :)
I am wondering if this can be done. Basically I have a layout with 2 fragments in it that I use for most of my tabs but on 2 of the tabs I want to add a couple more fragments to display more things. Is it possible to change the content view to a different layout when changing tabs?
If that cant be done I thought about creating a layout with all the fragment parts that I would need and just changing the layouts of the fragments so the ones I dont use wont "show". I dont mean using FragmentTransaction.hide() because I want the fragments to fill the screen when others are not used. Would that be a bad idea or is there an easier way to do what I want?
here is my code for the activity and tabs
public class Tabs extends Activity{
long deleteID;
#Override
public void onCreate(Bundle create){
super.onCreate(create);
setContentView(R.layout.main_layout);
createTabs();
ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.setDisplayHomeAsUpEnabled(true);
if(create != null){
bar.setSelectedNavigationItem(create.getInt("Home",0));
}
}
I also add tabs a whatnot but thats not important
this is the actionbar subclass
private class TabListener implements ActionBar.TabListener{
TabContent mFragment;
public TabListener(TabContent fragment) {
mFragment = fragment;
}
#Override
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
ListFragment newListFragment = new BowlersListFragment();
Fragment newFragment = new BowlerEntryFrag();
ft = getFragmentManager().beginTransaction();
ft.replace(R.id.frameOne, newListFragment);
ft.replace(R.id.frameTwo, newFragment);
ft.addToBackStack(null);
ft.commit();
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
if(ft != null){
ft.remove(mFragment);
}
}
}
}
I tried doing Activity.setContentView(r.layout.newView) but that won't work
I had similar problem, so implemented it like this. I have a mainActivity that holds and creates the tabs. That activity uses a layout with one fragment container, main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
In my activity I have the following code for creating the tabs and fragments:
historyTab = actionbar.newTab().setText("History");
historyTab.setTabListener(new MyTabsListener(new HistoryFragment()));
actionbar.addTab(historyTab);
My tabListener looks something like this:
private class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
private boolean isFragmentAdded = false;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xaction = fragMgr.beginTransaction();
if (fragment instanceof HistoryFragment) {
fragment = new HistoryFragment();
xaction.add(R.id.fragment_container, fragment);
} else if (fragment instanceof .. some other fragment..) {
fragment = new .. some other fragment();
xaction.add(R.id.fragment_container, fragment);
}
}
xaction.commit();
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xaction;
xaction = fragMgr.beginTransaction();
Fragment fragment = fragMgr.findFragmentById(R.id.fragment_container);
xaction.remove(fragment);
xaction.commit();
}
}
The layout for the History fragment in my example, can be anything, even a layout that contains two fragments, or as much you need. Just be careful, and in onCreateview method in the fragment, use this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
if (view == null) { // this line is very important!
view = inflater.inflate(R.layout.history_fragment_layout, container, false);
listView = (ListView) view.findViewById(R.id.historyList);
}
return view;
}
Hope that helps!:)