this is my first time using tabs in an app and I feel like this will be a simple fix but I can not find the correct solution. I have 5 tab fragments right now but when I run it all of them contain the same material. I think the problem is with this method:
#Override
public Fragment getItem(int position) {
Fragment fragment = new MiscFragment();
Bundle args = new Bundle();
args.putInt(MiscFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}
I have the fragment set to a new MiscFragment(); (which eclipse automatically built with a dummyfragment when I created the project)
And I have:
public static class MiscFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
public MiscFragment() {
}
View rootView;
GridView gridView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.misc_fragment,
container, false);
gridView = (GridView) rootView.findViewById(R.id.miscgridview);
gridView.setAdapter(new MiscAdapter(getActivity()));
return rootView;
}
}
public static class OtherFragment extends Fragment{
public static final String ARG_SECTION_NUMBER = "section_number";
public OtherFragment(){
}
View rootView;
GridView gridView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup contatiner,
Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.sb_fragment,
contatiner, false);
gridView = (GridView) rootView.findViewById(R.id.sbgridview);
gridView.setAdapter(new OtherAdapter(getActivity()));
return rootView;
}
}
(The first method and both inner classes are in my MainActivity)and it looks like they both use the same "section_number" so both GridViews are referencing the same thing. Both my adapter classes for each fragment have a different number of items in the GridView but the second one looks and acts the same as the first. Any help would be much appreciated!
You never read the section_number argument in the fragment.
int section = getArguments().getInt(ARG_SECTION_NUMBER);
I hate answering my own question but here it is:
The problem was with the getItem method. It works as follows:
public Fragment getItem(int position) {
Fragment fragment1 = new FirstFragment();
Fragment fragment2 = new SecondFragment();
Fragment fragment3 = new ThirdFragment();
if(position == 0){
return fragment1;
}
else if (position == 1){
return fragment2;
}
else{
return fragment3;
}
}
Then each (Number)Fragment() relates to the inner Fragment classes
Related
i have seen the relative post to my issue but, it's not solve my probleme.
I'm trying to get a swipe view with 3 fragment.
In the main fragment i have this:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View vue = inflater.inflate(R.layout.fragment_conversions, container, false);
ConversionsPagerAdapter cPageAdapter = new ConversionsPagerAdapter(getActivity().getSupportFragmentManager());
ViewPager vp = vue.findViewById(R.id.conversionsPager);
cPageAdapter.getItem(0);
vp.setAdapter(cPageAdapter);
Button convKmhKts = (Button) vue.findViewById(R.id.convKmhKts);
convKmhKts.setText("...");
...
Here is the class of my FragmentStatePagerAdapter:
public class ConversionsPagerAdapter extends FragmentStatePagerAdapter{
public ConversionsPagerAdapter(FragmentManager fm) {
super(fm);
Log.i("ARKA", "FragmentStatePagerAdapter CONSTRUCTOR");
}
#Override
public Fragment getItem(int i) {
return ConversionFragment.newInstance(i);
}
#Override
public int getCount() {
return 1;
}
}
And finnaly the Fragment which display the Tab:
public class ConversionFragment extends Fragment {
public static final String ID_CONVERSION = "id_conversion";
public static ConversionFragment newInstance(int pos) {
ConversionFragment stf = new ConversionFragment();
Bundle args = new Bundle();
args.putInt("pos", pos);
stf.setArguments(args);
return stf;
}
public ConversionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// The last two arguments ensure LayoutParams are inflated
// properly.
Bundle args = getArguments();
int idConversion = args.getInt(ID_CONVERSION);
Log.i("idConversion", String.valueOf(idConversion));
int idVue;
switch (idConversion){
case 0: idVue = R.layout.fragment_conversions_vitesse;
break;
case 1: idVue = R.layout.fragment_conversions_vitesse;
default: idVue = R.layout.fragment_conversions_vitesse;
break;
}
View rootView = inflater.inflate(idVue, null);
return rootView;
}
}
The fact is, the getItem() is never called.
I try to change getActivity().getSupportFragmentManager() by getChildFragmentManager(), but it seem it's not the good way...
When i'm trying to acces my button i get this:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
At the line where i'm using the button.
If you use ViewPager inside fragment you have to use chield fragment manager so try replace getActivity().getSupportFragmentManager() with getChildFragmentManager(). If you use one fragment manager for all stuff, it will bring some bugs to you.
For more information
You are doing wrong here
cPageAdapter.getItem(0);
vp.setAdapter(cPageAdapter);
Set adapter to view pager first and then try to call get item method.
vp.setAdapter(cPageAdapter);
cPageAdapter.getItem(0);
Ok,
the probleme was that i try to acces a component which is not inflated:
convKmhKts.setText("...");
I acces to it in the child fragment and now it's ok....
I have been trying to show different layouts in different tabs in the swipeable TabLayout using PagerTabStrip. Can anybody help?
I want to show one layout in first tab, second different layout in 2nd tab etc.
public class MainActivity extends FragmentActivity {
// create object of FragmentPagerAdapter
SectionsPagerAdapter mSectionsPagerAdapter;
// viewpager to display pages
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the adapter that will return a fragment for each of the five
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
/**
* A FragmentPagerAdapter that returns a fragment corresponding to one of
* the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#SuppressLint("NewApi")
#Override
public Fragment getItem(int position) {
switch (position) {
case 0: {
//Show 1st Layout(Here I need HELP)
//HELP HELP HELP
}case 1:
{
//Show 2nd Layout(Here I need HELP)
//HELP HELP HELP
}
default:
}
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
// Show 5 total pages.
return 6;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Section 1";
case 1:
return "Section 2";
case 2:
return "Section 3";
case 3:
return "Section 4";
case 4:
return "Section 5";
case 5:
return "Section 6";
}
return null;
}
}
/**
* A dummy fragment representing a section of the app, but that simply
* displays dummy text.
*/
public static class DummySectionFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public static final String ARG_SECTION_NUMBER = "section_number";
public DummySectionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Create a new TextView and set its text to the fragment's section
// number argument value.
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
textView.setTextSize(25);
textView.setText(Integer.toString(getArguments().getInt(
ARG_SECTION_NUMBER)));
return textView;
}
}
}
View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
switch (getArguments().getInt(ARG_SECTION_NUMBER))
{
case 1: {
rootView = inflater.inflate(R.layout.fragment_bba, container, false);
break;
}
case 2: {
rootView = inflater.inflate(R.layout.fragment_bcom, container, false);
break;
}
case 3: {
rootView = inflater.inflate(R.layout.fragment_bca, container, false);
break;
}
}
return rootView;
Ok for the people who want to solve this problem using design patterns.
Find full working solution Here.
If u write the fragment based on if-else condition it may solve the problem
switch(fragmentId)
{
case 1:
{
fragment 1 related stuff
}
case 2:
{
fragment 2 related stuff
}
.......
.......
and so on
But the problem with this approach is if in future,
1) you decide to add more fragments
or
2) you decide to change some functionality of existing fragment
Then you will have to modify the existing code (inside if-else condition)
Not a preferred programming practice
Instead you can follow this approach
public abstract class BasicFragment extends Fragment {
public BasicFragment newInstance()
{
Log.d("Rohit", "new Instance");
Bundle args = new Bundle();
// args.putInt(ARG_PAGE, page);
BasicFragment fragment = provideYourFragment();
fragment.setArguments(args);
return fragment;
}
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater,ViewGroup parent, Bundle savedInstanseState)
{
View view = provideYourFragmentView(inflater,parent,savedInstanseState);
return view;
}
public abstract BasicFragment provideYourFragment();
public abstract View provideYourFragmentView(LayoutInflater inflater,ViewGroup parent, Bundle savedInstanceState);
}
Your Fragment implementation
public class ImageFragment extends BasicFragment{
#Override
public BasicFragment provideYourFragment() {
return new ImageFragment();
}
#Override
public View provideYourFragmentView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.image_fragment,parent,false);
//Get your parent layout of fragment
RelativeLayout layout = (RelativeLayout)view;
//Now specific components here
ImageView imageView = (ImageView)layout.findViewById(R.id.myImage);
imageView.setImageResource(android.R.drawable.ic_media_play);
return view;
}
}
Happy coding
I have a Main Activity.inside that main activity i have fragment with gridview and i want change my fragment by gridview clicking.
any help...
this is my mainActivity class
public class MainActivity extends Activity implements Fragment_name_list.Communicator {
Fragment_name_list f1;
Fragment_tests f2;
FragmentManager manager;
Fragment_addStudentDetails f3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
manager=getFragmentManager();
f1 = (Fragment_name_list) manager.findFragmentById(R.id.fragment);
f1.setCommunicator(this);
//ArrayAdapter<String> adapter= new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item,result);
}
#Override
public void respond(int index) {
f2 = (Fragment_tests) manager.findFragmentById(R.id.fragment2);
f3 = (Fragment_addStudentDetails) manager.findFragmentById(R.id.fragment3);
switch (index){
case 1:
///Intent i = new Intent(this,Group_AddStudent_details.class);
///i.putExtra("index", index);
//startActivity(i);
f2.changeData(index);
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
}
}
this is my Fragment test class
public class Fragment_tests extends Fragment {
TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_test,container,false);
text = (TextView) view.findViewById(R.id.textViewp);
return view;
}
public void changeData(int index){
String[] result= getResources().getStringArray(R.array.result);
text.setText(result[index]);
}
}
this is my Fragmnet add student class
public class Fragment_addStudentDetails extends Fragment {
TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_add_student_details,container,false);
text = (TextView) view.findViewById(R.id.textViewp);
return view;
}
}
i want to replace my fragmnet_test with fragmnet_add_student_details.
plzz help
First, don't put your Fragments in the layout xml for your main Activity. I can't see if you are doing this for sure from your code, but I suspect that's what you're doing because of the fields you are keeping to refer to the two Fragments you are working with.
What you want to do is have a ViewGroup of some sort (FrameLayout will work) that you put your Fragment into programmatically. Use replace on a FragmentTransaction to swap out the existing Fragment for another.
getFragmentManager().beginTransaction() //
.replace(R.id.fragmentContainer, new BlahFragment()) //
.commit();
Also, don't use mutating methods on Fragments. If the data changes, just swap out the Fragment with the aforementioned code snippet, and get yourself a new Fragment via the documented pattern:
BlahFragment.newInstance(String[] data);
I pulled this example from the docs:
public static class DetailsFragment extends Fragment {
/**
* Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
}
Trying to create application with view pager inside navigation drawer. I've options to select from navigation and depending on that (outer selection), i have to populate different number of fragments in view pager.
I've used tutorials to create navigation drawer and view pager separately from Google docs. As per docs, view pager have fixed number of fragments. if i hard code that way everything works fine.
But, when i try to make it dynamic as per left selection, i'm getting illegal state exception
for instance, I've implemented fragmentstatepageradapter,
public class innerFragment extends Fragment {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
public static final String active_outer_option = "section_number";
public innerFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_outer, container,
false);
Log.d("logs", "onCreateView:innerFragment()");
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((MainActivity) activity).onSectionAttached(Integer
.parseInt(getArguments().getString(active_outer_option)));
Log.d("logs", "onAttach:innerFragment()");
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private int active_outer_option= 0;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Log.d("logs", "getItem(int " + position + ")");
active_outer_option = position;
Bundle b = new Bundle();
b.putString("section_number", "" + position);
DummySectionFragment fragment = new DummySectionFragment();
fragment.setArguments(b);
return fragment;
}
#Override
public int getCount() {
switch (active_outer_option) {
case 0:
return 9;
case 1:
return 2;
case 2:
return 2;
case 3:
return 2;
case 4:
return 4;
default:
return 0;
}
}
#Override
public CharSequence getPageTitle(int position) {
Log.d("logs", "getPageTitle(int " + position + ")");
return "OP " + String.valueOf(position);
}
}
public static class DummySectionFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
public DummySectionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("logs", "onCreateView:DummySectionFragment()");
View rootView = inflater.inflate(R.layout.fragment_inner,
container, false);
TextView dummyTextView = (TextView) rootView
.findViewById(R.id.section_label);
dummyTextView.setText(getArguments().getString(ARG_SECTION_NUMBER));
return rootView;
}
}
}
when i run this application, its giving "Unfortunately application stopped working" and exception is:
java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 9, found: 2 Pager id: com.xxx.xxx:id/pager Pager class: class android.support.v4.view.ViewPager Problematic adapter: class com.xxx.xxx.innerFragment$SectionsPagerAdapter
any idea whats wrong with that exception and code?
Edit:
from my debugging first everything is fine and gettitle is called twice with index 0 and 1 and after that getcount is called with index and getting exception.
does this ring any bells?
I am trying to create a ViewPager which contains 5 fragments.
5 fragments "container", so each of them contain 2 fragments.
The 4 first fragments have the same layout and belong to the same class. The fifth is from an other class, and there is no problem with that one.
The problem is that when the activity launches, only 1 fragment seem to be working (the one at position 0 in viewPager). I tried to return new Fragment() at position 0 in my PagerAdapter, but when I do that it's the 2nd fragment that is working. (By working i mean displaying the list on the left, I still haven't taken care of the details fragment on the right)
Here is some code
CustomPagerAdapter.java
public class CustomPagerAdapter extends FragmentPagerAdapter{
public CustomPagerAdapter(FragmentManager fm) {
super(fm);
}
public CustomPagerAdapter(FragmentManager fm, Context context) {
super(fm);
}
#Override
public Fragment getItem(int pos) {
if(pos == 4)
return new OtherContainerFragment();
else
return new ContainerFragment(pos);
}
#Override
public int getCount() {
return 5;
}
ContainerFragment.java
public class ContainerFragment extends Fragment {
private int CONTAINER_TYPE;
public ContainerFragment(){
}
public ContainerFragment(int type){
CONTAINER_TYPE = type;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_container, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
CustomListFragment frag = new CustomListFragment(CONTAINER_TYPE);
ft.replace(R.id.replaceable_list, frag);
ft.commit();
CustomListFragment.java
public class CustomListFragment extends SuperCustomListFragment{
private ArrayList<Model> mModels;
private int TYPE;
public CustomListFragment(){
}
public CustomListFragment(int type){
TYPE = type;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mModels = new ArrayList<Model>();
if(TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL){
mAdapter = AppUtils.getJournalListAdapter(getActivity(), mModels);
new syncPapers().execute();
}else if(TYPE == AppConstants.FRAGMENT_TYPE_MOVIES){
mAdapter = AppUtils.getMoviesListAdapter(getActivity(), mModels);
new syncMovies().execute();
}
if(mAdapter != null)
mListView.setAdapter(mAdapter); //mListView is defined in the superClass
Here are the constants I use :
public class AppConstants {
public static final int FRAGMENT_TYPE_AGENDA = 0; //so Fragment at position 0 should be of type agenda
public static final int FRAGMENT_TYPE_NEWS = 1; // position 1 should be of type news
public static final int FRAGMENT_TYPE_MOVIES = 2; // ...
public static final int FRAGMENT_TYPE_JOURNAL = 3; // ...
}
And the xml for the container :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/replaceable_list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</LinearLayout>
<LinearLayout
android:id="#+id/replaceable_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/background" >
</LinearLayout>
</LinearLayout>
SO this code is not working, it seems that the list on the left in the fragment container is replaced in each fragment, and only the fragment at position 0 displays it. (Currently it displays the list with the adapter of type "JOURNAL", but it should display list of type "AGENDA".
--------------------
*BUT !...*
--------------------
If I create different fragment_container layout-files, and write IF conditions in the onCreateView and onViewCreated in the ContainerFragment.java, everything works fine.
So :
ContainerFragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL)
return inflater.inflate(R.layout.fragment_container_journal, container, false);
else if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_MOVIES)
return inflater.inflater(R.layout.fragment_container_movies, container, false);
else
return super.onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
CustomListFragment frag = new CustomListFragment(CONTAINER_TYPE);
if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_JOURNAL)
ft.replace(R.id.replaceable_journal_list, frag);
else if(CONTAINER_TYPE == AppConstants.FRAGMENT_TYPE_MOVIES)
ft.replace(R.id.replaceable_movies_list, frag);
else
return;
ft.commit();
I guess that's because in each fragment, I replace the LinearLayout of the same ID ? (replaceable_list)
I thought it was possible to share the same layout file for every fragments and didn't want to create 4 layout-files that would be the same. But it looks like I must do so ?
Or am I missing something here ?
Thank you for your time,
Though a very late response but I was facing same kind of issue and I fixed the issue by using
getChildFragmentManager().beginTransaction()
instead of
getActivity().getSupportFragmentManager().beginTransaction()
As in this case we are trying to make transaction from within a fragment (one out of the list of fragments which are attached to the ViewPager, thus the Activity holding the ViewPager) so we have to use getChildFragmentManager() here for desired results.
I was able to solve this by setting the id of the layout that is inflated within each fragment to its position.
What you would have to do is simply change the method onCreateView in you ContainerFragment class to:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_container, container, false);
v.setId(CONTAINER_TYPE)
return v;
This works because of the way the FragmentPagerAdapter implementation handles fragment tags.