For some reason I am getting an error when i invoke the addFrag function/method to populate my fragment and string title. I am creating a simple ViewPager with an adapter. This is all in a fragment by the way. Here is the code:
public class HomeFragment extends Fragment {
private View view;
private ViewPager viewPager;
private TabLayout tabLayout;
private PagerAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup viewGroup,
#Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.home_fragment, viewGroup, false);
viewPager = (ViewPager) view.findViewById(R.id.viewpager);
setUpViewPager(viewPager);
tabLayout = (TabLayout) view.findViewById(R.id.sliding_tabs);
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return view;
}
private void setUpViewPager(ViewPager viewPager) {
adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFrag(new ContentFragment(), "ONE");
adapter.addFrag(new ContentFragment(), "TWO");
adapter.addFrag(new ContentFragment(), "THREE");
viewPager.setAdapter(adapter);
}
}
class ViewPagerAdapter extends FragmentPagerAdapter{
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> tabTitles = new ArrayList<>();
//Default Fragment Constructor
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
public void addFrag(Fragment fragment, String title){
fragmentList.add(fragment);
tabTitles.add(title);
}
#Override
public CharSequence getPageTitle(int position){
return tabTitles.get(position);
}
}
When I try to type adapter.addFrag(new ExampleFragment(), "Hello"); I get an error cannot resolve method addFrag. Any help will be appreciated.
adapter is declared as a PagerAdapter, not a ViewPagerAdapter. Therefore the only methods you can use on adapter are the ones defined for PagerAdapter. The compiler doesn't know that adapter will actually be a ViewPagerAdapter at that point--I can tell that it will, because I saw the assignment adapter = new ViewPagerAdapter(...) up above, but the compiler isn't allowed to notice that (those are the rules of the language). Instead:
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
Use viewPagerAdapter to call your addFrag methods, and eventually assign adapter = viewPagerAdapter;.
Change private PagerAdapter adapter; to private ViewPagerAdapter adapter;
OR
Type cast adapter to ViewPagerAdapter and then call addFlag
((ViewPagerAdapter)adapter).addFlag(new ContentFragment(), "ONE");
Related
I have simple problem.. I have MainActivity.. inside it i have 5 fragments and i can move using bottom navigation bar without problem!
In first fragment (Profile) i have inside that tow fragment using Tablayout and Viewpager..
First Fragment (Friends) Second Fragment (Users)..
My problem when i run app and open (Profile) the tow fragments (Friends and Users)
Working 100% just in first time.. when i come back to other fragment using bottom bar and come back to friends or users is empty and not load !
I want attach some of my codes you will need it..
Profile Fragment:
mSectionsPageAdapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) v.findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) v.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
mSectionsPageAdapter.notifyDataSetChanged();
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapter adapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
adapter.addFragment(new FriendsFragment(), "Friends");
adapter.addFragment(new UsersFragment(), "Online");
viewPager.setAdapter(adapter);
}
SectionsPageAdapter:
public class SectionsPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}}
I try to add this in Friends Fragment and Users Fragment the problem was solved but the content duplicated in first time run only.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
}
}
SectionsPageAdapter:
public class SectionsPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}}
A possible reason for your problems could be you are mixing up FragmentManagers.
In your Activity to handle the bottom navigation you should use Activity#getSupportFragmentManager().
But for any of the Fragments inside that activity, if you want to have children/nested fragments. You should use Fragment#getChildFragmentManager().
So in your profile fragment, while populating the two tabs pager, you should pass it Fragment#getChildFragmentManager() instead of getActivity().getSupportFragmentManager()
You can use interface to solve this problem. Implement interface in your "User" & "Friend" fragments & call the interface method when your "Profile" fragments "OnCreateView" is called. You can load data when interface method is called. For reference, Please check this link:
Communicating with Other Fragments
EDIT
Sorry,you can load data without using Interface. Here is some sample code:
Profile Fragment:
ProfileFragment extends Activity {
FriendsFragment friends;
UsersFragment users;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mSectionsPageAdapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) v.findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) v.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
mSectionsPageAdapter.notifyDataSetChanged();
friends.update();
users.update();
}
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapter adapter = new
SectionsPageAdapter(getActivity().getSupportFragmentManager());
friends = new FriendsFragment();
users = new UsersFragment();
adapter.addFragment(friends, "Friends");
adapter.addFragment(users, "Online");
viewPager.setAdapter(adapter);
}
Friends Fragment:
FriendFragment extends Activity {
public void update(){
// load data
}
jest Use
ViewPagerAdapter(getChildFragmentManager())
getChildFragmentManager()
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'
so I'm working on an app that utilizes a fixed 2 tabs within a view pager. I have a RecyclerView inside of a ViewPager but the RecyclerView is not responding to horizontal swipes. I have disabled swiping to change pages within the ViewPager by overriding onInterceptTouchEvent and onTouchEvent. I've called setFocusable(false) and setFocusableInTouchMode(false) on the view pager to no avail. Any ideas?
// ViewPager code
pager = (NoSwipePager) findViewById(R.id.pager);
pager.setFocusable(false);
pager.setFocusableInTouchMode(false);
adapter = new FormTabAdapter(getSupportFragmentManager(), form, editing);
pager.setAdapter(adapter);
pager.setCurrentItem(0);
tabs = (PagerTabStrip) findViewById(R.id.tab_strip);
tabs.setTabIndicatorColor(Color.WHITE);
tabs.setBackgroundColor(Color.parseColor("#A52A2A"));
tabs.setTextColor(Color.WHITE);
// RecyclerView code
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(act);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rv.setLayoutManager(linearLayoutManager);
((SimpleItemAnimator) rv.getItemAnimator()).setSupportsChangeAnimations(false);
elementsAdapter = new ElementsAdapter(listener, act, new LinkedList<>(elements), editing);
rv.setAdapter(elementsAdapter);
ItemTouchHelper.Callback callback = new ElementTouchHelper(elementsAdapter);
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(rv);
For that you need to off viewpager swaping both are not working at same time.
Too disable swip of viewpager use below code
public class MyViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true; // default swipe enable is true
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
// true - enable swipe
// false - disable swipe
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
and use below code while using viewpager in .xml file
<package.MyViewPager
android:id="#+id/viewPager"
android:layout_height="match_parent"
android:layout_width="match_parent" />
Hope these answer helps you.
These same approach you can use use it for recyclerview also if you required in future.
Hope these help you.
You can use fragment to show RecycleView.
For example:
You will create a class Adapter to manage.
public class HomeFragmentAdapter extends FragmentPagerAdapter {
private final ArrayList<Fragment> mFragment = new ArrayList<>();
private final ArrayList<String> mFragmentTitle = new ArrayList<>();
public HomeFragmentAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
public void addFragment(Fragment fragment, String title){
mFragment.add(fragment);
mFragmentTitle.add(title);
}
#Override
public Fragment getItem(int position) {
return mFragment.get(position);
}
#Override
public int getCount() {
return mFragment.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitle.get(position);
}
}
And after that you will add more fragment which include any RecycleView you need.
public class HomeFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
Menu mMenu;
public HomeFragment(){
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
View view = inflater.inflate(R.layout.fragment_layout_home, null);
tabLayout = (TabLayout) view.findViewById(R.id.tab_home);
viewPager = (ViewPager) view.findViewById(R.id.viewpager_home);
if(viewPager != null){
setupViewPager(viewPager);
}
tabLayout.setTabMode(TabLayout.MODE_FIXED);
tabLayout.setupWithViewPager(viewPager);
return view;
}
private void setupViewPager(ViewPager viewPager){
HomeFragmentAdapter adapter = new HomeFragmentAdapter(getChildFragmentManager());
adapter.addFragment(new ExpenseFragment(), "Expense");
adapter.addFragment(new IncomeFragment(), "Income");
viewPager.setAdapter(adapter);
}
T hope it could been help you.
I have an application that has an index page which has tabs for navigation. This page has multiple children pages being implemented as fragments.
Some of my children fragment views also have tabs in them for more navigation like below
The issue i am having is when i switch from one of these fragments to the other, and return to it.The tabs on that one are recreated like so
And i'm not sure how to solve this problem as it is my first time getting this serious with tabs.
Below is my code for the top-level-tab adapter
public class indexTabAdapter extends FragmentPagerAdapter
{
private List<String> titleList;
private List<Fragment> fragmentList;
public indexTabAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> titleList)
{
super(fm);
this.fragmentList = fragmentList;
this.titleList = titleList;
}
#Override
public Fragment getItem(int position)
{
return fragmentList.get(position);
}
#Override
public int getCount()
{
return fragmentList.size();
}
#Override
public CharSequence getPageTitle(int position)
{
return titleList.get(position);
}
}
Below here is the code for the activity class managing the top-level-tabs
#Override
protected void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index_page);
pager = (ViewPager) findViewById(R.id.indexViewPager);
tabLayout = (TabLayout)findViewById(R.id.indexTabs);
prepareDataResource();
indexTabAdapter ita = new indexTabAdapter(getSupportFragmentManager(),fragmentList,titleList);
pager.setAdapter(ita);
tabLayout.setupWithViewPager(pager);
ita.notifyDataSetChanged();
}
private void prepareDataResource()
{
fragmentList.add(new dash());
titleList.add("Dash");
fragmentList.add(new AcademicCalender());
titleList.add("Calender");
fragmentList.add(new IncidentReport());
titleList.add("Incident Report");
fragmentList.add(new Profile());
titleList.add("Profile");
fragmentList.add(new Pta());
titleList.add("PTA");
fragmentList.add(new timeTable());
titleList.add("Time Table");
fragmentList.add(new Results());
titleList.add("Results");
}
Lastly, this is the code for the lower-level-tab that keeps repeating
public class Profile extends Fragment
{
private List<String> titleList = new ArrayList<>();
private List<Fragment> fragmentList = new ArrayList<>();
private ViewPager pager;
private TabLayout tabLayout;
public Profile()
{
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.profile_view_activity,container,false);
pager = (ViewPager) view.findViewById(R.id.profileViewPager);
tabLayout = (TabLayout) view.findViewById(R.id.profileTabs);
prepareDataResource();
profileTabsAdapter rta = new profileTabsAdapter(getFragmentManager(),fragmentList,titleList);
pager.setAdapter(rta);
tabLayout.setupWithViewPager(pager);
return view;
}
private void prepareDataResource()
{
fragmentList.add(new index());
titleList.add("Home");
fragmentList.add(new immunization());
titleList.add("Immunization");
fragmentList.add(new information());
titleList.add("Information");
fragmentList.add(new records());
titleList.add("Health Records");
}
}
FragmentPagerAdapter instances your fragment once. So if you instantiate your list when declaring it as a field, it will always retain that same list, thus adding elements when the Fragment's onCreateView is called.
To avoid this, declare and instantiate both lists like this:
public class Profile extends Fragment {
private List<String> titleList;
private List<Fragment> fragmentList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
//your code for views initialization
//init the lists here!
titleList = new ArrayList<>();
fragmentList = new ArrayList<>();
prepareDataResource();
//your adapter set up code
return view;
}
If you're working with ViewPager, try calling viewPager.setOffscreenPageLimit(numberOfTabs). I'm not a hundred percent sure this will work, but it won't hurt to try.
From the official Android documentation:
setOffscreenPageLimit(int limit)
Set the number of pages that should be retained to either side of the
current page in the view hierarchy in an idle state.
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);
}