I'm trying to open a new fragment in viewpager's fragment using this as example. But I'm getting this error of IndexOutOfBoundsException in the line tabLayout.getTabAt(0).setIcon(tabIcons[0]);. I pasted the logcate here. Can any one tell me how to solve this as I need tablayout with my viewpager while the example didn't had one?
public class FirstFragment extends Fragment {
private static final String TAG = "FirstFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.first_fragment, container, false);
Button btn = (Button) view.findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction trans = getFragmentManager()
.beginTransaction();
/*
* IMPORTANT: We use the "root frame" defined in
* "root_fragment.xml" as the reference to replace fragment
*/
trans.replace(R.id.root_frame, new SecondFragment());
/*
* IMPORTANT: The following lines allow us to add the fragment
* to the stack and return to it later, by pressing back
*/
trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
trans.addToBackStack(null);
trans.commit();
}
});
return view;
}
}
First tab:
public class RootFragment extends Fragment {
private static final String TAG = "RootFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/* Inflate the layout for this fragment */
View view = inflater.inflate(R.layout.root_fragment, container, false);
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
/*
* When this container fragment is created, we fill it with our first
* "real" fragment
*/
transaction.replace(R.id.root_frame, new FirstFragment());
transaction.commit();
return view;
}
}
Main Activity:
public class MainActivity extends AppCompatActivity {
// For this example, only two pages
static final int NUM_ITEMS = 2;
private TabLayout tabLayout;
private ViewPager mPager;
private int[] tabIcons = {
R.drawable.facebook,
R.drawable.twitter
};
SlidePagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Instantiate a ViewPager and a PagerAdapter. */
tabLayout=(TabLayout)findViewById(R.id.tabs);
mPager = (ViewPager) findViewById(R.id.viewpager);
mPagerAdapter = new SlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
setupTabIcons();
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
}
/* PagerAdapter class */
public class SlidePagerAdapter extends FragmentPagerAdapter {
public SlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
/*
* IMPORTANT: This is the point. We create a RootFragment acting as
* a container for other fragments
*/
if (position == 0)
return new RootFragment();
else
return new StaticFragment();
}
#Override
public int getCount() {
return NUM_ITEMS;
}
}
}
use below function
private void setupTabIcons() {
tabLayout.addTab(tabLayout.newTab().setIcon(tabIcons[0]));
tabLayout.addTab(tabLayout.newTab().setIcon(tabIcons[1]));
}
you have not added any tab to your tabLayout, so you get IndexOutOfBoundsException
Related
I want to want to make ViewPager with each tab containing three fragments. FragmentPagerAdapter only works for one fragment, so I tried my best to make my own custom adapter extending PagerAdapter. Unfortunately, the code I wrote only displays these three Fragments in the first tab and after restarting the app all tabs are blank. I suspect that it has something to do with onSaveInstanceState, but I don't know how to make it properly. Also, I've read that I shouldn't add the fragments to FragmentTransaction in instantiateItem, but I don't know where else I could do it. Could you help me ?
TaskListPagerActivity:
public class TaskListPagerActivity extends AppCompatActivity implements BottomPanelFragment.OnBottomPanelSelectedListener {
private static final String TAG = "TaskListPagerActivity";
private ViewPager mViewPager;
FragmentStacker[] mStacker;
public static Intent newInstance(Context packageContext) {
Intent intent = new Intent(packageContext, TaskListPagerActivity.class);
return intent;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task_list_pager);
mStacker = new FragmentStacker[7];
mViewPager = (ViewPager) findViewById(R.id.activity_task_list_pager);
mViewPager.setAdapter(new TaskListPagerAdapter(this));
}
// Interface methods
private class TaskListPagerAdapter extends PagerAdapter {
private FragmentActivity mContext;
public TaskListPagerAdapter(FragmentActivity context) {
mContext = context;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment res;
FragmentManager fm = mContext.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (mStacker[position] == null) {
mStacker[position] = new FragmentStacker();
ft.add(container.getId(), mStacker[position]);
} else {
ft.attach(mStacker[position]);
}
res = mStacker[position];
ft.commit();
return res;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
#Override
public int getCount() {
return 7;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return ((Fragment) object).getView()==view;
}
}}
FragmentStacker:
public class FragmentStacker extends Fragment {
Fragment[] fragments = createFragments();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.task_list_activity_fragment, container, false);
FragmentManager fm = getFragmentManager();
Fragment customDateFragment = fm.findFragmentById(R.id.custom_date_fragment_container);
Fragment taskListFragment = fm.findFragmentById(R.id.task_list_fragment_container);
Fragment bottomPanelFragment = fm.findFragmentById(R.id.bottom_panel_container);
FragmentTransaction fragmentTransaction = fm.beginTransaction();
if (customDateFragment == null) {
customDateFragment = fragments[0];
taskListFragment = fragments[1];
bottomPanelFragment = fragments[2];
fragmentTransaction.add(R.id.custom_date_fragment_container, customDateFragment);
fragmentTransaction.add(R.id.task_list_fragment_container, taskListFragment);
fragmentTransaction.add(R.id.bottom_panel_container, bottomPanelFragment);
fragmentTransaction.commit();
} else {
fragmentTransaction.attach(customDateFragment);
fragmentTransaction.attach(taskListFragment);
fragmentTransaction.attach(bottomPanelFragment);
}
return v;
}
private Fragment[] createFragments() {
return new Fragment[]{new CustomDateFragment(), new TaskListFragment(), new BottomPanelFragment()};
}}
I am creating swipe screens using ViewPager where i have two fragments to show using swipes inside FragmentActivity .Please consider the following code :
Fragment_One.java
public class Fragment_One extends Fragment {
private Button btnNext;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_one,null);
btnNext = (Button) v.findViewById(R.id.btnNext);
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment = new Fragment_Two();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentOne,fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return v;
}
}
2.Fragment_Two.java
public class Fragment_Two extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_two,null);
}
}
3. PagerAdapter.java
public class PagerAdapter extends FragmentPagerAdapter {
List<Fragment> listFragments ;
public PagerAdapter(FragmentManager fm,List<Fragment> listFragments) {
super(fm);
this.listFragments = listFragments;
}
#Override
public Fragment getItem(int i) {
return listFragments.get(i);
}
#Override
public int getCount() {
return listFragments.size();
}
}
4.MainActivity.java
public class MainActivity extends FragmentActivity{
private List<Fragment> listFragments;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
Fragment_One fragment_one = new Fragment_One();
Fragment_Two fragment_two = new Fragment_Two();
listFragments = new ArrayList<>();
listFragments.add(fragment_one);
listFragments.add(fragment_two);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(),listFragments);
viewPager.setAdapter(pagerAdapter);
}
}
The above mentioned code is working fine while swiping screens .But i click on next button ,fragment is replaced with another but is displayed on the same screen.I am not able to fix the issue.Screenshot is given below :
Next button should work in the same way as we swipe the screen .Please help me to fix the issue.
Wouldn't that be easier to use:
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
viewPager .setCurrentItem(viewPage.getCurrentItem() + 1);
});
My ViewPager is not working correctly. I don't know what's wrong with my code. I am facing some problems with my Fragments:
Basically, I have a Fragment named MyListFragment that has a list and on the click event of list item I move to the second Fragment named FlowersFragment that has a ViewPager with three items(Another three Fragments) in it. And i have a Button in my FlowersFragment and on click of that Button i move to the third screen named WelcomeFragment. now i have a problem :
If i go back to FlowersFragment from WelcomeFragment then it loses some Fragments from ViewPager after some research i got a solution like use childFragmentManager while creating adapter. That is good for my pager all Fragments are now showing correctly in my FlowersFragment Pager. But if I go back to MyListFragment and I click on second or third item of ListFragment its showing me exception with NO ACTIVITY.
Here is my FirstFragment named MyListFragment
public class MyListFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
private ListView listviewPlaces;
private FloristAdapter adapter;
private ArrayList<FloristItems> items = new ArrayList<FloristItems>();
private FlowersFragment frag;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_list, container,false);
listviewPlaces = (ListView)view.findViewById(R.id.listviewPlaces);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
for (int i = 0; i < 10; i++) {
FloristItems florist = new FloristItems();
florist.away = "3 miles away";
florist.title = "Florist Flowers";
florist.price = "$45";
items.add(florist);
}
adapter = new FloristAdapter(getActivity().getApplicationContext(), items);
listviewPlaces.setAdapter(adapter);
listviewPlaces.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if(frag == null){
frag = new FlowersFragment();
}
handleFragments(frag);
}
});
}
private void handleFragments(Fragment fragment){
fm = getActivity().getSupportFragmentManager();
ft = fm.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(null);
ft.commit();
}
}
Here is my FlowersFragment class that have view pager with containing three fragments:
public class FlowersFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
private ViewPager pager;
private Button btnSendThatFlower;
private FlowerPagerAdapter pageAdapter;
private WelcomeFragment welcomeFrag;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_choose_flower_buyer, container,false);
pager = (ViewPager)view.findViewById(R.id.viewpager);
btnSendThatFlower = (Button)view.findViewById(R.id.btnSendThatFlower);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
pageAdapter = new FlowerPagerAdapter(getActivity().getSupportFragmentManager());
pager.setAdapter(pageAdapter);
btnSendThatFlower.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(welcomeFrag == null){
welcomeFrag = new WelcomeFragment();
}
handleFragments(welcomeFrag);
}
});
}
private void handleFragments(Fragment fragment){
fm = getActivity().getSupportFragmentManager();
ft = fm.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(null);
ft.commit();
} }
Here is my pager Adapter class:
public class FlowerPagerAdapter extends FragmentPagerAdapter{
private ArrayList<Fragment> pagerItems;
public FlowerPagerAdapter(FragmentManager fm) {
super(fm);
pagerItems = new ArrayList<Fragment>();
pagerItems.add(FlowerImage1.getInstance());
pagerItems.add(FlowerImage2.getInstance());
pagerItems.add(CustomFlowerFragment.getInstance());
}
#Override
public Fragment getItem(int num) {
if (num == 0) {
return new FlowerImage1();
}
else if(num == 1) {
return new FlowerImage2();
}
else{
return new CustomFlowerFragment.getInstance();
}
}
#Override
public int getCount() {
return pagerItems.size();
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
//super.restoreState(state, loader);
}}
FlowerImage1 FlowerImage1 CustomFlowerFragment are fragments with only imageview.
This is my last fragment WelcomeFragment
public class WelcomeFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_write_note_buyer, container,false);
return view;
}}
when i am pressing back press then its not showing fragments in viewpager but after swipe on view pager its showing only first or sometimes last pager fragment.
I have also faced same issue ended up adding following code inside fragment adapter.
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
//super.restoreState(state, loader);
}
I was also faced with the same problem, but i fixed it by extending "FragmentStatePagerAdapter" instead of FragmentPagerAdapter. for your case,it would be:
public class FlowerPagerAdapter extends FragmentStatePagerAdapter{
private ArrayList<Fragment> pagerItems;
public FlowerPagerAdapter(FragmentManager fm) {
super(fm);
pagerItems = new ArrayList<Fragment>();
pagerItems.add(FlowerImage1.getInstance());
pagerItems.add(FlowerImage2.getInstance());
pagerItems.add(CustomFlowerFragment.getInstance());
}
#Override
public Fragment getItem(int num) {
if (num == 0) {
return new FlowerImage1();
}
else if(num == 1) {
return new FlowerImage2();
}
else{
return new CustomFlowerFragment.getInstance();
}
}
#Override
public int getCount() {
return pagerItems.size();
}
}
here's a portion of my code:
public class MenuExpenses extends Fragment {
private ViewPager viewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.expenses,container, false);
viewPager = (ViewPager) root.findViewById(R.id.pager);
viewPager.setAdapter(new MyPagerAdapter(getChildFragmentManager()));
// Bind the tabs to the ViewPager
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) root.findViewById(R.id.tabs);
tabs.setViewPager(viewPager);
return root;
}
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
private final String[] TITLES = { "Daily", "Recurring" };
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0: return new MenuExpensesDaily();
case 1: return new IncomeList2();
default: return new MenuExpensesDaily();
}
}
}
}
MenuExpensesDaily & IncomeList2 are both fragments. So how can I set the fragment tag for both of them here?
You can override the instantiateItem method, the save the fragment to a SparseArray/HashMap, then create a method to return the fragment with the position. Now you will be able to access your selected your fragment and set the tag to it.
I have a viewpager with 2 fragment pages inside it. Now i want to access the views (textview,buttons) from the first fragment page but everytime Iam getting Nullpointer exception
check out my code
Fragment i want to access its views:
public class ListPagerFragment extends Fragment
{
ListView listview;
TextView text;
private ViewPager pager;
public static ListPagerFragment newInstance(int message)
{
ListPagerFragment f = new ListPagerFragment();
// pass the text message received from main activity into a bundle to be
// delivered to the new fragment
Bundle bdl = new Bundle();
bdl.putInt("num", message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.list_pager_fragment, container, false);
return v;
}
public void fillList(Nameslist list)
{
listview = (ListView) getView().findViewById(R.id.listView1);
if (listview == null)
System.out.println("listview null"); //this should not be null but
//it is thus the nullpointerexception
if (listview.getAdapter() == null)
{
MyListAdapter listAdapter = new MyListAdapter(getActivity(), R.layout.listview_item, list.getVenues());
listview.setAdapter(listAdapter);
}
else
{
((MyListAdapter) listview.getAdapter()).updateAdapter(list.getnames());
}
}
PagerAdapter code
public class MyPagerAdapter extends FragmentStatePagerAdapter
{
private int mCount = 1;
public MyPagerAdapter(FragmentManager fm)
{
super(fm);
// TODO Auto-generated constructor stub
}
#Override
public Fragment getItem(int position)
{
switch (position)
{
case 1:
return ResultsPagerFragment.newInstance(position);
}
return ListPagerFragment.newInstance(position);
}
#Override
public int getCount()
{
// TODO Auto-generated method stub
return mCount;
}
}
and main finally activity code
private ViewPager pager;
private MyPagerAdapter pagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
}
and later somewhere in the activity i have the code that should trigger the fillList from Fragment to do the job
Fragment frag = pagerAdapter.getItem(0); //this should give me the Fragment i want right?
((ListPagerFragment)frag).fillList(result);
What am I missing here?
Ok I found it seems like the problem was in my custom FragmentStatePagerAdapter
All I had to do is create the fragments when activity is created and put them into an ArrayList which it will be later passed to MyPagerAdapter
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
frags = new ArrayList<Fragment>();
frags.add(ListPagerFragment.newInstance(0));
frags.add(ResultsPagerFragment.newInstance(1));
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager(),frags);
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
}
And then modify the MyPagerAdapter like so:
public class MyPagerAdapter extends FragmentStatePagerAdapter
{
private List<Fragment> fragments;
public MyPagerAdapter(FragmentManager fm, List<Fragment> frags)
{
super(fm);
this.fragments = frags;
}
#Override
public Fragment getItem(int position)
{
return fragments.get(position);
}
}
kind of silly isn't it? I don't understand the point but it worked
That's probably because you are trying to use the views from your Activity, before your ListPagerFragment.onCreateView() has inflated your xml layout. Move what's inside your onCreate() and some code of fillList() to onCreateView(), something like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.list_pager_fragment, container, false);
listview = (ListView) v.findViewById(R.id.listView1);
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
pager = (ViewPager) v.findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
return v;
}
After your fragments onCreateView() has inflated the view, you can try to fill it.
And don't forget to clear your view references and unregister your listview listener(if you set one) in onDestroyView() to avoid memory leaks, e.g.
#Override
public void onDestroyView() {
super.onDestroyView();
listview.setOnItemClickListener(null);
...
listview = null;
}
read about the fragment's lifecycle --> Fragment's Lifefycle