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
Related
so i'm using ViewPager to make my app much faster , instead of using an activity for each layout.
the problem is , in activity you can write your code inside onCreate
and it will only starts when you start the activity , right?
but when you go with fragments and fragmentPagerAdapter and use ViewPager for them.
all your fragments going to start their (onCreateView) together even if your ViewPager only showing the First Fragment!
if you are you playing a sound or animation on the start of a fragment , it will starts in the background !
here's my fragmentPagerAdapter class:
public class PagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitle = new ArrayList<>();
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#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);
mFragmentTitle.add(title);
}
}
and i have this (second Fragment) that i don't want it to starts without being seleceted!
public class GameFragment extends Fragment{
private View gameLayout
private Animation showBtn;
private Button button;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
gameLayout = inflater.inflate(R.layout.game_layout, container, false);
button = gameLayout .findViewById(R.id.button);
// loading my anim xml file
showBtn = AnimationUtils.loadAnimation(getContext(),R.anim.btn_show);
button.startAnimation(showBtn);
loadLevel();
return gameLayout
}
finally this is my Activity that have ViewPager :
public class ControllerActivity extends AppCompatActivity {
public CustomPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controller);
viewPager = findViewById(R.id.viewPager);
PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager());
adapter.addFragment(new HomeFragment(),"Home");
adapter.addFragment(new GameFragment(),"Game");
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(0);
}
i need your help to show me my mistakes here and what is the correct way
Using an OnPageChangeListener in your View Pager, you can detect which fragment is currently shown in the View Pager. You'll then need to check which fragment is shown and then call a method on that fragment's class to start any sounds for example that you don't want to start until the fragment is the fragment in view.
You should use an interface for this.
Here you can find an example of using an OnPageChangeListener.
Here you can find an example of Activity to Fragment communication using interfaces. This example has a lot of code that won't be relevant to your use case, but demonstrates the use of interfaces.
One way to do it "Might" be to just initialize the view of the fragment in onCreateView :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_media_viewer, container, false);
return view;
}
Then in the override the setUserVisibleHint() function and do the rest of the initialization there. This function is called when ever the fragment is in view.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
// do the rest of the code here.
}
I haven't used setuserVisibleHint for this purpose yet. But you can try it. Let me know too.
I used PagerSlidingTabStrip and have to fragments.
In each fragments, I used AsyncTask to get data from server.
Below is my fragment class that gets html from server and displays listview.
public class MainFragmentSubList extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main_list, container, false);
ListView mainList = (ListView) view.findViewById(R.id.fragment_list);
ArrayList<String> infoList;
// this is AsyncTask class and i made an interface.
new GetHtml(new OnRequestFinish(){
#Override
void onFinish(){
// Below are about ui
ArrayList<String> titleList = (ArrayList<String>) User.subName.clone();
int size = infoList.size();
MainListAdapter adapter = new MainListAdapter(titleList, infoList, size + 1);
mainList.setAdapter(adapter);
}
}).execute();
return view;
}
Since AsyncTask does things in background, return view; didn't work as I expected.
Here is my main activity that has fragments.
public class MainActivity extends ActionBarActivity {
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
tabs.setShouldExpand(true);
tabs.setViewPager(pager);
}
}
How can I return View from fragment using AsyncTask?
Go ahead and setup your view in onCreateView. Init and set your adapter too, with an empty list. For convenience you make the adapter and your list member variables.
Make sure that onFinish is invoked by AsyncTask's onPostExecute, so that it runs on the correct thread. When it is called, you update your list and then call the adapter's notifyDataSetChanged() method.
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!
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");