I am using support library to create action bar in my app. I have added actions in action bar thats working perfect. Now I edit tabs below that. But for changing tabs I have to click on tabs. I want to add swipe in this code. But Its difficult for me as I am taking reference from one link thats only show to add tabs and change them with on click on them. So please someone help me to add swipe from screen to change tabs.
Code-
public class Types extends ActionBarActivity {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.types);
setupTabs();
}
private void setupTabs() {
android.support.v7.app.ActionBar ab = getSupportActionBar();
ab.setNavigationMode( ActionBar.NAVIGATION_MODE_TABS );
Tab tab = ab.newTab()
.setText( R.string.frag1).setTabListener(new MyTabListener(this, Type1.class.getName()));
ab.addTab(tab);
tab = ab.newTab()
.setText( R.string.frag2).setTabListener(new MyTabListener( this, Type2.class.getName() ) );
ab.addTab(tab);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search:
homeActivity();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void homeActivity() {
Toast.makeText(this, "Home Option Selexted", Toast.LENGTH_SHORT).show();
}
private class MyTabListener implements ActionBar.TabListener
{
private Fragment mFragment;
private final Activity mActivity;
private final String mFragName;
public MyTabListener( Activity activity, String fragName )
{
mActivity = activity;
mFragName = fragName;
}
#Override
public void onTabReselected( Tab tab,
FragmentTransaction ft )
{
}
#Override
public void onTabSelected( Tab tab,
FragmentTransaction ft )
{
mFragment = Fragment.instantiate( mActivity, mFragName );
ft.add( android.R.id.content, mFragment );
}
#Override
public void onTabUnselected( Tab tab, FragmentTransaction ft )
{
ft.remove( mFragment );
mFragment = null;
}
}
Create ViewPagerAdapter class-
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final int PAGES = 4;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Type1();
case 1:
return new Type2();
case 2:
return new Type3();
case 3:
return new Type4();
default:
throw new IllegalArgumentException("The item position should be less or equal to:" + PAGES);
}
}
#Override
public int getCount() {
return PAGES;
}
}
Then in your Typle class-
public class Types extends ActionBarActivity {
private ViewPager viewPager;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.pagerad);
viewPager = (ViewPager) findViewById(R.id.pager);
ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);
viewPager.setOnPageChangeListener(onPageChangeListener);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
addActionBarTabs();
}
private ViewPager.SimpleOnPageChangeListener onPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
ab.setSelectedNavigationItem(position);
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search:
homeActivity();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void homeActivity() {
Toast.makeText(this, "Home Option Selexted", Toast.LENGTH_SHORT).show();
}
private void addActionBarTabs() {
ab = getSupportActionBar();
String[] tabs = { "TYPE 1", "TYPE 2", "TYPE 3", "TYPE 4" };
for (String tabTitle : tabs) {
ActionBar.Tab tab = ab.newTab().setText(tabTitle).setTabListener(tabListener);
ab.addTab(tab);
}
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
}
private ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
};
}
Finally create pagerad xml-
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
Then create Each Type fragment like-
public class Type1 extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.type, container, false)
return rootView;
}
}
You need to use the ViewPager.
When implementing the viewpager from the android tutorial you simply need to focus on the getitem method of the SectionsPagerAdapter. Here you could pick the right fragment based on the position of the position of the "view".
Your challenge is that the swipe part of the app is now one activity only, and each view now must be implemented as a fragment. But this layout seems compatible with your current code (eg similar to the onTabSelected method).
You types.xml file should be a ViewPager:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.Types" />
Next, declare a ViewPager and SectionsPagerAdapter in you Types activity:
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
Now, in you OnCreate add:
// Create the adapter that will return a fragment for each swipe screen
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
The SectionsPagerAdapter is implemented as:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
if (position == 2) {
return new FragmentA();
} else if (position == 1) {
return new FragmentB();
} else {
// Pattern from you code...
return Fragment.instantiate( mActivity, mFragName );
}
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
That's all :)
Related
My app has a tab bar that should be visible at all times. The first tab contains a ListFragment. When I click on an item within, it loads a new activity that creates a detail fragment displaying the contents of the object in the list. I would like to display this content without having to start a new activity because it also destroys the tab bar!
Any help would be greatly appreciated!
To illustrate, here are some screenshots and code:
This is the code for the FragmentActivity that creates the tabs:
public class MainFragmentActivity extends FragmentActivity
implements ActionBar.TabListener {
SectionsPagerAdapter sectionsPagerAdapter = null;
ViewPager viewPager = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
getActionBar().setDisplayShowHomeEnabled(false);
getActionBar().setDisplayShowTitleEnabled(false);
sectionsPagerAdapter =
new SectionsPagerAdapter
(
getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(sectionsPagerAdapter);
viewPager.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
}); // End of sectionPageAdapter.
Tab browseTab = actionBar.newTab();
browseTab.setIcon(R.drawable.search);
browseTab.setTabListener(this);
actionBar.addTab(browseTab);
Tab myStuffTab = actionBar.newTab();
myStuffTab.setIcon(R.drawable.my_stuff);
myStuffTab.setTabListener(this);
actionBar.addTab(myStuffTab);
Tab profileTab = actionBar.newTab();
profileTab.setIcon(R.drawable.profile);
profileTab.setTabListener(this);
actionBar.addTab(profileTab);
Tab settingsTab = actionBar.newTab();
settingsTab.setIcon(R.drawable.settings);
settingsTab.setTabListener(this);
actionBar.addTab(settingsTab);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Fragment browseFragment = new BrowseFragment();
Bundle browseArgs = new Bundle();
browseArgs.putInt(BrowseFragment.sectionNumberKey, position + 1);
browseFragment.setArguments(browseArgs);
return browseFragment;
case 1:
Fragment myStuffFragment = new MyStuffFragment();
Bundle myStuffArgs = new Bundle();
myStuffArgs.putInt(BrowseFragment.sectionNumberKey, position + 1);
myStuffFragment.setArguments(myStuffArgs);
return myStuffFragment;
case 2:
Fragment profileFragment = new ProfileFragment();
Bundle profileArgs = new Bundle();
profileArgs.putInt(BrowseFragment.sectionNumberKey, position + 1);
profileFragment.setArguments(profileArgs);
return profileFragment;
case 3:
Fragment settingsFragment = new SettingsFragment();
Bundle settingsArgs = new Bundle();
settingsArgs.putInt(BrowseFragment.sectionNumberKey, position + 1);
settingsFragment.setArguments(settingsArgs);
return settingsFragment;
}
return null;
}
// There are always 4 tabs
#Override
public int getCount() {
return 4;
}
// Return a CharSequence for the selected tab
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase();
case 1:
return getString(R.string.title_section2).toUpperCase();
case 2:
return getString(R.string.title_section3).toUpperCase();
case 3:
return getString(R.string.title_section4).toUpperCase();
}
return null;
}
}
} // End of class.
This is the code for the first tab:
public class BrowseFragment extends ListFragment {
public static String sectionNumberKey = "sec_num";
private String activityName = "Browse";
int currentPosition = 0;
List<Listing> listings = new ListingData().getListings();
public BrowseFragment() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BrowseArrayAdapter adapter = new BrowseArrayAdapter(getActivity(),
R.layout.browselist_item,
listings);
setListAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_browse,
container, false);
TextView tv = (TextView) rootView.findViewById(R.id.section_label);
int intSectionNumber = getArguments().getInt(sectionNumberKey);
String numAsString = Integer.toString(intSectionNumber);
tv.setText(numAsString);
activityName += " " + numAsString;
return rootView;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
showDetails(position);
}
void showDetails(int index) {
currentPosition = index;
Intent intent = new Intent();
intent.setClass(getActivity(), BrowseDetailsActivity.class);
intent.putExtra("index", index);
startActivity(intent);
}
And here is the code for the Detail Activity:
public class BrowseDetailsActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// During initial setup, plug in the details fragment.
BrowseDetailFragment details = new BrowseDetailFragment();
details.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
}
}
}
Basicly you just have to use the content of the onCreate method from your BrowseDetailActivity in the showDetails method of your BrowseFragment. In this way, you can drop your BrowseDetailsActivity.
BrowseFragment.java
void showDetails(int index) {
BrowseDetailFragment details = BrowseDetailFragment.newInstance(index);
getChildFragmentManager().beginTransaction().add(details).commit();
}
And use the static newInstance method inside your BrowseDetailFragment like so:
BrowseDetailFragment.java
public class BrowseDetailFragment extends Fragment {
private int position;
public static BrowseDetailFragment newInstance(int position) {
BrowseDetailFragment fragment = new BrowseDetailFragment();
fragment.position = position;
return fragment;
}
public BrowseDetailFragment() {
//Required empty constructor
}
//Lifecycle methods and logics
}
Make sure to provide some navigation option so users can return to your list.
I'm trying to use a NavigationDrawer with FragmentStatePagerAdapter for the navigation of my app. The idea is that when clicking on an item of the NavigationDrawer a new fragment opens with two tabs in it.
My problem is that I can't make it work correctly. When clicking on an item of the NavigationDrawer, instead of two tabs I get four, then six, ...
This problem can be solved with actionBar.removeAllTabs(), but my main problem is that when I come back on a previous fragment by re-clicking on the item of the NavigationDrawer (fragment 1 -> fragment 2 -> fragment 1), I got an empty fragment.
I tried to solve this problem by make some changes according to what's stated on other pages, but I didn't succeed in making it work.
Any help would be appreciated, thank you!
Here is the class managing my main fragment:
public class FragmentMultiTab extends SherlockFragment {
private MyVariables mk;
private ActionBar actionBar;
private ViewPager viewPager;
private View rootView;
private int i;
#Override
public View onCreateView(final LayoutInflater inflater,
final ViewGroup container, final Bundle savedInstanceState) {
final int[] fragment = { R.layout.fragment1, R.layout.fragment2,
R.layout.fragment3 };
final int[] pager = { R.id.pager1, R.id.pager2, R.id.pager3 };
this.mk = new MyVariables(this.getArguments());
i = this.mk.getInt("INDEX");
this.rootView = inflater.inflate(fragment[i], container, false);
viewPager = (ViewPager) this.rootView.findViewById(pager[i]);
viewPager.setOnPageChangeListener(onPageChangeListener);
viewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
viewPager.getAdapter().notifyDataSetChanged();
addActionBarTabs();
return rootView;
}
private final ViewPager.SimpleOnPageChangeListener onPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
actionBar.setSelectedNavigationItem(position);
}
};
private void addActionBarTabs() {
actionBar = getSherlockActivity().getSupportActionBar();
final String[][] tabTitle = {{"Tab 1","Tab 3","Tab 5" },{"Tab 2","Tab 4",
"Tab 6" } };
for (int k = 0; k < 2; k++) {
ActionBar.Tab tab = actionBar.newTab().setText(tabTitle[k][i])
.setTabListener(tabListener);
actionBar.addTab(tab);
}
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
}
private final ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
};
}
Here is the ViewPager used
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 2;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int arg0) {
switch (arg0) {
case 0:
FragmentTab1 fragmenttab1 = new FragmentTab1();
return fragmenttab1;
case 1:
FragmentTab2 fragmenttab2 = new FragmentTab2();
return fragmenttab2;
}
return null;
}
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return PAGE_COUNT;
}
}
My fragments have the following structure:
<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.support.v4.view.ViewPager
android:id="#+id/pager1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</android.support.v4.view.ViewPager>
</RelativeLayout>
And finally here is my MainActivity:
public class MainActivity extends SherlockFragmentActivity {
DrawerLayout mDrawerLayout;
ListView mDrawerList;
ActionBarDrawerToggle mDrawerToggle;
MenuListAdapter mMenuAdapter;
FragmentMultiTab fragment1 = new FragmentMultiTab();
FragmentMultiTab fragment2 = new FragmentMultiTab();
FragmentMultiTab fragment3 = new FragmentMultiTab();
private final MyVariables mk = new MyVariables();
private int currentPosition;
#Override
public void onConfigurationChanged(final Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
this.mDrawerToggle.onConfigurationChanged(newConfig);
}
// The click listener for ListView in the navigation drawer
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
#Override
public void onItemClick(final AdapterView<?> parent, final View view,
final int position, final long id) {
MainActivity.this.selectItem(position);
}
}
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
currentPosition = -1;
// Locate DrawerLayout in activity_main.xml
this.mDrawerLayout = (DrawerLayout) this
.findViewById(R.id.drawer_layout);
// Locate ListView in activity_main.xml
this.mDrawerList = (ListView) this.findViewById(R.id.listview_drawer);
// Set a custom shadow that overlays the main content when the drawer
// opens
this.mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
// Pass results to MenuListAdapter Class
this.mMenuAdapter = new MenuListAdapter(this);
// Set the MenuListAdapter to the ListView
this.mDrawerList.setAdapter(this.mMenuAdapter);
// Capture button clicks on side menu
this.mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// Enable ActionBar app icon to behave as action to toggle nav drawer
this.getSupportActionBar().setHomeButtonEnabled(true);
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
this.mDrawerToggle = new ActionBarDrawerToggle(this,
this.mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open,R.string.drawer_close) {
#Override
public void onDrawerClosed(final View view) {
// TODO Auto-generated method stub
super.onDrawerClosed(view);
}
#Override
public void onDrawerOpened(final View drawerView) {
// TODO Auto-generated method stub
super.onDrawerOpened(drawerView);
}
};
this.mDrawerLayout.setDrawerListener(this.mDrawerToggle);
if (savedInstanceState == null) {
this.selectItem(0);
}
this.mk.setVariables(this);
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
this.getSupportMenuInflater().inflate(R.menu.action_bar_main, menu);
this.getActionBar().setDisplayHomeAsUpEnabled(true);
return true;
}
#Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (this.mDrawerLayout.isDrawerOpen(this.mDrawerList)) {
this.mDrawerLayout.closeDrawer(this.mDrawerList);
} else {
this.mDrawerLayout.openDrawer(this.mDrawerList);
}
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onPostCreate(final Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
this.mDrawerToggle.syncState();
}
private void selectItem(final int position) {
final FragmentTransaction ft = this.getSupportFragmentManager()
.beginTransaction();
if (currentPosition != position)
// Locate Position
switch (position) {
case 0:
this.mk.addInt("INDEX", 0);
this.mk.addBoolean("START", false);
this.fragment1.setArguments(this.mk.getArgs());
ft.replace(R.id.content_frame, this.fragment1);
break;
case 1:
this.mk.addInt("INDEX", 1);
this.fragment2.setArguments(this.mk.getArgs());
ft.replace(R.id.content_frame, this.fragment2);
break;
case 2:
this.mk.addInt("INDEX", 2);
this.fragment3.setArguments(this.mk.getArgs());
ft.replace(R.id.content_frame, this.fragment3);
break;
}
currentPosition = position;
ft.commit();
this.mDrawerList.setItemChecked(position, true);
// Close drawer
this.mDrawerLayout.closeDrawer(this.mDrawerList);
}
}
I'd suggest using the ViewPagerIndicator instead of the standard ActionBar Tabs (they have some issues with regards to being converted into dropdown menus in some cases. The interface is quite simply (you just hook your viewpagerindicator to a viewpager), and you'll probably solve your issue as well.
Hi Im new in android and I want ask for help. Im creating new project in android studio and I use navigation Action bar tabs with viewpager. Android studio generate this code. I know work with one activity atc but now I want to learn work with swipe layouts with tabs. My question is: Is possible do more layouts with different items inside this? For example, now I have on every fragment one textview and when I swipe I see any text on every page. But I need for example on page(tab1) layout with textview, on tab2 I need layout edittext, on tab3 I need layout with image. Is this possible with this? Because I can change text but now I have the same layout for all tabs.
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
}
In this case you can define 3 separate fragment classes. Then you can return them appropriately in getItem of your SectionsPagerAdapter:
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new YourFragmentClass1();
case 1:
return new YourFragmentClass2();
case 2:
return new YourFragmentClass3();
}
}
To elaborate on Szymon's answer.
Step 1 Delete the inner class PlaceHolderFragment
Step 2: Create your fragment classes, with corresponding layouts. For example, ImageViewFragment (which extends Fragment of course) and then image_view_fragment_layout.
Step 3 Have ImageViewFragment's onCreateView method inflateimage_view_fragment_layout.
public ImageViewFragment extends Fragment {
...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.image_view_fragment_layout,
container, false);
return rootView;
}
Follow these steps for as many tabs you want to add.
Then in the getItem() method follow Szymon's answer. Remember, the tab you want to appear first will be in position 0 and so on.
One more Important thing, in your getCount method:
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
the number returned should reflect the number of tabs you have added.
Well, Consider I have have two fragments FragmentTab1 & ShowAllContactFragment. FragmentTab1 consists a list-view & and a button. When the button is clicked I replace ShowAllContactFragment in my viewpager. When shows ShowAllContactFragment, user can select several contacts by selecting check-box in a list-view & it also has a ADD contact button.
What I need: I want to update existing listview in FragmentTab1 , when user pressing ADD button in ShowAllContactFragment, after selecting some contacts in this list-view. I also remove ShowAllContactFragment, and show FragmentTab1 when this will occur.
My Solving Status: I follow the the android developers forum to communicate data between fragment via Activity. I'm almost done. I create Interface OnContactSelectedListener in ShowAllContactFragment & Implements in MainActivity. Everything is ok! . After debugging, I check my callback methods that I have data in MainActivity but I can't replace the ShowAllContactFragment & can't show the previous fragment FragmentTab1 & update it's list-view.
To open ShowAllContactFragment from FragmentTab1, I wrote like:
ShowAllContactFragment allContactsFragment = new ShowAllContactFragment();
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
transaction.addToBackStack(null);
transaction.add(R.id.fragmentTabLayout1, allContactsFragment);
transaction.commit();
My MainActivity & FragmentAdapter Looks :
public class MainActivity extends SherlockFragmentActivity implements
ShowAllContactFragment.OnContactSelectedListener {
ActionBar.Tab Tab1, Tab2, Tab3, Tab4;
private Context context = this;
// view pager
// Declare Variables
ActionBar actionBar;
ViewPager mPager;
Tab tab;
FragmentAdapter mAdapter;
List<Fragment> fragmentList = new ArrayList<Fragment>();
ArrayList<Person> blackListPersonList;
private final static String TAG_FRAGMENT = "TAG_FRAGMENT";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// set application in portrait mode
ActivityHelper.initialize(this);
actionBar = getSupportActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
addFragmentsInList();
// Locate ViewPager in activity_main.xml
mPager = (ViewPager) findViewById(R.id.pager);
// add an adapter to pager
mAdapter = new FragmentAdapter(getSupportFragmentManager(), mPager,
actionBar, fragmentList);
mPager.setAdapter(mAdapter);
addActionBarTabs();
}
public void addFragmentsInList() {
FragmentTab1 aFragmentTab1 = new FragmentTab1();
fragmentList.add(new FragmentTab1());
fragmentList.add(new FragmentTab2());
fragmentList.add(new FragmentTab3());
}
private void addActionBarTabs() {
String[] tabs = { "Tab 1", "Tab 2", "Tab 3" };
for (String tabTitle : tabs) {
ActionBar.Tab tab = actionBar.newTab().setText(tabTitle)
.setTabListener(tabListener);
actionBar.addTab(tab);
}
}
private ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
mPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// add action menu here
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.activity_itemlist, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.add_item:
// openSearch();
Toast.makeText(context, " add_item ", Toast.LENGTH_SHORT).show();
return true;
case R.id.about:
// composeMessage();
Toast.makeText(context, " about", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
class FragmentAdapter extends FragmentPagerAdapter implements
ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
final int TOTAL_PAGES = 3;
private List<Fragment> fragments;
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public FragmentAdapter(FragmentManager fm, ViewPager pager,
ActionBar actionBar, List<Fragment> fragmentsList) {
super(fm);
this.mViewPager = pager;
this.mViewPager.setOnPageChangeListener(this);
this.fragments = fragmentsList;
}
#Override
public Fragment getItem(int position) {
// switch (position) {
// case 0:
// return FragmentTab1.newInstance();
// case 1:
// return FragmentTab2.newInstance();
// case 2:
// return FragmentTab3.newInstance();
// default:
// throw new IllegalArgumentException(
// "The item position should be less or equal to:"
// + TOTAL_PAGES);
// }
return this.fragments.get(position);
}
#Override
public int getCount() {
// return TOTAL_PAGES;
return this.fragments.size();
}
public ViewPager getViewPager() {
return mViewPager;
}
// added newly
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container,
position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
}
#Override
public void onBackPressed() {
Log.e(TAG_FRAGMENT, "onBackPressed");
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
Log.i("MainActivity", "popping backstack");
fm.popBackStack();
} else {
Log.i("MainActivity", "nothing on backstack, calling super");
super.onBackPressed();
}
}
#Override
public void onContactSelected(ArrayList<Person> contactNumberlist) {
// data comes here, no problem.
this.blackListPersonList = contactNumberlist;
Log.d("onContactSelected", "onContactSelected");
// get error here
FragmentTab1 aFragmentTab1 = (FragmentTab1) mAdapter.getItem(0);
if (aFragmentTab1 != null) {
aFragmentTab1.updateFragment1(blackListPersonList);
}
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.add(R.id.fragment_all_contacts_layout, aFragmentTab1);
transaction.commit();
}
public ArrayList<Person> getBlackListContacts() {
return blackListPersonList;
}
// public Fragment getFragment(ViewPager pager){
// Fragment theFragment = fragments.get(pager.getCurrentItem());
// return theFragment;
// }
}
FrgmentTab1 looks :
public class FragmentTab1 extends SherlockFragment implements OnClickListener {
Button btnTest;
ViewPager pager;
LinearLayout layoutBlockNumbers;
LinearLayout layoutContact, layoutCallLog, layoutSMSLog, layoutManually;
public Context mContext;
CustomizedDialog dialog;
private static final int CONTACT_PICKER_RESULT = 1001;
private static final String DEBUG_TAG = "Contact List";
private static final double RESULT_OK = -1;
ListView listViewOnlyBlackListNumber;
ArrayList<Person> personList;
BlackListAdapter aBlackListAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragmenttab1, container,
false);
layoutBlockNumbers = (LinearLayout) rootView
.findViewById(R.id.layoutAddBlockNumbers);
layoutBlockNumbers.setOnClickListener(this);
listViewOnlyBlackListNumber = (ListView) rootView
.findViewById(R.id.listViewOnlyBlackListNumber);
personList = ((MainActivity) getActivity()).getBlackListContacts();
if (personList != null) {
aBlackListAdapter = new BlackListAdapter(getActivity(), personList,
m_onSelectedEventCalender);
listViewOnlyBlackListNumber.setAdapter(aBlackListAdapter);
} else {
listViewOnlyBlackListNumber.setEmptyView(container);
}
return rootView;
}
public void updateFragment1(ArrayList<Person> personList) {
// trying to update when came back here
aBlackListAdapter = new BlackListAdapter(getActivity(), personList,
m_onSelectedEventCalender);
listViewOnlyBlackListNumber.setAdapter(aBlackListAdapter);
aBlackListAdapter.notifyDataSetChanged();
}
}
Get Error In onContactSelected, inside MainActivity
10-30 00:22:29.674: E/AndroidRuntime(26834): FATAL EXCEPTION: main
java.lang.IllegalStateException: Can't change container ID of fragment FragmentTab1{42d27380 #0 id=0x7f040032 android:switcher:2130968626:0}: was 2130968626 now 2130968638
E/AndroidRuntime(26834): at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:407)
E/AndroidRuntime(26834): at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:384)
E/AndroidRuntime(26834): at com.mobigic.callblocker.MainActivity.onContactSelected(MainActivity.java:240)
Hope, Somebody help me.
Your question is not very clear especially the part about how you handle those fragments. Like when you're showing the ShowAllContactFragment fragment in which layout do you put it? From the code you posted it seems you're blindly adding the ShowAllContactFragment fragment directly in the layout containing the ViewPager which isn't right.
Related to the error, you get a reference to one of the fragments already managed by the FragmentManager through the adapter of the ViewPager and then you retry to add it in a transaction, action which will fail. If you're trying to show the previous shown FragmentTab1 fragment, after showing and working with the ShowAllContactFragment fragment, you should try simply removing the last recorded action of the FragmentManager through one of its popBackStack...() methods.
Edit: I looked at your code but what you're doing is still ambiguous. I've looked at the layout for the main activity but you don't have a container with the id R.id.fragment_all_contacts_layout so I'm assuming you're somehow trying to insert the new FragmentTab1 in the layout of the old FragmentTab1 which really doesn't make any sense(not to mention you add the ShowAllContactFragment to a container with the id R.id.fragmentTabLayout1 which I also can't see). Anyway, I'm assuming that you want the ShowAllContactFragment to replace the FragmentTab1 from the ViewPager. For this you'll need a wrapper fragment to hold the two nested fragment and also enable the communication between them. For example the wrapper fragment:
public static class WrapperFragment extends Fragment implements
OnContactSelectedListener {
private static final String TAG_FIRST = "tag_first";
private static final String TAG_SECOND = "tag_second";
private static final int CONTENT_ID = 1000;
private FragmentTab1 mFrag1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FrameLayout content = new FrameLayout(getActivity());
content.setId(CONTENT_ID);
if (getChildFragmentManager().findFragmentByTag(TAG_SECOND) == null) {
mFrag1 = (FragmentTab1) getChildFragmentManager()
.findFragmentByTag(TAG_FIRST);
if (mFrag1 == null) {
mFrag1 = new FragmentTab1();
getChildFragmentManager().beginTransaction()
.add(CONTENT_ID, mFrag1, TAG_FIRST).commit();
}
}
return content;
}
#Override
public void onContactSelected(List<Person> contactNumberlist) {
getChildFragmentManager().popBackStackImmediate();
mFrag1.updateFragment1(contactNumberlist);
}
public void showPickerfragment() {
getChildFragmentManager().beginTransaction()
.replace(CONTENT_ID, new ShowAllContactFragment())
.addToBackStack(null).commit();
}
}
This will be the fragment that you'll use in the ViewPager's adapter instead of the FragmentTab1 fragment. Notice that it implements the OnContactSelectedListener interface. You'll also need to make some changes to other parts of the code:
#Override
public void onClick(View v) {
if (v == layoutCallLog) {
dialog.dismiss();
// make the wrapper fragment to open the ShowAllContactFragment fragment
((WrapperFragment) getParentFragment()).showPickerfragment();
// rest of the code
The ShowAllContactFragment will need to be modified to send the selection event to the wrapper fragment which implements its interface:
#Override
public void onClick(View v) {
if (v == btnAdd) {
Toast.makeText(getActivity(), "" + blockListedPersonList.size(),
Toast.LENGTH_SHORT).show();
((OnContactSelectedListener) getParentFragment())
.onContactSelected(blockListedPersonList);
}
}
And in the main activity to handle the BACK button when the ShowAllContactFragment is showing in the ViewPager:
#Override
public void onBackPressed() {
if (mViewPager.getCurrentItem() == 0) { // I assumed 0 is the position in the adapter where the WrapperFragment will be used
Fragment targetPage = getSupportFragmentManager()
.findFragmentByTag("android:switcher:" + PAGER_ID + ":" + 0); // PAGER_ID is the id of the ViewPager
if (targetPage.getChildFragmentManager().getBackStackEntryCount() > 0) {
targetPage.getChildFragmentManager().popBackStack();
}
return;
}
super.onBackPressed();
}
Keep in mind that you'll need to save the data of the nested fragments.
I used FragmentActivity and ViewPager in differents projects and there are two solutions:
1: You can use onHiddenChanged(boolean hidden) method on your FragmentTab1.
override fun onHiddenChanged(hidden: Boolean) {
// TODO Auto-generated method stub
if (!hidden) {
// check if personList size is changed
// and then call updateFragment1() methode
}
super.onHiddenChanged(hidden)
}
2: Use a static method: you can ake updateFragment1() method static so when user pressing "ADD", call updateFragment1().
Hope it helps.
I've looked at quite a lot of code and can't figure this out. http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
It has to be something simple.
I'm showing most of the code. The error is in the next section.
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
public static final int TAB_COUNT = 3;
public static InputMethodManager inputManager;
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab.
mViewPager
.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
// To control keyboard pop-up
inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
This is where my error is.
case 1 of getItem, Type mismatch: Cannot convert from MainActivity.HistoryFragment to Fragment. it is telling me to either change method return type to HistoryFragment or change return type of newInstance() to Fragment. Where I can't do either. Other examples I've seen look almost identical to my code. I have tried with and without passing an argument.
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
Fragment tipCalc = new TipCalcFragment();
return tipCalc;
case 1:
// Fragment history = new HistoryFragment();
return HistoryFragment.newInstance(i); //ERROR HERE
case 2:
Fragment stats = new StatsFragment();
return stats;
}
return null;
}
And my HistoryFragment that extends ListFragment. In the end it won't be pulling from the String[] values but from database resources. I just wanted to setup a structure first and see it/play with the layout.
public static class HistoryFragment extends ListFragment {
// public HistoryFragment() {
// }
String[] values = new String[] { ... };
static HistoryFragment newInstance(int num) {
HistoryFragment history = new HistoryFragment();
Bundle args = new Bundle();
args.putInt("num", num);
history.setArguments(args);
return history;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.history, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1,
values));
}
}
I figured it out after getting some sleep. I was importing android.app.ListFragment instead of android.support.v4.app.ListFragment
I think you will have to typecast to fragment before returning. So try this
Fragment history = HistoryFragment.newInstance(i);
return history;