I have a ViewPager and I'm using FragmentStatePagerAdapter to hold my fragments. Now the problem is that when I slide the OnCreateView and OnCreate of the Fragments are called everytime and I make network calls in the Fragments which will be called again and again causing lag.
I have copied from here
How to Avoid calling the OnCreateView and OnCreate of the Fragments.
Here's my code:
FragmentHolder.class
public class ViewPagerAdapter extends SmartFragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
private final ArrayList<Fragment> mFragments = new ArrayList<>();
private long baseId = 0;
private String tabTitles[] = new String[] { "HOME", "DISCOVER", "MESSAGES" };
private Context context;
private TabLayout tabLayout;
public int[] imageResId = {
R.drawable.ic_ac_unit_black_24dp,
R.drawable.ic_airport_shuttle_black_24dp,
R.drawable.ic_all_inclusive_black_24dp
};
public ViewPagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
if(position == 0)
{
Log.d("Fragment","1");
return FragmentOne.newInstance(position + 1);
}
else if(position == 1)
{
Log.d("Fragment","2");
return FragmentTwo.newInstance(position + 2);
}
else if(position == 2)
{
Log.d("Fragment","3");
return FragmentThree.newInstance(position + 3);
}
return new Fragment();
}
#Override
public CharSequence getPageTitle(int position)
{
Drawable image = ContextCompat.getDrawable(context, imageResId[position]);
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
SpannableString sb = new SpannableString(" ");
ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}
}
MainActivity:
lockableViewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(),
Dashboard.this));
lockableViewPager.setSwipeable(false);
lockableViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if (position == 0) {
fragmentOne.message();
} else if (position == 1) {
fragmentTwo.message();
} else if (position == 2) {
fragmentThree.message();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Yes, using the setOffscreenPageLimit to 3 (depending on the no of fragments you have), allows you to retain the Fragments (not calling on CreateView)
lockableViewPager.setOffscreenPageLimit(3);
Related
I'm trying to use viewpager2 in fragment and make each pages clickable.
But all solutions are not working for me.
I tried to make ListPageAdapter to extend RecyclerView.ViewHolder and custom viewHolder by using onCreateViewHolder and onBindViewHolder like recyclerView but it already extended FragmentStateAdapter for making fragment.
How can i make it clickable?
Here is my code
ListPageAdapter.java
public class ListPageAdapter extends FragmentStateAdapter {
public int mCount;
private LayoutInflater mInflate;
private OnListItemClickListener listener;
public ListPageAdapter(FragmentActivity fa, int count) {
super(fa);
mCount = count;
}
#NonNull
#Override
public Fragment createFragment(int position) {
int index = getRealPosition(position);
if(index==0) return new Swipe1();
else if(index==1) return new Swipe2();
else if(index==2) return new Swipe3();
else if(index==3) return new Swipe4();
else return new Swipe5();
}
#Override
public int getItemCount() {
return 2000;
}
public int getRealPosition(int position) { return position % mCount; }
}
TextSearch.java
public class TextSearch extends AppCompatActivity {
private Button submitBtn;
private CircleIndicator3 mIndicator;
private ViewPager2 mPager;
private FragmentStateAdapter pagerAdapter;
private int num_page = 5;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_search);
submitBtn = findViewById(R.id.submitBtn);
//ViewPager2
mPager = findViewById(R.id.viewpager);
//Adapter
pagerAdapter = new ListPageAdapter(this, num_page);
//Indicator
mIndicator = findViewById(R.id.indicator);
//ViewPager Setting
mPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
mPager.setCurrentItem(1000);
mPager.setOffscreenPageLimit(3);
mPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (positionOffsetPixels == 0) {
mPager.setCurrentItem(position);
}
}
#Override
public void onPageSelected(int position) {
super.onPageSelected(position);
mIndicator.animatePageSelected(position % num_page);
}
});
final float pageMargin = getResources().getDimensionPixelOffset(R.dimen.pageMargin);
final float pageOffset = getResources().getDimensionPixelOffset(R.dimen.offset);
mPager.setPageTransformer(new ViewPager2.PageTransformer() {
#Override
public void transformPage(#NonNull View page, float position) {
float myOffset = position * -(2 * pageOffset + pageMargin);
if (mPager.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
if (ViewCompat.getLayoutDirection(mPager) == ViewCompat.LAYOUT_DIRECTION_RTL) {
page.setTranslationX(-myOffset);
} else {
page.setTranslationX(myOffset);
}
} else {
page.setTranslationY(myOffset);
}
}
});
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPager.setAdapter(pagerAdapter);
mIndicator.setViewPager(mPager);
mIndicator.createIndicators(num_page, 0);
String sendText = textLine.getText().toString();
Log.d("calling", sendText);
FileUploadUtils.sendText(sendText);
}
});
}
}
You can use the same approach as for a common fragments. In Fragment(page of a pager) Override onAttach method and implement it like this.
#Override
public void onAttach(#NotNull Context context) {
super.onAttach(context);
try {
pageClickListener = ((PageClickListener) context);
} catch (Exception e) {
Log.e("SwipeFragment", "Root activity must implement PageClickListener");
}
}
And a root activity have to implement your listener.
public class MainActivity implements PageClickListener
I am trying to set infinite view Pager(circular Scroll-able tab) using Infinite ViewPager but when I tried to set the adapter
1.It work only from the end side (last Position).
2.It is not working on the start(position 0) side.
3.It repeat the last fragment when scrolled further.
My adapter
private InfiniteViewPager pager = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pager = (InfiniteViewPager) findViewById(R.id.pager);
FragmentManager fragmentManager = getSupportFragmentManager();
pager.setAdapter(new MyAdapter(fragmentManager));
pager.setPageTransformer(true, new CubeOutTransformer());
pager.setCurrentItem(2);
}
My adapter class
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
public int getActualPosition(int i){
return i < 5? i : 0;
}
#Override
public Fragment getItem(int i) {
Fragment fragment = null;
i = getActualPosition(i);
if (i == 0) {
fragment = new Albums();
}
if (i == 1) {
fragment = new Artists();
}
if (i == 2) {
fragment = new Songs();
}
if (i == 3) {
fragment = new Genres();
}
if (i == 4) {
fragment = new Playlists();
}
return fragment;
}
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
#Override
public CharSequence getPageTitle(int position) {
String title = new String();
if (position == 0) {
return "ALBUMS";
}
if (position == 1) {
return "ARTISTS";
}
if (position == 4) {
return "PLAYLIST";
}
if (position == 3) {
return "GENRES";
}
if (position == 2) {
return "SONGS";
}
return title;
}
}
I have gone through Infinite Pager Adapter and Mine pager adapter
but when I try to set the adapter inside another adapter I am getting an error in my adapter class.
where I am doing wrong and how I can fix the scrolling from both starting and ending.
You should set adapter like this
MyAdapter adapter=new MyAdapter(fragmentManager);
InfinitePagerAdapter myAdapter= new InfinitePagerAdapter(adapter);
pager.setAdapter(myAdapter);
Also in your adapter change this code
from this
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
to
#Override
public int getCount() {
return 5;
}
I am using TabLayout with ViewPager (fragmented webview) to get a tabbed browser. The issue I am facing is my app crashes when I remove any tab expect the first and the last tab from tabbed layout.
In this case we are also removing linked Fragment from ViewPager which contains the WebView.
After that again we add multiple tabs and removes then the app crash.
The Add function
private void addViewPagerAndTab(String tag) {
mTabTags.add(tag);
MyFragment browserWebviewFragment = new MyFragment();
Bundle bundle = new Bundle();
String timestamp = System.currentTimeMillis() + "";
bundle.putString("timestamp", timestamp);
browserWebviewFragment.setArguments(bundle);
adapter.addFrag(browserWebviewFragment, "TAB " + countTabHeading, "TAB " + countTabHeading, timestamp);
countTabHeading++;
if (adapter != null) {
adapter.notifyDataSetChanged();
}
tabLayout.setupWithViewPager(viewPager);
tabLayout.setScrollPosition(((mTabTags.size()) + 1), 0f, true);
viewPager.setCurrentItem(((mTabTags.size()) + 1));
setupTabIcons();
}
The Remove Function
private void removeTabs() {
int position = tabLayout.getSelectedTabPosition();
if (deleteTabPosition > position) {
mTabTags.remove(deleteTabPosition);
tabLayout.removeTabAt(deleteTabPosition);
adapter.removeViewPagerView(deleteTabPosition);
} else if (deleteTabPosition < position) {
mTabTags.remove(deleteTabPosition);
tabLayout.removeTabAt(deleteTabPosition);
adapter.removeViewPagerView(deleteTabPosition);
tabLayout.setScrollPosition(position - 1, 0f, true);
viewPager.setCurrentItem(position - 1);
} else {
int tabCount = tabLayout.getTabCount();
if (tabCount > position + 1) {
mTabTags.remove(deleteTabPosition);
tabLayout.removeTabAt(deleteTabPosition);
adapter.removeViewPagerView(deleteTabPosition);
tabLayout.setScrollPosition(position, 0f, true);
viewPager.setCurrentItem(position);
} else if (tabCount <= position + 1) {
mTabTags.remove(deleteTabPosition);
tabLayout.removeTabAt(deleteTabPosition);
adapter.removeViewPagerView(deleteTabPosition);
tabLayout.setScrollPosition(position - 1, 0f, true);
viewPager.setCurrentItem(position - 1);
}
}
}
The ViewPager Adapter
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<TabInfo> mFragmentTitleList = new ArrayList<TabInfo>();
private int deleteTabPosition = -1;
class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title, String url, String timestamp) {
mFragmentList.add(fragment);
TabInfo infoTab = new TabInfo();
infoTab.setStrTabName(title);
infoTab.setStrTabUrl(url);
infoTab.setTimestamp(timestamp);
mFragmentTitleList.add(infoTab);
}
#Override
public int getItemPosition(Object object) {
Fragment fragmentTemp = (Fragment) object;
if (mFragmentList.contains(fragmentTemp)) {
return mFragmentList.indexOf((Fragment) object);
} else {
return POSITION_NONE;
}
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position).getStrTabName();
}
public View getTabView(final int position) {
View v = LayoutInflater.from(MainActivity.this).inflate(R.layout.tab_bg, null);
TextView tv = (TextView) v.findViewById(R.id.tvTab);
tv.setText(mFragmentTitleList.get(position).getStrTabName());
final ImageView img = (ImageView) v.findViewById(R.id.ic_tab_close);
img.setImageResource(R.drawable.ic_tab_close);
img.setTag(mFragmentTitleList.get(position).getTimestamp());
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String strTag = (String) v.getTag();
deleteTabPosition = -1;
if (mFragmentTitleList != null) {
for (int i = 0; i < mFragmentTitleList.size(); ++i) {
if (mFragmentTitleList.get(i).getTimestamp().equals(strTag)) {
deleteTabPosition = i;
break;
}
}
}
if (tabLayout.getTabCount() != 1) {
removeTabs();
} else {
}
}
});
return v;
}
/*
* Remove the View pager page associated with Tab
* */
public void removeViewPagerView(int position) {
mFragmentList.remove(position);
mFragmentTitleList.remove(position);
this.notifyDataSetChanged();
}
}
Full sourcecode on following link
http://45.33.27.221/CustomTabNoida.zip
java.lang.IllegalStateException: Fragment already active
at android.support.v4.app.Fragment.setInitialSavedState(Fragment.java:574)
at android.support.v4.app.FragmentStatePagerAdapter.instantiateItem(FragmentStatePagerAdapter.java:110)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:870)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1054)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:552)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:514)
at android.support.v4.view.ViewPager.dataSetChanged(ViewPager.java:946)
at android.support.v4.view.ViewPager$PagerObserver.onChanged(ViewPager.java:2910)
at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
at android.support.v4.view.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:276)
at com.sourcefuse.sns.views.Activities.HomeScreenActivity.addViewPagerAndTab(HomeScreenActivity.java:603)
at com.sourcefuse.sns.views.Activities.HomeScreenActivity.onClick(HomeScreenActivity.java:525)
at android.view.View.performClick(View.java:5204)
at android.view.View$PerformClick.run(View.java:21153)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
MainActivity(extends fragmentActivity) has listview which calls listviewadapter within which have a ViewPager with ViewpagerAdapter now if i need to generate 5 fragments within ViewPager how to pass getFragmentManager() to adapter.
MainActivity [fragmentActivity] ----> Listview ----> ListviewAdapter[Custom BaseAdapterAdapter with getview of layout ViewPager] ---> ViewPager ---> ViewPageAdapter[i need to create 5 fragments based on position?]
It will be too long if i paste the whole code so i have attached only
public class ViewPagerAdapter extends PagerAdapter {
ArrayList<ModelClass> arrayModelClasses = new ArrayList<ModelClass>();
Context mcontext ;
LinearLayout layouttest;
final int PAGE_COUNT = 5;
private String titles[] = new String[] { "Villa ","", "" ,"","",""};
private int[] imageResId = { R.drawable.transparant,R.drawable.ic_action_place, R.drawable.icon_3d1,
R.drawable.icon_flooplan,R.drawable.icon_gallery,R.drawable.icon_location };
#SuppressLint("NewApi")
#Override
public void finishUpdate(ViewGroup container) {
// TODO Auto-generated method stub
super.finishUpdate(container);
}
public ViewPagerAdapter(ArrayList<ModelClass> arrayModelClasses , Context context) {
super();
this.arrayModelClasses = arrayModelClasses;
this.mcontext= context;
}
#Override
public boolean isViewFromObject(View collection, Object object) {
return collection == ((View) object);
}
View view;
#Override
public Object instantiateItem(View collection, int position) {
if (position == 0) {
//need to call fragment 1
}if (position == 1) {
//need to call fragment 2
}if (position == 2) {
//need to call fragment 3
}if (position == 3) {
//need to call fragment 4
}if (position == 4) {
//need to call fragment 5
}
return view;
}
#Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
#Override
public CharSequence getPageTitle(int position) {
Drawable image = mcontext.getResources().getDrawable(imageResId[position]);
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
SpannableString sb = new SpannableString(" " + titles[position] );
ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
}
link but it uses FragmentPagerAdapter for viewPager and passed the getSupportFragmentManager from FragmentActivity but its not possible with 2 adapters so help.
Question: How to create fragment within viewPager which is inside listview. sorry if its confusing.
Thanks,
Considering you did not post your ListView Adapter I'll assume you extend BaseAdapter (either way it'll be similar). On the getView(...) method instantiate a new ViewPagerAdapter and set it to the PagerAdapter defined in the list item xml.
Note: having a ViewPager inside the ListView (and specially while loading the items that way) could cause low performance.
I've attached fragments inside ViewPager with the code as follows
public class IntroslideActivity extends FragmentActivity {
private static int NUM_PAGES = 5;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_introslide);
mPager = (ViewPager) findViewById(R.id.pager);
/**
* A simple pager adapter that represents 5 {#link ScreenSlidePageFragment} objects, in
* sequence.
*/
private class ScreenSlidePagerAdapter extends FragmentPagerAdapter{
protected final int[] ICONS = new int[] {
R.drawable.ic_message,
R.drawable.ic_phone,
R.drawable.ic_message,
R.drawable.ic_message,
R.drawable.ic_message
};
public ScreenSlidePagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
android.support.v4.app.Fragment frm = null;
System.out.println("scrolling position"+position);
if(position==0){
frm=ScreenSlidePageFragment.create(position);
}
else if(position==1){
frm=Screenslidetwo.create(position);
}
else if(position==2){
frm=Screenslidethree.create(position);
}
else if(position==3){
frm=Screenslidefour.create(position);
}
else if(position==4){
frm=Screenslidefive.create(position);
}
return frm;
}
#Override
public int getCount() {
return NUM_PAGES;
}
public void setCount(int count) {
if (count > 0 && count < 5) {
NUM_PAGES = count;
notifyDataSetChanged();
}
}
}
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
}
I have a viewpager and in that viewpager i have 6 pages.All of the pages contains listviews.Sometimes viewpager shows wrong pages at wrong indexes.Here is my viewpager adapter:
public class TestFragmentAdapter extends FragmentPagerAdapter{
protected static final String[] CONTENT = new String[] { "a","b","c","d","e","f" };
private int mCount = CONTENT.length;
Fragment fragment1,fragment2,fragment3,fragment4,fragment5,fragment6;
public TestFragmentAdapter(FragmentManager fm) {
super(fm);
fragment1 = new CategoryListView();
fragment2 = CustomizedListviewRecent.newInstance(41);
fragment3 = CustomizedListviewMostRecents.newInstance(0);
fragment4 = CustomizedListviewPopulars.newInstance();
fragment5 = CustomizedListviewRecent.newInstance(42);
fragment6 = CustomizedListviewRecent.newInstance(43);
}
#Override
public Fragment getItem(int position) {
if(position == 0)
return fragment1;
else if(position == 1)
return fragment2;
else if(position == 2)
return fragment3;
else if(position == 3)
return fragment4;
else if(position == 4)
return fragment5;
else
return fragment6;
}
#Override
public int getCount() {
return mCount;
}
#Override
public CharSequence getPageTitle(int position) {
return TestFragmentAdapter.CONTENT[position % CONTENT.length];
}
public void setCount(int count) {
if (count > 0 && count <= 10) {
mCount = count;
notifyDataSetChanged();
}
}
}
Here is how i create my viewpager:
public class SampleTitlesDefault extends BaseSampleActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mAdapter = new TestFragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TitlePageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
mIndicator.setCurrentItem(1);
}
}
Thanks for your help
try this:
public class TestFragmentAdapter extends FragmentPagerAdapter{
protected static final String[] CONTENT = new String[] { "a","b","c","d","e","f" };
ArrayList<Fragment> fragments;
public TestFragmentAdapter(FragmentManager fm) {
super(fm);
fragments.add(new CategoryListView());
fragments.add(CustomizedListviewRecent.newInstance(41));
fragments.add(CustomizedListviewMostRecents.newInstance(0));
fragments.add(CustomizedListviewPopulars.newInstance());
fragments.add(CustomizedListviewRecent.newInstance(42));
fragments.add(CustomizedListviewRecent.newInstance(43));
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return TestFragmentAdapter.CONTENT[position % CONTENT.length];
}
}
this mIndicator.setCurrentItem(1);
must replace by this mPager.setCurrentItem(1);