I'm facing a strange problem and totally clueless about what is causing the problem.
I have one Mainactivity with pager layout where Tabs Contain two tabs "Sec A " and "Sec B".
Under Sec A and Sec B, I have another fragment with pager layout and now each contain seven Days of week to show the Time Table of Class of our university.
Now, The Problem is When app launch for first Time, If I load Sec A fragment , then it loads and fill the child fragment of seven days very well but when I click Sec B tab...then all the seven days of Sec B show white screen although I have used same layout file , database and adapter class for Both Sec A and B. If instead I load Sec B then Sec B loads but Sec A shows white screen now.
Here is the link for my whole project https://github.com/BlueYeti1881/routine
My project File Structure is
My Sec A Fragment is
and Sec B Fragment is
My Sec A Fragment class is
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_section, container, false);
ViewPager viewPager = (ViewPager) view.findViewById(R.id.pager_dayscount);
ViewPagerAdapter adapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager());
adapter.addFragment(new sunA(), "Sun");
adapter.addFragment(new monA(), "Mon");
adapter.addFragment(new tueA(), "Tue");
adapter.addFragment(new wedA(), "Wed");
adapter.addFragment(new thuA(), "Thu");
adapter.addFragment(new friA(), "Fri");
viewPager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tabs_dayscount);
tabLayout.setupWithViewPager(viewPager);
return view;
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
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 addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
which is same as B and my Adapter class is
public class AmonAdapter extends RecyclerView.Adapter<AmonAdapter.Holder> {
private static final String TAG = AmonAdapter.class.getSimpleName();
private final FlowerClickListener mListener;
private List<Flower> mFlowers;
public AmonAdapter(FlowerClickListener listener) {
mFlowers = new ArrayList<>();
mListener = listener;
}
#Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.days_item, null, false);
return new Holder(row);
}
#Override
public void onBindViewHolder(Holder holder, int position) {
Flower currFlower = mFlowers.get(position);
holder.mName.setText(currFlower.getName());
holder.mPrice.setText(String.format("$%.2f", currFlower.getPrice()));
}
#Override
public int getItemCount() {
return mFlowers.size();
}
public void addFlower(Flower flower) {
mFlowers.add(flower);
notifyDataSetChanged();
}
public void reset() {
mFlowers.clear();
notifyDataSetChanged();
}
public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mName, mPrice;
public Holder(View itemView) {
super(itemView);
mName = (TextView) itemView.findViewById(R.id.flowerName);
mPrice = (TextView) itemView.findViewById(R.id.flowerPrice);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mListener.onClick(getLayoutPosition());
}
}
public interface FlowerClickListener {
void onClick(int position);
}
}
Related
ViewPager2 is scrolling to the wrong page when I am selecting a tab from a far position. Swiping and selecting tab of loaded pages working fine. The error is only happening when the page is not loaded and scrolling animation is active. I have created a large viewpager2 with 100 pages containing Recyclerview.
My Activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = findViewById(R.id.tabLayout);
ViewPager2 viewPager = findViewById(R.id.viewPager2);
viewPager.setAdapter(new viewPagerAdapter(this));
new TabLayoutMediator(tabLayout, viewPager, true, true,
((tab, position) -> tab.setText("Page: " + position))).attach();
}
private class viewPagerAdapter extends FragmentStateAdapter {
public viewPagerAdapter(FragmentActivity fa) {
super(fa);
}
#Override
public Fragment createFragment(int position) {
Fragment fragment = new itemFragment();
Bundle args = new Bundle();
args.putInt(itemFragment.ARG_PARAM1, position);
fragment.setArguments(args);
return fragment;
}
#Override
public int getItemCount() {
return 100;
}
}
}
My Fragment
public class itemFragment extends Fragment {
public static final String ARG_PARAM1 = "parram1";
int pagePosition;
public itemFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pagePosition = getArguments().getInt(ARG_PARAM1);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frgment_item, container, false);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
TextView textView = view.findViewById(R.id.textView);
textView.setText("Page - " + pagePosition);
RecyclerView recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setAdapter(new myAdapter());
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 16));
}
private class myAdapter extends RecyclerView.Adapter<Myvh> {
#Override
public Myvh onCreateViewHolder(ViewGroup parent, int viewType) {
return new Myvh(new TextView(getContext()));
}
#Override
public void onBindViewHolder(Myvh holder, int position) {
int codepoint=pagePosition*700 + position;
char[] ch=Character.toChars(codepoint);
holder.textView.setText(String.valueOf(ch));
}
#Override
public int getItemCount() { return 700; }
}
private class Myvh extends RecyclerView.ViewHolder {
TextView textView;
public Myvh(View itemView) {
super(itemView);
textView = (TextView) itemView;
}
}
}
I have also tried Recyclerview adapter instead of FragmentStateAdapter and getting same problem.
I have found some solution but not sufficient.
Those are:
Using old ViewPager(deprecated)
Using viewPager.setOffscreenPageLimit(100); (taking huge time to load activity)
Disabling smoothscroll ( looks awful when swiping)
ViewPager2 is removing last tab instead of current tab, same problem was occurring when i was using viewpager.
Also when selected tab is last one it removes last tab correctly
dependency
implementation "androidx.viewpager2:viewpager2:1.0.0"
This is main activity code
MainActivity.java
public class MainActivity extends AppCompatActivity {
TabLayout tabLayout;
ViewPager2 viewPager;
ViewPagerAdapter adapter;
Button btnAddTab,btnRemoveCurrentTab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = findViewById(R.id.view_pager);
tabLayout = findViewById(R.id.tabs);
btnAddTab=findViewById(R.id.btn_add);
btnRemoveCurrentTab=findViewById(R.id.btn_remove);
adapter=new ViewPagerAdapter(this);
viewPager.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager,
new TabLayoutMediator.TabConfigurationStrategy() {
#Override public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
tab.setText("Store " + (position + 1));
}
}).attach();
btnRemoveCurrentTab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
adapter.removeFrag(tabLayout.getSelectedTabPosition());
}
});
btnAddTab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DynamicFragment fView = new DynamicFragment();
adapter.addFrag(fView,"Store "+(adapter.getmFragmentIdList().contains(adapter.getItemCount()+1)?adapter.getItemCount()+2:adapter.getItemCount()+1),(adapter.getmFragmentIdList().contains(adapter.getItemCount()+1)?adapter.getItemCount()+2:adapter.getItemCount()+1));
}
});
}
}
ViewPagerAdapter
This is FragentStateAdapter
public class ViewPagerAdapter extends FragmentStateAdapter {
private final List<DynamicFragment> mFragmentList = new ArrayList<>();
private final List<Integer> mFragmentIdList = new ArrayList<>();
public ViewPagerAdapter(#NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
#NonNull #Override public Fragment createFragment(int position) {
return DynamicFragment.newInstance(String.valueOf(position),mFragmentIdList.get(position));
}
public void addFrag(DynamicFragment fragment, String title, int id) {
mFragmentList.add(fragment);
Log.e("fragment id " ,""+id);
Log.e("fragment array " ,title+ mFragmentList.size());
mFragmentIdList.add(id);
notifyDataSetChanged();
}
public void removeFrag(int pos) {
Log.e("deleted frag",mFragmentIdList.get(pos)+" "+pos);
mFragmentList.remove(pos);
mFragmentIdList.remove(pos);
notifyDataSetChanged();
}
public List<Integer> getmFragmentIdList() {
return mFragmentIdList;
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override public int getItemCount() {
return mFragmentList.size();
}
}
Fragment
This is my dynamic fragment which i want to add and remove
public class DynamicFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
private static final String ARG_ID = "id";
private String sectionNumber;
int id;
TextView textView;
EditText editText1,editText2;
public DynamicFragment() {
// Required empty public constructor
}
public static DynamicFragment newInstance(String sectionNumber, int id) {
DynamicFragment fragment = new DynamicFragment();
Bundle args = new Bundle();
args.putString(ARG_SECTION_NUMBER, sectionNumber);
args.putInt(ARG_ID, id);
fragment.setArguments(args);
Log.e("StoreDynamic","dynamic new instance");
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView= inflater.inflate(R.layout.fragment_dynamic, container, false);
textView=rootView.findViewById(R.id.textView);
editText1=rootView.findViewById(R.id.et1);
editText2=rootView.findViewById(R.id.et2);
sectionNumber = getArguments().getString(ARG_SECTION_NUMBER);
id=getArguments().getInt(ARG_ID);
editText1.setText(id+" "+sectionNumber);
textView.setText(id+" "+sectionNumber);
return rootView;
}
}
I ran into the same problem and the solution to this question: remove fragment in viewPager2 use FragmentStateAdapter, but still display worked for me. Mostly the part about overriding the getItemId function to return something other than the position to identify the item because the item's position changes when adding and removing fragments.
You need to overwrite the methods getItemId() and containsItemId()
as shown in this post: https://stackoverflow.com/a/57944197/870242
items variable holds your fragment (mFragmentList )
private val pageIds= items.map { it.hashCode().toLong() }
override fun getItemId(position: Int): Long {
return items[position].hashCode().toLong() // make sure notifyDataSetChanged() works
}
override fun containsItem(itemId: Long): Boolean {
return pageIds.contains(itemId)
}
I tried to add Viewpager inside RecycleView item, then I created the adapter for the recycle view and I created a Pager Adapter that extends from FragmentStatePagerAdapter class inside the the adapter.
Just the first item of the recycle works fine, but the rest items of recycle view do not show the view pager.
When I Log inside the Pager Adapter I can see all the fragment position.
When I scroll horizontally inside any pager of any recycle view item I can see the Log statement, but nothing appear on the screen.
Could any one help me in that case ?
Here is my code
public class RentCategoryItemAdapter extends RecyclerView.Adapter<RentCategoryItemAdapter.ViewHolder> {
Context mContext;
ArrayList<RentCategoryItem> categoryItems;
ArrayList<MyPagerAdapter> pagerAdapters = new ArrayList<>();
/*ArrayList<ViewPager> pagerArrayList = new ArrayList<>();
ArrayList<MyPagerAdapter> myPagerAdapterArrayList = new ArrayList<>();*/
public RentCategoryItemAdapter(Context context, ArrayList<RentCategoryItem> categoryItems) {
mContext = context;
this.categoryItems = categoryItems;
AppCompatActivity activity = (AppCompatActivity) mContext;
for (int i = 0; i < categoryItems.size(); i++) {
pagerAdapters.add(new MyPagerAdapter(activity.getSupportFragmentManager(), categoryItems.get(i).catItems));
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemLayoutView;
itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.rent_category_item,parent, false);
RentCategoryItemAdapter.ViewHolder viewHolder = new RentCategoryItemAdapter.ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.catName.setText(categoryItems.get(position).catName);
//AppCompatActivity activity = (AppCompatActivity) mContext;
//holder.mPagerAdapter = new MyPagerAdapter(activity.getSupportFragmentManager(), categoryItems.get(position).catItems);
holder.pager.setAdapter(pagerAdapters.get(position));
Log.d("Tag", pagerAdapters.get(position).getCount() + " position " + position);
/*holder.mPagerAdapter = myPagerAdapterArrayList.get(position);
holder.pager.setAdapter(myPagerAdapterArrayList.get(position));*/
int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10*16, mContext.getResources().getDisplayMetrics());
holder.pager.setPageMargin(-margin);
}
#Override
public int getItemCount() {
return categoryItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
private PagerAdapter mPagerAdapter;
TextView catName;
ViewPager pager;
public ViewHolder(View itemView) {
super(itemView);
pager = itemView.findViewById(R.id.pager);
catName = itemView.findViewById(R.id.cat_name);
/*pagerArrayList.add(new ViewPager(mContext));
AppCompatActivity activity = (AppCompatActivity) mContext;
myPagerAdapterArrayList.add(new MyPagerAdapter(activity.getSupportFragmentManager()));*/
}
}
private class MyPagerAdapter extends FragmentStatePagerAdapter {
ArrayList<RentItem> items;
public MyPagerAdapter(FragmentManager fm, ArrayList<RentItem> items) {
super(fm);
this.items = items;
}
#Override
public Fragment getItem(int position) {
Fragment fragment = new RentCategoryForPagerFragment();
Bundle bundle = new Bundle();
bundle.putString("first_last", "first");
bundle.putString("product_id", items.get(position).productId);
bundle.putString("product_name", items.get(position).productName);
bundle.putString("product_price", items.get(position).productPrice);
bundle.putString("product_image", items.get(position).productImage);
fragment.setArguments(bundle);
Log.d("Tag", "inside my pager adapter " + position);
return fragment;
}
#Override
public int getCount() {
return items.size();
}
}
}
And here is RentCategoryForPagerFragment class
public class RentCategoryForPagerFragment extends Fragment {
String firstOrLast = "";
ImageView productImage;
TextView productName, productPrice;
String productId;
Button showDetailsButton;
public RentCategoryForPagerFragment() {
//firstOrLast = getArguments().getString("first_last");
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.rent_item_in_category_layout, container, false);
productImage = rootView.findViewById(R.id.product_image);
productName = rootView.findViewById(R.id.product_name);
productPrice = rootView.findViewById(R.id.product_price);
showDetailsButton = rootView.findViewById(R.id.show_details_button);
Bundle bundle = getArguments();
String imageURL = bundle.getString("product_image");
Glide.with(getActivity()).load(imageURL).into(productImage);
productId = bundle.getString("product_id");
productName.setText(bundle.getString("product_name"));
productPrice.setText(bundle.getString("product_price"));
showDetailsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), "Clicked ", Toast.LENGTH_LONG).show();
}
});
return rootView;
}
}
The result I got in this
Finally I found the solution. I was using the wrong class because it sound that FragmentStatePagerAdapter and FragmentPagerAdapter Classes do not serve my idea.
So You should extend from PagerAdapter instead to implement more than one pager in the same screen. And you should override some methods to complete it.
I hope this answer helps someone in someday.
I wanted to use recyclerview inside a fragment of my 3 fragment viewpager. I wrote the code and it ran perfectly but I don't know why it is too slow.When I swap from one fragment to another it almost takes half minute.Don't know what mistakes I did here.
Main Activity
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar)findViewById(R.id.toolBar);
tabLayout = (TabLayout)findViewById(R.id.tabs);
viewPager = (ViewPager)findViewById(R.id.viewPager);
setSupportActionBar(toolbar);
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPagerAdapter.addFragment(new OneFragment(), "One");
viewPagerAdapter.addFragment(new TwoFragment(), "Two");
viewPagerAdapter.addFragment(new ThreeFragment(), "Three");
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
}
Here it is one of my fragment where I tried to implement recyclerview.
Fragment
public class TwoFragment extends Fragment {
public TwoFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_two, container, false);
OurData ourData = new OurData();
ourData.pic.add(R.drawable.b);
ourData.title.add("Hello");
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.listRecyclerView);
ListAdapter listAdapter = new ListAdapter();
recyclerView.setAdapter((listAdapter));
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
return view;
}
}
public class ListAdapter extends RecyclerView.Adapter {
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ListViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((ListViewHolder) holder).bindView(position);
}
#Override
public int getItemCount() {
return OurData.title.size();
}
private class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView text;
private ImageView image;
public ListViewHolder(View itemview) {
super(itemview);
text = (TextView) itemview.findViewById(R.id.textF);
image = (ImageView) itemview.findViewById(R.id.imageF);
itemview.setOnClickListener(this);
}
public void bindView(int position) {
text.setText(OurData.title.get(position));
image.setImageResource(OurData.pic.get(position));
}
public void onClick(View view) {
}
}
}
public class OurData {
public static ArrayList<String> title = new ArrayList<String>();
public static ArrayList<Integer> pic = new ArrayList<Integer>();
}
It tooks my whole day thinking what I did wrong. Please help me out!
set your adapter recyclerView.setAdapter((listAdapter));
insise onViewCreated instead of onCreateView
I think the problem is because of one of your Methods.
maybe 'OurData'
and also are you sure of this:
#Override
public int getItemCount() {
return OurData.title.size();
}
also try using Log in each code and see the part that takes time especially 'OurData'
I have a ViewPager with fragments in my activity, each page has a textview, I want to change the text of the textview from the onCreate method in the activity that contains the viewpager. How should I go about doing that?
below is the code that would return a null object exception:
Fragment:
public class MyFragment extends Fragment {
private TextView textView;
public static MyFragment getInstance(){
return new MyFragment();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_layout, container, false);
textView = (TextView) rootView.findViewById(R.id.textView);
return rootView;
}
public void setText(String text){
textView.setText(text);
}
}
Adapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return MyFragment.getInstance();
}
#Override
public int getCount() {
return 3;
}
}
Activity onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
final ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
MyFragment fragment = (MyFragment) adapter.getItem(0);
fragment.setText("Altered"); // and this returns null pointer exception
}
Thank you!
Most FragmentPagerAdapters will have an addFragment method and will keep track various fragments that are added to it via an internal object:
public class MyPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragments = new ArrayList<>();
private final List<String> mFragmentTitles = new ArrayList<>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
public void addFragment(Fragment fragment, String title) {
mFragments.add(fragment);
mFragmentTitles.add(title);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitles.get(position);
}
}
As it stands, your implementation of getItem returns a new instance of MyFragment every time it is called. As such, MyFragment fragment = (MyFragment) adapter.getItem(0); is a new instance that will never be loaded into the ViewPager, will never be inflated, and hence has a null textView reference.
The other issue is that within the onCreate of your activity, the fragments have not yet been inflated, so the textView will be null unless you delay the call:
final MyFragment fragment = (MyFragment) mPagerAdapter.getItem(0);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
fragment.setText("Altered");
}
}, 100);
But really, why not just set it to the correct value when it is initialized?
Try This
Fragment:
public class MyFragment extends Fragment {
private TextView textView;
private String Text;
public MyFragment (String Text){
this.Text=Text;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_layout, container, false);
textView = (TextView) rootView.findViewById(R.id.textView);
textView.setText(Text);
return rootView;
}
}
Adapter :
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return new MyFragment("Altered");
}
#Override
public int getCount() {
return 3;
}
}
Activity onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
final ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
}