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.
Related
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
}
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.
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
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;
}
}
I've done some research on this already, and I seem to understand the solutions suggested out there. This is not a repeat question, I'm just having trouble implementing these solutions to my viewpager/fragment code.
So here is my "FirstFragment.java" that sets up my view pager, and the fragment it calls is "UserFragment.java". Basically what I'm doing is providing a user defined number of forms created as pages in my view pager.
I of course, am experiencing the orientation change issue, where fragment gets created a couple times, and eventually lost. I would like to fix it.
My code for FirstFragment.java is:
import java.util.ArrayList;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.util.SparseArray;
public class FirstFragment extends FragmentActivity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_viewpager);
// Check whether the activity is using the layout version with
// the fragment_container FrameLayout. If so, we must add the first fragment
int size = getIntent().getExtras().getInt("numass1");
ViewPager vp = (ViewPager) findViewById(R.id.viewPager);
if (savedInstanceState != null) {
return;
}
ArrayList<Fragment> lf = new ArrayList<Fragment>();
for(int count=0; count<size; count ++){
Fragment f = new UserFragment();
lf.add(f);
}
FragmentAdapter hello = new FragmentAdapter(getSupportFragmentManager() , lf);
vp.setAdapter(hello);
}
SparseArray<Question> questions = new SparseArray<Question>();
public void saveData(Question quest){
ViewPager vp = (ViewPager) findViewById(R.id.viewPager);
questions.put(vp.getCurrentItem(), quest);
}
public ViewPager getPager() {
ViewPager vp = (ViewPager) findViewById(R.id.viewPager);
return vp;
}
}
Just incase, my FragmentAdapter.java code is:
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.ViewGroup;
public class FragmentAdapter extends FragmentPagerAdapter{
private List<Fragment> fragments;
public FragmentAdapter(FragmentManager fragmentManager, ArrayList<Fragment> fragments) {
super(fragmentManager);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = fragments.get(position);
Bundle args = new Bundle();
args.putInt("page_position", position + 1);
args.putInt("size", fragments.size());
fragment.setArguments(args);
return fragment;
}
#Override
public void destroyItem (ViewGroup container, int position, Object object)
{
super.destroyItem(container, position, object);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
Please keep in mind, I am clearly a noob, and I'm trying to learn. So code snippets, and explanations would be awesome!
Thank you very much for your time and help.
EDIT: Please help ...
If you add
android:configChanges="orientation|keyboardHidden"
in <activity> node of your file AndroidManifest.xml your activity will not reset when the orientation changed.
Is it what you wanted?