I've been trying something..unique..recently. Due to hierarchical levels of the app requiring multiple nav drawers, which isn't very good UX, I've been trying to add a ViewPager in the nav drawer which pages to show the list for the lower level in the hierarchy
Unfortunately, this doesn't seem to be working. Neither does it page, nor does it show an overscroll, indicating more fragments. Its not an Adapter problem, since all ViewPagers in the app are using the same adapter
Adapter
class AdapterClass extends FragmentStatePagerAdapter
{
List<Fragment> mFragments;
public AdapterClass(FragmentManager mFragManager, List<Fragment> mFragment)
{
super(mFragManager);
this.mFragments = mFragment;
}
#Override
public int getCount()
{
return mFragments.size();
}
#Override
public Fragment getItem(int position)
{
return mFragments.get(position);
}
}
Fragments (both fragments are same, save for the list text)
public class NavPagerFragMain extends SherlockFragment
{
View view;
ListView mList;
private ArrayList<String> mItems = new ArrayList<String>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.nav_pager_frag_main, container, false);
mList = (ListView)view.findViewById(R.id.nav_pager_frag_main);
mItems.add("Read");
mItems.add("Implement");
mItems.add("Design");
mItems.add("Download");
mItems.add("Connect");
mItems.add("Watch");
UserAdapter mAdapter = new UserAdapter(getActivity().getApplicationContext(), mItems);
mList.setAdapter(mAdapter);
return view;
}
Activity where I initialize and setup the ViewPager
mDrawer = (DrawerLayout)findViewById(R.id.app_drawer);
mDrawerItem = (ViewPager)findViewById(R.id.app_drawerpager);
List<Fragment> mInitFrags = new ArrayList<Fragment>();
mInitFrags.add(Fragment.instantiate(getApplicationContext(), NavPagerFragMain.class.getName()));
mInitFrags.add(Fragment.instantiate(getApplicationContext( ), NavPagerFragSub.class.getName()));
mAdapter = new AdapterClass(getSupportFragmentManager(), mInitFrags);
mDrawerItem.setAdapter(mAdapter);
mDrawerItem.setPageTransformer(true, new DepthPageTransformer());
Is your main Activity where you setup the ViewPager also a Fragment? If so, rather than pass the result of getSupportFragmentManager() to your adapter's constructor, pass it the result of the base fragment's getChildFragmentManager() call. In this scenario, you are effectively embedding Fragments within other fragments and the pager needs the child fragment manager to transition and deal with the children. Good luck!
Related
Scenarios:
I have a Fragment with a ViewPager, that it has a FragmentPagerAdapter that provides 3 Fragments.
So the first time my application loads, the 3 tab fragments looks just fine.
When I navigate in the application, i do a FragmentManager.replace to load another fragment.
When i go back, or navigate to the Main View (the tabbed View) my first and second tabs are blank.
I debugged the app, and the Fragment.onDestroyView never gets call on the Tab fragment, so when it shows again, the Fragment.onCreateView never gets called again, so my view is blank.
If I navigate to the third Tab in the Tabbed Fragment, then the Fragment.onDestroy gets called by the PageAdapter (i supposed because of the 1 offLimit on the ViewPager)
So, my question is, once another Fragment is loaded in my Activity, and then i go back, or navigate to the Tabbed View, how can i force the ViewPager, or the PageAdapter, or even the Fragment itself to be recreated.
So far i try to do a FragmentManager.remove(fragment) with the TabView without any look, also, every time, i navigate to the Tabbed View i pass a new instance to the FragmentManager.replace method, it seems that every time, he pulls the same object from the FragmentManager.
TabView (Fragment):
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.tab_view, container, false);
viewPager = (ViewPager) view.findViewById(R.id.view_iam);
final PagerAdapter pagerAdapter = new MyFragmentAdapter(getActivity().getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
return view;
}
PageAdapter:
private static class MyFragmentAdapter extends FragmentPagerAdapter {
private Fragment[] tabs;
private String[] names;
public MyFragmentAdapter(FragmentManager fm) {
super(fm);
tabs = new Fragment[]{new FlightsView(), new MyFlightsRequestView(),
new MyFlightsView()};
names = new String[]{"VUELOS", "SOLICITUDES", "MIS VUELOS"};
}
#Override
public Fragment getItem(int position) {
return tabs[position];
}
#Override
public int getCount() {
return tabs.length;
}
#Override
public String getPageTitle(int position) {
return names[position];
}
}
FlightsView (One of the Tab Fragments)
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.view_flight, container, false);
recycle_view = (RecyclerView) view.findViewById(R.id.recycler_view);
progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
setHasOptionsMenu(true);
return view;
}
Can you please try to extend your adapter from FragmentStatePagerAdapter instead of FragmentPagerAdapter
I have this Layout:
1) An AppCompatActivity with a ToolBar and a fragment container
2) Some simple Fragments
3) A Fragment that coantains TabLayout with ViewPager
When i use the fragments that are supposed to be used on the tabs the fragments are showing nicely.
One of the fragments that are supposed to be on the tabs has inside a ViewPager.
This is how i try to implement the TabLayout inside the Fragment
The Fragment with the TabLayout and the ViewPager:
public class StaffProfileFragment : Fragment
{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your fragment here
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Use this to return your custom view for this Fragment
// return inflater.Inflate(Resource.Layout.YourFragment, container, false);
var view = inflater.Inflate(Resource.Layout.StaffProfilesWithTabs, container, false);
var fragments = new Fragment[]
{
new StaffList(),
new MessagesFragment(),
new SuggestionsMessagesFragment()
};
var titles = CharSequence.ArrayFromStringArray(new[]
{
"Profile",
"Thanks",
"Suggestions"
});
var viewPager = view.FindViewById<ViewPager>(Resource.Id.ProfileViewpager);
viewPager.Adapter = new TabsFragmentPagerAdapter(ChildFragmentManager, fragments, titles);
//var myActivity = (MainActivity)this.Activity;
//myActivity.SetActionBarTitle("Select Your Location");
// Give the TabLayout the ViewPager
var tabLayout = view.FindViewById<TabLayout>(Resource.Id.SlidingTabsTabLayout);
tabLayout.SetupWithViewPager(viewPager);
return view;
}
}
}
And the Adapter i use:
public class TabsFragmentPagerAdapter : FragmentPagerAdapter
{
private readonly Fragment[] fragments;
private readonly ICharSequence[] titles;
public TabsFragmentPagerAdapter(FragmentManager fm, Fragment[] fragments, ICharSequence[] titles) : base(fm)
{
this.fragments = fragments;
this.titles = titles;
}
public override int Count
{
get
{
return fragments.Length;
}
}
public override Fragment GetItem(int position)
{
return fragments[position];
}
public override ICharSequence GetPageTitleFormatted(int position)
{
return titles[position];
}
}
(Im putting only this code for now if it is enough for the problem to be solved, else i will put the xmls and the Fragments code.)
The problem is that the fragment appears but it doesnt load the data correctly, tha tabs cannot be swyped and if i click on the fragment somewhere the app crash with crushing in Debugger.
What am i doing wrong? is it bad idea to implement tablayout inside a fragment? maybe i should implement it on the AppCompatActivity and show/hide the elements i want to use on every occasion?
Two solutions that work as i have test them are:
Create a seperate Activity with toolbar and tabhost.
In the activity with the toolbar to add tabhost and when i want to show only one fragment, i would use tabhost and set visibility to gone.
But im trying to understand which is the best way to do this,
Thanks
I have an app with ViewPager that contains 4 Classes extends Fragment. i've follow tutorials on internet, but now i have occurred in a strange problem.
This is constructor of fragment adapter:
public class FragmentAdapter extends FragmentPagerAdapter {
private final int PAGE_COUNT = 4;
TableFragment table_fragment;
MixFragment mix_fragment;
HumFragment hum_fragment;
TempFragment temp_fragment;
public FragmentAdapter(FragmentManager fm) {
super(fm);
Log.i("AAAAAA", "FragmentAdapter constructor");
table_fragment = new TableFragment();
mix_fragment = new MixFragment();
hum_fragment = new HumFragment();
temp_fragment = new TempFragment();
}
and this is one of the fragment compose ViewPager (the others look similar):
public class TableFragment extends Fragment {
MainActivity main;
ListView list_view;
ArrayAdapter<String> adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tab_layout, container, false);
list_view = (ListView) v.findViewById(R.id.list_view);
adapter = new ArrayAdapter<String>(v.getContext(),
android.R.layout.simple_list_item_1);
list_view.setAdapter(adapter);
return v;
}
Now, i've noticed that, after in my mainactivity i create a new FragmentAdapter object, the onCreateView() method of fragment isn't call immediatly, and my app crash (because each fragment have some methods that modify the fragment content).
How can i do for avoid this? i need that Fragments are created immediatly, so i can perform action on its
For an application which I am currently building in Java for Android I am looking for the following. I have a set with lets say 10 database records. For each row i want to show an activity (which is every time the same activity). The activity has some fields for each row to be updated.
Lets say for example you have a record set with contacts and now you want to loop through al 10 contacts and update the data.
Now I am not sure how this should work in android. Should I use fragments for this? How should i model this. Some pseudo code would help.
Since this is a custom app I am developing for ICS
Thanks very much
Create FragmentActivity with ViewPager.
ViewPager uses Adapter to display same fragments with different data.
For example, if you store in database images ids which you want to display, the code will look like this.
public class MyActivity extends FragmentActivity {
public static class MyFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final ImageView content = new ImageView(getActivity());
content.setImageResource(getArguments().getInt("img"));
return content;
}
}
private class MyPagerAdapter extends FragmentStatePagerAdapter {
private final ArrayList<Integer> imgs;
public AppTourPagerAdapter(final FragmentManager fm, final ArrayList<Integer> imgs) {
super(fm);
this.imgs = imgs;
}
#Override
public int getCount() {
return imgs.size();
}
#Override
public Fragment getItem(final int position) {
final MyFragment fragment = new MyFragment();
final Bundle args = new Bundle();
args.putInt("img", imgs.get(position));
fragment.setArguments(args);
return fragment;
}
}
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
final ViewPager pager = (ViewPager) findViewById(R.id.pager);
final ArrayList<Integer> imgIds = ... // get values from database
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager(), imgIds));
}
}
Use a viewpager with a viewpager adapter. then create a layout with a view pager, after that create a layout that will contain the items in the view pager you wish to flip through. In the adapter inflate the layout you wish to flip through. There are tons of examples online. Google it. You can copy paste 90% of what, you need to make it work.
I'm new to Android developing and I would really appreciate some help here.
I'm using a fragment that contains a TextView and I'm using 5 instances of the same MyFragment class.
In the activity, i got a button and a ViewPager, and I need the button to update all the fragment instances content, whenever its clicked.
Here's the Activity
public class MainActivity extends FragmentActivity {
final static String[] CONTENT = {"a", "b"};
ViewPager pager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<MyFragment> fragments = new Vector<MyFragment>();
for(int i = 0; i < 5; i++){
MyFragment fragment = new MyFragment(CONTENT);
fragments.add(fragment);
}
PagerAdapter adapter = new PagerAdapter(this.getSupportFragmentManager(), fragments);
pager = (ViewPager) findViewById(R.id.viewpager);
pager.setAdapter(adapter);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//method that isn't working
PagerAdapter adapter = (PagerAdapter)pager.getAdapter();
for(int i = 0; i < 5; i++){
MyFragment fragment = (MyFragment) adapter.getItem(i);
fragment.textView.setText(fragment.content[1]);
}
}
});
}
}
The Fragment
public class MyFragment extends Fragment{
String[] content;
TextView textView;
public MyFragment(String[] content) {
this.content = content;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_content, container, false);
textView = (TextView) view.findViewById(R.id.textView1);
textView.setText(content[0]);
return view;
}
}
And the FragmentPagerAdapter
public class PagerAdapter extends FragmentPagerAdapter{
List<MyFragment> fragments;
public PagerAdapter(FragmentManager fm, List<MyFragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int arg0) {
return fragments.get(arg0);
}
#Override
public int getCount() {
return fragments.size();
}
}
The OnClick method gives me a NullPointerException whenever i try to access a fragment from the adapter which is less than adapter.getCurrentItem() - 1, or more than adapter.getCurrentItem() + 1.
Any idea on how to update all the fragments at the same time?
Thanks in advance.
The easiest way to update those fragments is to use your code and set the number of fragments that the ViewPager holds in memory to the number of total fragments - 1(so all fragments are valid no matter at what page you are). In your case:
pager.setOffscreenPageLimit(4); // you have 5 elements
You can still use the method from my comment with the method onPageScrollStateChanged(so the update will start the moment the user starts swiping) to see when the user is starting to swipe the pager and update the fragments to the left and right of the currently visible fragment, but this will be a bit difficult to get right so I recommend to go with the first option.
Some points regarding your code containing fragments:
If you nest the fragment class make it static so you don't tie it to the activity object.
Don't create a constructor for a Fragment besides the default one. If the framework needs to recreate the fragment it will call the default constructor and if it is not available it will throw an exception. For example, try to change the orientation of the phone/emulator and see what happens(this is one of the cases when Android will recreate the fragments). Last, use a custom name for the ViewPager's adapter, you use PagerAdapter which is the name of the super class of FragmentViewPager and it's very confusing for someone reading your code.
If you need to pass data to the Fragment you could use a creation method like the one below:
public static MyFragment newInstance(String text) {
MyFragment f = new MyFragment();
Bundle b = new Bundle();
b.putString("content", text);
f.setArguments(b);
return f;
}
The text will be available in MyFragment by using getArguments().getString("content");