Android Studio Section Pager Fragment Adapter - android

So I want to make an app that has multiple tabs that I can slide between.
I choose the Tabbed Acitivity with Action Bar Tabs (with ViewPager) navigation tabs.
I am trying to make each tab correspond with a fragment. So I can change the lay-out of each fragment etc.
A part of my fragment code is:
public class Page1Fragment extends Fragment {
private OnFragmentInteractionListener mListener;
public Page1Fragment() {
// Required empty public constructor
}
*This is not the complete code
In my SeciontsPagerAdapter, this is my getItem method.
#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).
// return MainActivity.PlaceholderFragment.newInstance(position + 1);
switch(position){
case 0:
return new Page1Fragment();
case 1:
return new Page2Fragment();
case 2:
return new Page3Fragment();
case 3:
return new Page4Fragment();
}
return null;
}
But I get an error? It says Page1Fragment can't be converted to a Fragment?
But I let Page1Fragment extends from Fragment?
Does anyone have any idea why this doesn't work?

Try this:
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 GamesFragment1();//.newInstance(0);
case 1:
return new GamesFragment2();//.newInstance(1);
case 2:
return new GamesFragment3();//.newInstance(2);
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
Page1Fragment:
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager.PageTransformer;

There are two fragment classes either you have to use support library class or app.fragment class. don't mix it up

You need to import below
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
Did you add this ?
import android.support.v4.app.FragmentStatePagerAdapter;
SetFragmentStatePagerAdapter instead of FragmentPagerAdapter

Related

Why FragmentStateAdapter not work in ViewPager2? [duplicate]

This question already has answers here:
Proper implementation of ViewPager2 in Android
(12 answers)
Closed 3 years ago.
Android Studio 3.6
I want in my activity to use 2 fragments inside ViewPager2.
Here my activity:
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
public class QRBluetoothSwipeActivity extends AppCompatActivity {
private ViewPager2 myViewPager2;
private ViewPagerFragmentAdapter myAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
// Make sure this is before calling super.onCreate
setTheme(R.style.AppTheme); // show splash screen
super.onCreate(savedInstanceState);
setContentView(R.layout.qr_bluetooth_swipe_activity);
init();
}
private void init() {
myAdapter = new ViewPagerFragmentAdapter(getSupportFragmentManager());
myAdapter.addFragment(new BluetoothPageFragment());
myAdapter.addFragment(new QrPageFragment());
myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
myViewPager2.setAdapter(myAdapter);
}
}
here ViewPagerFragmentAdapter
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.ArrayList;
public class ViewPagerFragmentAdapter extends FragmentStateAdapter {
private ArrayList<Fragment> arrayList = new ArrayList<>();
public ViewPagerFragmentAdapter(#NonNull FragmentManager fragmentManager) {
super(fragmentManager);
}
#NonNull
#Override
public Fragment getItem(int position) {
return arrayList.get(position);
}
public void addFragment(Fragment fragment) {
arrayList.add(fragment);
}
#Override
public int getItemCount() {
return arrayList.size();
}
}
but I get compile error:
ViewPagerFragmentAdapter is not abstract and does not override abstract method createFragment(int) in FragmentStateAdapter
How I can fix this and use FRAGMENTS in ViewPager2 ?
Thanks
FragmentStateAdapter in ViewPager2 is a little bit different than in ViewPager as follows:
Instead of implementing getCount(), implement getItemCount()
Instead of implementing getItem(int position), implement createFragment(int position)
Constructor signature is different by adding Lifecycle argument
which should be included in super as well
So replace your ViewPagerFragmentAdapter with below
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.ArrayList;
public class ViewPagerFragmentAdapter extends FragmentStateAdapter {
private ArrayList<Fragment> arrayList = new ArrayList<>();
public ViewPagerFragmentAdapter(#NonNull FragmentManager fragmentManager, #NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
public void addFragment(Fragment fragment) {
arrayList.add(fragment);
}
#Override
public int getItemCount() {
return arrayList.size();
}
#NonNull
#Override
public Fragment createFragment(int position) {
// return your fragment that corresponds to this 'position'
return arrayList.get(position);
}
}
Also make sure to import/extend the right adapter of ViewPager2
import androidx.viewpager2.adapter.FragmentStateAdapter;
UPDATE 2021
This answered the original issue of the question; However creating the FragmentStateAdapter this way is not that right generally speaking; because of:
To have a high performant ViewPager, it should keep only a few instantiated off-screen page fragments.
Keeping all the page fragments into a list is not good in terms of wasting device resources.
createFragment(), as its name implies, is intended to create a new fragment for a particular page and return it; not to return a fragment from a list that has already instantiated fragments.
Above all as per documentation createFragment()::
Provide a new Fragment associated with the specified position.
The adapter will be responsible for the Fragment lifecycle:
The Fragment will be used to display an item.
The Fragment will be destroyed when it gets too far from the
viewport, and its state will be saved. When the item is close to the
viewport again, a new Fragment will be requested, and a previously
saved state will be used to initialize it.
So, I'd suggest to change this design to include that into consideration:
Assuming your page fragment is PageFragment; then you can have single instance pattern by having static PageFragment newInstance(int position) {} method in the PageFragment, and then the createFragment() should be then:
#NonNull
#Override
public Fragment createFragment(int position) {
// return a brand new fragment that corresponds to this 'position'
return PageFragment.newInstance(position); // Create a new instance of the page fragment
}

PagerAdapter() cannot be applied to android.app FragmentManager

I tried to create a ViewPager in Android Studio.
I get the error:
PagerAdapter() cannot be applied to android.app FragmentManager
at the line super(fm);
Here is my code for the adapter. Do I need to change anything?
package com.example.admin.usthweather;
import android.app.Fragment;
import android.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.view.View;
/**
* Created by Admin on 11/15/2017.
*/
public class HomeFragmentAdapter extends PagerAdapter {
private final int PAGE_COUNT = 3;
private String titles[] = new String[] {"Hanoi","Paris", "Saigon"};
public HomeFragmentAdapter(FragmentManager fm){
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
// Override
public Fragment getItem(int page) {
// returns an instance of Fragment corresponding to the specified page
Fragment frag=null;
switch (page){
case 0:
frag=new Hanoi();
break;
case 1:
frag=new Paris();
break;
case 2:
frag=new Saigon();
break;
}
return frag;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return false;
}
}
There is no constructor in PagerAdapter with FragmentManager as parameter. You're code is similar for FragmentPagerAdapter or FragmentStatePagerAdapter so you can use one of them. It will be something like this:
public class HomeFragmentAdapter extends FragmentStatePagerAdapter {
private final int PAGE_COUNT = 3;
private String titles[] = new String[] {"Hanoi","Paris", "Saigon"};
public HomeFragmentAdapter(FragmentManager fm){
super(fm);
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int page) {
Fragment frag=null;
switch (page){
case 0:
frag=new Hanoi();
break;
case 1:
frag=new Paris();
break;
case 2:
frag=new Saigon();
break;
}
return frag;
}
}
Please remember to use the correct import file for Fragment and FragmentManager from Support library:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
fm in super(fm); is wrong. Therefore none of this is necessary:
public HomeFragmentAdapter(FragmentManager fm){
super(fm);
}
However, I suspect that you did not want to subclass PagerAdapter, but either or FragmentStatePagerAdapter. As the docs say:
Base class providing the adapter to populate pages inside of a ViewPager. You will most likely want to use a more specific implementation of this, such as FragmentPagerAdapter or FragmentStatePagerAdapter.
Instead of providing a View recycling mechanism directly ViewPager uses callbacks to indicate the steps taken during an update.

Issues with TabLayout getChildFragmentManager()

My application is working fine when I use getChildFragmentManager() but unfortunately, it will only work with API 17 and above. Now when I switch it over to getFragmentManager(), everything works fine except for one thing. Whenever I load my tablayout in horizontal view, both pages are empty and swiping is sluggish. Vertically it is fine and they won't be empty if I first load them vertically and then switch to horizontally, because I'm using a saved instance. I have no idea what is causing this. All I know is that as soon as I switch the code above around, it happens. Let me know what is required to find the issue and I will gladly post it. I am using the support-v13 library's FragmentPagerAdapter. I am doing this so I don't have to use support-v4's way of creating fragments. I do import the ViewPager from v4 in my tablayout fragment.
Edit:
Okay when the tablayout is created for the first time, it works fine. When called again it will be blank and sluggish. It had nothing to do with orientation.
Edit:
Tablayout code Keep in mind that this code is functional. But when I change getChildFragmentManager() to getFragmentManager() it gets sluggish and only works on first oncreate:
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class TabFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = 2;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View x = inflater.inflate(R.layout.tab_layout, null);
tabLayout = (TabLayout) x.findViewById(R.id.tabs);
viewPager = (ViewPager) x.findViewById(R.id.viewpager);
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return x;
}
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FragmentOne();
case 1:
return new FragmentTwo();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "TAB1";
case 1:
return "TAB2";
}
return null;
}
}
}

Swipe View and Multiple Fragments Android

I'm trying to make an application that has two fragments that are both different in function and you can swipe right to go between them. I've looked into how to do this, but no solution seems to work.
Tabs and Swipe - editing the getItem to display 3 different fragments
Im trying to implement a getitem similar to this, but as you can see in this code:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by cwallace on 11/10/14.
*/
//Implement PagerAdapter Class to handle individual page creation
class MyPagesAdapter extends FragmentPagerAdapter {
public MyPagesAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 2;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = new InitialFragment();
return fragment;
}
}
I want to return a different type of fragment than the function wants, and I can't cast my Initial Fragment to the Fragment class. Am I even attempting to do this the correct way?
Let's point out some things.
can't cast my Initial Fragment, make sure that your initialFragment class extends the Fragment.
As #hitch.united suggest, in getItem() of adapter , you can return the fragment by the id in a if-else. But remember that: You should not use this function to retrieve the fragment!
I can suggest you by using the ViewPager for swipe operation.
Try this way:
class MyPagesAdapter extends FragmentPagerAdapter {
public MyPagesAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 2;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch(position) {
case 0:
fragment = new InitialFragment();
break;
case 1:
fragment = new YourSecondFragment();
break;
}
return fragment;
}
}

Problems with FragmentPagerAdapter

I'm trying to make a slidescreen with viewpager and fragments so that I can load different layouts per fragment and give each page different functionality.
I followed a tutorial to accomplish this.
The error I'm getting when hovering over public Fragment getItem(int arg0): The return type is incompatible with FragmentPagerAdapter.getItem(int)
and error #2: The constructor FragmentPagerAdapter(FragmentManager) is undefined
--> getting this one when hovering super(fm);
package com.example.spui;
import android.os.Bundle;
import android.app.Fragment;
import android.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class MyFragmentPagerAdapter extends FragmentPagerAdapter{
final int PAGE_COUNT = 5;
/** Constructor of the class */
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
/** This method will be invoked when a page is requested to create */
#Override
public Fragment getItem(int arg0) {
MyFragment myFragment = new MyFragment();
Bundle data = new Bundle();
data.putInt("current_page", arg0+1);
myFragment.setArguments(data);
return myFragment;
}
/** Returns the number of pages */
#Override
public int getCount() {
return PAGE_COUNT;
}
}
You are using the wrong FragmentManager import. Use android.support.v4.app.FragmentManager instead.
Same problem with Fragment - use android.support.v4.app.Fragment
Note: if you are building an API11+ only application and want to use the native Fragments, then you should instead change your FragmentPagerAdapter import to android.support.v13.app.FragmentPagerAdapter.

Categories

Resources