A week later, I am still trying without success to create a tabbed action bar with v7 support to be able to switch between fragments. This is my first effort at an android app in native code and I am new to Java.
My Main.Activity.java looks like this
package com.example.appcompattest;
import android.os.Bundle;
import android.app.Activity;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;
import android.support.v7.app.ActionBarActivity;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// setup action bar for tabs
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(true);
Tab tab = actionBar.newTab()
.setText(R.string.grammar)
.setTabListener(new TabListener<GrammarFragment>(
this, "GRAMMAR", GrammarFragment.class));
actionBar.addTab(tab);
tab = actionBar.newTab()
.setText(R.string.lexis)
.setTabListener(new TabListener<LexisFragment>(
this, "LEXIS", LexisFragment.class));
actionBar.addTab(tab);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
/** Constructor used each time a new tab is created.
* #param activity The host Activity, used to instantiate the fragment
* #param tag The identifier tag for the fragment
* #param clz The fragment's Class, used to instantiate the fragment
*/
public TabListener(Activity activity, String tag, Class<T> clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
/* The following are each of the ActionBar.TabListener call backs */
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
// Commit the transaction
ft.add(R.id.fragment_holder, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.attach( mFragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
}
}
Apart from this, I have a Framelayout called fragment_holder in my activity_main.xml to swap the tabs in and out of, and separate xml files for my two fragments. I also have two classes, LexisFragment.java and GrammarFragment.java which are basically the same (with Grammar/grammar substituted for Lexis/lexis) and look like this.
public class LexisFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.lexisfragment, container, false);
}
When I run the activity, the first fragment is added. Selecting the other tab causes the the second fragment to be added but without destroying the first. On subsequent tab changes the fragments just remain superimposed.
After logging the variables (mTag and mFragment) at each step and experimenting with ft.remove(), I am pretty sure that what is happening is as follows:
On the first tab change onTabUnselected fails to detach / remove anything while onTabSelected adds the new fragment. Then, on sucessive tab changes, the tab which should be added is removed while the tab which should be removed is added. I am grateful for any suggestions.
Hope this helps you..
public class AboutActivity extends Activity {
boolean mIsFromMem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mIsFromMem=savedInstanceState!=null;
}}
Related
I'm trying to create an activity that shows some fragments. I'm following this example here: http://developer.android.com/training/animation/screen-slide.html, however there seems to be some missing code / inconsistencies. I've narrowed down many of the problems but I'm stuck on one part, though it seems it would be simple to someone that knows how this works.
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm); // error on fm
}
error underlines fm on super(fm);: "FragmentStatePagerAdapter (android.support.v4.app.FragmentManager) in FragmentStatePagerAdapter cannot be applied to (android.app.FragmentManager)"
#Override
public Fragment getItem(int position) { // error on Fragment
return ScreenSlidePageFragment.create(position);
}
error underlines Fragment on public Fragment getItem(int position) {: 'getItem(int)' in 'com.example.Application.ScreenSlideActivity.ScreenSlidePagerAdapter' clashes with 'getItem(int)' in 'android.support.v4.app.FragmentStatePagerAdapter'; attempting to use incompatible return type
ScreenSlideActivity.java:
package com.example.dgzl.corvegas;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.NavUtils;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
/**
* Demonstrates a "screen-slide" animation using a {#link ViewPager}. Because {#link ViewPager}
* automatically plays such an animation when calling {#link ViewPager#setCurrentItem(int)}, there
* isn't any animation-specific code in this sample.
*
* <p>This sample shows a "next" button that advances the user to the next step in a wizard,
* animating the current screen out (to the left) and the next screen in (from the right). The
* reverse animation is played when the user presses the "previous" button.</p>
*
* #see ScreenSlidePageFragment
*/
public class ScreenSlideActivity extends android.support.v4.app.FragmentActivity {
/* The number of pages (wizard steps) to show in this demo.*/
private static final int NUM_PAGES = 3;
/* The pager widget, which handles animation and allows swiping horizontally to access previous
* and next wizard steps.*/
private ViewPager mPager;
/* The pager adapter, which provides the pages to the view pager widget.*/
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_slide);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// When changing pages, reset the action bar actions since they are dependent
// on which page is currently active. An alternative approach is to have each
// fragment expose actions itself (rather than the activity exposing actions),
// but for simplicity, the activity provides the actions in this sample.
invalidateOptionsMenu();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.activity_screen_slide, menu);
menu.findItem(R.id.action_prev).setEnabled(mPager.getCurrentItem() > 0);
// Add either a "next" or "finish" button to the action bar, depending on which page
// is currently selected.
MenuItem item = menu.add(Menu.NONE, R.id.action_next, Menu.NONE,
(mPager.getCurrentItem() == mPagerAdapter.getCount() - 1)
? "action_finish"
: "action_next");
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// Navigate "up" the demo structure to the launchpad activity.
// See http://developer.android.com/design/patterns/navigation.html for more.
NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
return true;
case R.id.action_previous:
// Go to the previous step in the wizard. If there is no previous step,
// setCurrentItem will do nothing.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
return true;
case R.id.action_next:
// Advance to the next step in the wizard. If there is no next step, setCurrentItem
// will do nothing.
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A simple pager adapter that represents 5 {#link ScreenSlidePageFragment} objects, in
* sequence.
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return ScreenSlidePageFragment.create(position);
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
ScreenSlidePageFragment.java"
package com.example.Application
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class ScreenSlidePageFragment extends Fragment {
public static final String ARG_PAGE = "page";
private int mPageNumber;
public static ScreenSlidePageFragment create(int pageNumber) {
ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
fragment.setArguments(args);
return fragment;
}
public ScreenSlidePageFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPageNumber = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout containing a title and body text.
ViewGroup rootView = (ViewGroup) inflater
.inflate(R.layout.fragment_today, container, false);
// Set the title view to show the page number.
((TextView) rootView.findViewById(android.R.id.text1)).setText(
getString(R.string.title_template_step, mPageNumber + 1));
return rootView;
}
/**
* Returns the page number represented by this fragment object.
*/
public int getPageNumber() {
return mPageNumber;
}
}
You must import Fragment and FragmentManager class from support library please change your first two lines of import like below in your ScreenSlideActivity class
import android.support.v4.app.FragmentManager
import android.support.v4.app.Fragment
I have the following code :
MainActivity.java
package com.erc.library;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import com.erc.sayeghlibrary.adapter.TabsPagerAdapter;
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Stories", "Dictionaries", "eBooks"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int actionBarTitleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
if (actionBarTitleId > 0) {
TextView title = (TextView) findViewById(actionBarTitleId);
if (title != null) {
title.setTextColor(Color.WHITE);
}
}
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
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));
}
/**
* on swiping the viewpager make respective tab selected
* */
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, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// action with ID action_refresh was selected
case R.id.Favorites:
Toast.makeText(this, "Favorites selected", Toast.LENGTH_SHORT)
.show();
break;
// action with ID action_settings was selected
default:
break;
}
return true;
}
}
TabsPagerAdapter.java
package com.erc.library.adapter;
import com.erc.library.Dictionaries;
import com.erc.library.Ebooks;
import com.erc.library.Stories;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new Stories();
case 1:
return new Dictionaries();
case 2:
// Movies fragment activity
return new Ebooks();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
I'm making a library application in which the navigation is by tabs, the problem is each time I go from the third tab to the first or the first to the third, the tab content is refreshing, I want to prevent the refresh, Any help please ?
By default, ViewPager recreates the fragments when you swipe the page. To prevent this, you can try one of three things:
1. In the onCreate() of your fragments, call setRetainInstance(true).
2. If the number of fragments is fixed & relatively small, then in your onCreate() add the following code:
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(limit); /* limit is a fixed integer*/
3. Use a FragmentPagerAdapter as part of your ViewPager.
If I remember correctly, the second option is more promising. But I urge you to try all three and see which of them work.
one has to instance the FragmentPagerAdapter first, then .getCount() will return a value -
while .getCount() - 1 should be set as the default off-screen limit:
TabsPagerAdapter adapter = new TabsPagerAdapter(getSupportFragmentManager());
/* the ViewPager requires a minimum of 1 as OffscreenPageLimit */
int limit = (adapter.getCount() > 1 ? adapter.getCount() - 1 : 1);
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(limit);
you can handle view recreation by check if the view is null or not
public class FragmentExample extends Fragment {
private View rootView;
public FragmentExample() {}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
if (rootView == null) {
rootView = inflater.inflate(R.layout.fragment_example_layout, container, false);
// Initialise your layout here
} else {
((ViewGroup) rootView.getParent()).removeView(rootView);
}
return rootView;
}
}
In the onCreate() of your fragments, call setRetainInstance(true)
A bit late to this question, but thanks to Y.S., got to know how ViewPager works. I was building an app with 4 tabs and at any point of time, noticed that only two tabs were being refreshed, which I suppose was a default behaviour. After hours of investigation, I understood that Android refreshes multiple tabs to bring in a smooth swiping performance for the user - you might notice that you would have clicked tab2, but android brings in the data for tab3 and keeps it ready.
Though this behaviour is good, it has its pros and cons. Pros - you get a smooth swiping experience, without data being loaded from an external server when you land up in that tab. Cons-your backstack implementation in tabs could go for a toss. When you click a tab, the view pager actually calls smoother tab and you'll end up in a big trouble, if your methods are setting up backarrow (home) at the top left based on what is in the backstack in the clicked tab.
setOffscreenPageLimit is the answer to this. If you want your custom backstack framework to function, and do not want tab3 to be called when tab2 is clicked, you simply need to set the value to the number of tabs. For instance, if you have 4 tabs, set setOffScreePageLimit(4). This would mean that Android would refresh all the 4 fragments initially, which is a bit of a performance overhead (which you should manage properly). But, your backstack and tab switching remain intact. Hope this helps.
Since the activity implements ActionBar.TabListener, the activity's onCreate() is getting called again and again. So place the following code in onResume() method:
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
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));
}
/**
* on swiping the viewpager make respective tab selected
* */
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) {
}
});
In my case above suggestion does not work.
To restrict recreation of fragment, what i did:
In onCreateView you can store inflated view in a global variable and initialize it only if it is null, like in this code:
var root:View?=null
var apiDataReceived=false
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
if (root==null)
root=inflater!!.inflate(R.layout.fragment_layout, container, false)
return root
}
Now if you are parsing some data and fill it into RecyclerView or any other View
Make a global variable like in above code apiDataReceived
Set it to true if you successfully parsed data.
Before apiCalls place a condition like this:
if (!apiDataReceived) {
apiCalls()
}
So if apiCalls() would be called only if data is not parsed.
Do your http calls and parsing or any other thing in method which called after onCreateView like onStart
The above code is in kotlin, If you are facing any issue, let me know in comments.
I'm essentially a new Android Studio developer and currently I am attempting to switch between 3 tabs for my program. Unfortunately, the program forces a close when I try to open things up. I'm not entirely sure where the problem lies since I declared an instance of the classes in regards to the tab.
MainActivity.java
import java.util.Locale;
import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v13.app.FragmentPagerAdapter;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Main extends Activity implements ActionBar.TabListener {
Fragment FragmentTab1 = new Tab1();
Fragment FragmentTab2 = new Tab2();
Fragment FragmentTab3 = new Tab3();
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v13.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the 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++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.auth_port, menu);
return true;
}
#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) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
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.
// Return a PlaceholderFragment (defined as a static inner class below).
Fragment fragment = null;
if (position == 0)
{
fragment = FragmentTab1;
}
if (position == 1)
{
fragment = FragmentTab2;
}
if (position == 2)
{
fragment = FragmentTab3;
}
return fragment;
}
#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;
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given 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);
return rootView;
}
}
Tab1 (The Other 2 Tabs are the same)
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Tab1.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Charge#newInstance} factory method to
* create an instance of this fragment.
*
*/
public class Tab1 extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment Tab1
*/
// TODO: Rename and change types and number of parameters
public static Charge newInstance(String param1, String param2) {
Tab1 fragment = new Tab1();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public Tab1() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_tab1, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
I've looked on other websites for help on this, mostly they cover programs that are obsolete or don't cover the question completely, I have nothing else to turn to so any help on this problem I'd appreciate it.
Edit: I've learned it has to do with creating a .newinstance of the class but how this gets accomplished I haven't quite grasped yet.
Logcat output. Only included error portion
10-29 21:04:04.599 9452-9452/com.example.main
E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.authpayx.authportbeta04, PID: 9452
java.lang.ClassCastException: com.example.main.main#42d45398 must implement
OnFragmentInteractionListener
at com.example.main.Tab1.onAttach(Tab1.java:84)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:849)
at android.app.FragmentManagerImpl.performPendingDeferredStart(FragmentManager.java:785)
at android.app.Fragment.setUserVisibleHint(Fragment.java:997)
at android.support.v13.app.FragmentCompatICSMR1.setUserVisibleHint(FragmentCompatICSMR1.java:23)
at android.support.v13.app.FragmentCompat$ICSMR1FragmentCompatImpl.setUserVisibleHint(FragmentCompat.java:48)
at android.support.v13.app.FragmentCompat.setUserVisibleHint(FragmentCompat.java:76)
at android.support.v13.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:134)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1071)
at android.support.v4.view.ViewPager.populate(ViewPager.java:919)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1441)
at android.view.View.measure(View.java:17478)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5364)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at android.view.View.measure(View.java:17478)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5364)
at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:412)
at android.view.View.measure(View.java:17478)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5364)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2548)
at android.view.View.measure(View.java:17478)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2262)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1391)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1590)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1249)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6585)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at android.view.Choreographer.doFrame(Choreographer.java:573)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5579)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
at dalvik.system.NativeStart.main(Native Method)
You must implement OnFragmentInteractionListener inside your main activity.
change
public class Main extends Activity implements ActionBar.TabListener
to
public class Main extends Activity implements ActionBar.TabListener, OnFragmentInteractionListener
Then make sure your implement
public void onFragmentInteraction(Uri uri);
inside your main activity.
A little info on the new instance method. This is a common practice not a special method you are implementing. You can call it anything that you want but the idea is that new instance method takes your parameters and adds them to a bundle. when android destroys your fragment it gets recreated using its default constructor which does not have your data.
The solution is to use a new instance method and put your data in a bundle because when android recreates your fragment its bundle sticks around.
The only time you would not care about new instance is when you are not passing anything into your fragment.
It seems that this issue related to your Tab1 Fragment class. Also it seems that you created this Fragment class by android studio auto generated blank Fragment class.
For fixing this issue you can change codes of auto generated Fragment classes like Tab1 with code like below.
package com.example.android.actionbarcompat.styled;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by taher on 1/7/15.
*/
public class MainFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.main_view, container, false);
}
}
If you want to use your Tab1 fragment class please not that below comment from your Fragment Class.
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
I had the same problem, and in my case,
delete
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
these code, problem solved
I am receiving The return type is incompatible with FragmentPagerAdapter.getItem(int) for public void Fragment getItem(int position) at the bottom of the code. Error is coming from Fragment.
I have found some related topics on this error and I have tried to do them to fix the issue but nothing seems to solve the error or rather it fixes one error then 5 other errors open up, I try to fix those and again 30 errors open up. Any ideas?
I have changed import android.app.Fragment; to import android.support.v4.app.Fragment; and some other import changes and have gotten it down to this one error. Any help would be greatly appreciated. Thanks!
I included most of the code as I am not sure if I am making errors elsewhere. I believe it has to do with the import but I've tried many diff combinations and no luck.
package com.example.hellofragsandwich;
import java.util.Locale;
import android.app.Activity;
import android.app.ActionBar;
import android.support.v4.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v4.app.FragmentPagerAdapter;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends FragmentActivity implements ActionBar.TabListener, Communicator {
public final int TOTAL_FRAGMENTS=7;
Fragment fragment_0 = new Fragment_0();
Fragment fragment_1 = new Fragment_1();
Fragment fragment_2 = new Fragment_2();
Fragment fragment_3 = new Fragment_3();
Fragment fragment_4 = new Fragment_4();
Fragment fragment_5 = new Fragment_5();
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the 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++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
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) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
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.
// Return a PlaceholderFragment (defined as a static inner class
// below).
Fragment fragment = null;
switch (position) {
case 0:
return fragment_0;
case 1:
return fragment_1;
case 2:
return fragment_2;
case 3:
return fragment_3;
case 4:
return fragment_4;
case 5:
return fragment_5;
case 6:
return fragment_6;
}
return fragment;
}
}
If you are using import android.support.v13.app.FragmentPagerAdapter; from v13 support library you should use android.app.Fragment not v4 one. (with v13 you should use getFragmentManager())
Or if you want to use android.support.v4.app.Fragment you should use android.support.v4.app.FragmentPagerAdapter not v13 one (with v4 fragment you should use getSupportFragmentManager())
I created a Main activity, which sends me to an ActiviteResultats activity.
My goal is now just to show a message in this activity (Message who come from the main).
I followed the Starting Another Activity tutorial.
The problem is, when I start the ActiviteResultats activity, I have an error:
"no view found for id 0x7f080000 ........... for fragment PlaceholderFragment"
... and the app shuts down.
I don't know yet how to use fragments, and the tutorial says I don't have to use it for this example.
Where am I going wrong?
My code :
package com.example.surveyor;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class ActiviteResultats extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activite_resultats);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
String message = "TODO";
// Create the text view
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
// Set the text view as the activity layout
setContentView(textView);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activite_resultats, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_activite_resultats, container, false);
return rootView;
}
}
}
I had the same problem. Just remove the part:
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
That solved it for me. Hope that helps!
A quick look over the tutorial shows that most of the Fragment code is removed in a later step. You could remove all the code related to the fragments, along with the bit about the options menu if you want to clear out all distractions. It's likely to solve your problem and isn't vital to that tutorial
What you need to do is to set up intent in your main activity, and then get it here so it goes like follows:
under Main_Activity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.Main_Activity);
Intent i = new Intent(this,activiteResultats.class); // or getApplicationContext() <= for context
i.putExtras("TagOfMyMessage","MyMessageblablabla");
startActivity(i);
}
under ActivteResultats.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activite_resultats);
Intent i = getIntent();
String message = i.getStringExtras(); // or something like it
// Create the text view
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
// Set the text view as the activity layout
setContentView(textView);
}
You just don't need to use fragments if you want a clear and easy tutorial i advice you to check this one : http://www.vogella.com/tutorials/AndroidIntent/article.html