MainActivity.java
public class MainActivity extends ActionBarActivity {
Toolbar toolbar;
ViewPager pager;
ViewPagerAdapter adapter;
SlidingTabLayout tabs;
private ArrayList<String> mLanguagesArray = null;
int Numboftabs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if (extras != null) {
mLanguagesArray = new ArrayList<String>();
mLanguagesArray.addAll(extras.getStringArrayList("languages"));
Numboftabs = mLanguagesArray.size();
}
}
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
getSupportActionBar().setIcon(R.drawable.ic_launcher);
adapter = new ViewPagerAdapter(getSupportFragmentManager(),
mLanguagesArray, Numboftabs, MainActivity.this);
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setViewPager(pager);
tabs.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int arg0) {
refreshListInFragment(arg0);
}
});
}
protected void refreshListInFragment(int position) {
String currentLanguage = mLanguagesArray.get(position);
FragmentManager fm = getSupportFragmentManager();
ListviewFragment fragment = (ListviewFragment) fm
.findFragmentById(R.id.pager);
fragment.loadListview(currentLanguage);
}
}
ViewPagerAdapter.java
import java.util.ArrayList;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
ArrayList<String> Titles;
int NumbOfTabs;
Context mContext;
public ViewPagerAdapter(FragmentManager fm,
ArrayList<String> mLanguagesArray, int mNumbOfTabsumb,
Context context) {
super(fm);
Titles = new ArrayList<String>();
this.Titles = mLanguagesArray;
this.NumbOfTabs = mNumbOfTabsumb;
this.mContext = context;
}
#Override
public Fragment getItem(int position) {
ListviewFragment listfragment = new ListviewFragment(mContext);
return listfragment;
}
#Override
public CharSequence getPageTitle(int position) {
return Titles.get(position);
}
#Override
public int getCount() {
return NumbOfTabs;
}
}
ListviewFragment.java
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
public class ListviewFragment extends Fragment {
ProgressBar progressbar;
ListView list;
ArrayList<RStore> mRstoreList = null;
RadioListAdapter adapter;
Context mContext;
Button tryagain;
String mCurrentLanguage = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.listviewfragment, container, false);
progressbar = (ProgressBar) v.findViewById(R.id.progressbar);
list = (ListView) v.findViewById(R.id.listview);
if (ListviewFragment.this.isMenuVisible()) {
if (mRstoreList == null) {
loadListview("English");
}
}
return v;
}
public void loadListview(final String currentlanguage) {
this.mCurrentLanguage = currentlanguage;
mRstoreList = new ArrayList<RStore>();
new AsyncTask<Void, Void, String>() {
private String jsonStr;
#Override
protected void onPreExecute() {
list.setVisibility(View.GONE);
progressbar.setVisibility(View.VISIBLE);
tryagain.setVisibility(View.GONE);
super.onPreExecute();
}
#Override
protected String doInBackground(Void... arg0) {
try {
String URL = ServiceUrls.MUSIC_PHP;
CustomHttpClient sh = new CustomHttpClient();
JSONObject jsonobjpost = new JSONObject();
jsonobjpost.put("languages", currentlanguage);
jsonStr = sh.makeServiceCall(URL, CustomHttpClient.POST,
jsonobjpost.toString());
System.out.println("MUSIC_PHP_Response " + jsonStr);
} catch (Exception e) {
e.printStackTrace();
}
return jsonStr;
}
#Override
protected void onPostExecute(String result) {
if (result == null || result.trim().equalsIgnoreCase("null")
|| result.trim().equalsIgnoreCase("")) {
progressbar.setVisibility(View.GONE);
super.onPostExecute(result);
return;
}
try {
String DUMMYJASON = result.toString();
JSONObject jsonObject = new JSONObject(DUMMYJASON);
JSONArray jsonArray = jsonObject.getJSONArray("Language");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
String id = obj.getString("id");
String language = obj.getString("language");
String tittle = obj.getString("Tittle");
String link = obj.getString("link");
RStore storecon = new RStore();
storecon.setId(id);
storecon.setLanguage(language);
storecon.setTitle(tittle);
storecon.setLink(link);
mRstoreList.add(storecon);
}
} catch (JSONException e) {
e.printStackTrace();
}
adapter = new RadioListAdapter(mContext, mRstoreList);
list.setAdapter(adapter);
list.setVisibility(View.VISIBLE);
progressbar.setVisibility(View.GONE);
super.onPostExecute(result);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public ListviewFragment(Context context) {
this.mContext = context;
}
}
I'm creating number of fragments dynamically using one fragment class called ListviewFragment and setting it as view page adapter. ListviewFragment contains listview which is populated dynamically from service. With my code everything is working fine the only problem is, sometimes the datas inside the fragments are not refreshing or updating with new values. In my case the listview is showing the previously loaded data but in background the service is called and the listview Adapter is updated but the updated listview is not showing in the fragment. Please see my code, and correct me if i made any mistake..Thanks in advance
Instead of calling a method with (currentLanguage) as a parameter in fragment from activity using findFragmentById, I've just passed (currentLanguage) as bundle in ViewPagerAdapter getItem() method and in ListviewFragment class onCreateView i got (currentlanguage) value using getArguments and passed it to (loadListview) method. Now everything works fine and clean.
ViewPagerAdapter.java
#Override
public Fragment getItem(int position) {
Bundle args = new Bundle();
args.putString("language", Titles.get(position));
ListviewFragment f = new ListviewFragment(mContext);
f.setArguments(args);
return f;
}
ListviewFragment.java
private void getarugs() {
Bundle args = getArguments();
mCurrentLanguage = args.getString("language");
loadListview(mCurrentLanguage);
}
Related
i'm back here with a new Question. So at the moment i created an app , that can switch from a fragment to another fragment when you click on a button. And inside those 2 fragments there is 2 viewPagers, whose create a custom number of buttons. But the problem is that when i switch from a fragment to the other one, and then i switch back , the content of the first one is no longer here. I tried a lot of things and nothing really help me. And i hope you can help me. Thanks in advance.
The Main Activity :
public class MainActivity extends AppCompatActivity {
String identifiant=null;
BottomBar bottombar;
ProgressBar progressBar;
ImageButton imageButton;
TextView nomson;
RelativeLayout aaaa;
FragmentWhizz fragmentWhizz;
FragmentPlaylist fragmentPlaylist;
FragmentManager fm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
autorisation();
fragmentWhizz = new FragmentWhizz();
fragmentPlaylist=new FragmentPlaylist();
Fragment fragment = new FragmentConnexion();
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.contentFragment, fragment);
transaction.commit();
bottombar = (BottomBar) findViewById(bottomBar);
aaaa = (RelativeLayout) findViewById(R.id.aaaa);
bottombar.setVisibility(View.INVISIBLE);
bottombar.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(#IdRes int tabId) {
if (tabId == R.id.tab_whiz) {
if(identifiant !=null){
changementFragment(fragmentWhizz);
}
}
if (tabId == R.id.tab_playlist) {
if(identifiant !=null){
changementFragment(fragmentPlaylist);
}
}
if (tabId == R.id.tab_reveil) {
if(identifiant !=null){
changementFragment(new FragmentReveil());
}
}
if (tabId == R.id.tab_param) {
if(identifiant !=null){
changementFragment(new FragmentParam());
}
}
}
});
}
public void changementFragment(final Fragment fragment){
runOnUiThread(new Runnable() {
public void run() {
fm = getFragmentManager();
FragmentTransaction ft =fm.beginTransaction();
ft.setCustomAnimations(android.R.animator.fade_in,android.R.animator.fade_out);
ft.replace(R.id.contentFragment, fragment).commit();
}
});
}
}
One of the 2 fragments that have the ViewPager:
public class FragmentPlaylist extends Fragment {
SlideToutesPlaylist fragmentAllPlaylist = new SlideToutesPlaylist();
SlideUserPlaylist fragmentUserPlaylist = new SlideUserPlaylist();
ViewPager mViewPager;
FloatingActionButton floatbutton;
private FragmentActivity myContext;
#Override
public void onAttach(Activity activity) {
myContext=(FragmentActivity) activity;
super.onAttach(activity);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View myView = inflater.inflate(R.layout.playlist, container, false);
DeplacerBoutton deplacer = new DeplacerBoutton(getActivity(),2);
floatbutton = (FloatingActionButton) myView.findViewById(R.id.floatingActionButton);
floatbutton.setOnTouchListener(deplacer);
mViewPager = (ViewPager) myView.findViewById(R.id.slide);
mViewPager.setAdapter(new SamplePagerAdapter(myContext.getSupportFragmentManager()));
Log.i("test","test");
return myView;
}
public class SamplePagerAdapter extends FragmentStatePagerAdapter {
SamplePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
/** Show a Fragment based on the position of the current screen */
if (position == 0) {
return fragmentAllPlaylist;
} else
return fragmentUserPlaylist;
}
#Override
public int getCount() {
// Show 2 total pages.
return 2;
}
}
}
And finally one fragment displayed on the viewPager:
public class SlideToutesPlaylist extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View myView = inflater.inflate(R.layout.playlistall, container, false);
AffichePlaylist(myView);
return myView;
}
public void AffichePlaylist(View myView){
ExecHttpGetRequest requete = new ExecHttpGetRequest();
requete.execute("an IP");
LinearLayout aaa = (LinearLayout) myView.findViewById(R.id.aaa);
try {
if (requete.get() != null) {
JSONObject jsonObj = new JSONObject(requete.get());
JSONArray jSon = jsonObj.getJSONArray("valeurs");
for (int i = 0; i < jSon.length(); i++) {
JSONObject c = jSon.getJSONObject(i);
final String nom_playlist = c.getString("nom_playlist");
final String id_playlist = c.getString("id_playlist");
final String id_createur = c.getString("id_createur");
final String nb_vote = c.getString("nb_vote");
Button bouton = new Button(getContext());
bouton.setText(nom_playlist);
aaa.addView(bouton);
}
}
} catch (InterruptedException | ExecutionException | JSONException e) {
e.printStackTrace();
}
}
}
EDIT Ok finally i solved my problem with your solution but now i have this problem :
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:873)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:215)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1481)
at android.view.View.dispatchRestoreInstanceState(View.java:14762)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3123)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3129)
at android.view.View.restoreHierarchyState(View.java:14740)
at android.support.v4.app.Fragment.restoreViewState(Fragment.java:475)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1329)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:757)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2355)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2146)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2098)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2008)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:710)
at android.os.Handler.handleCallback(Handler.java:746)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
To inflate fragments inside another fragment you need tu use getChildFragmentManager() instead of
myContext.getSupportFragmentManager().
EDIT:
Use FragmentStatePagerAdapter as follows:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import java.util.ArrayList;
import java.util.List;
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragmentList = new ArrayList<>();
private List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
//Check if the list is empty before return the size
#Override
public int getCount() {
return mFragmentList != null ? mFragmentList.size() : 0;
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public void addFragment(Fragment fragment) {
mFragmentList.add(fragment);
}
#Override
public CharSequence getPageTitle(int position) {
if (!mFragmentTitleList.isEmpty()) {
return mFragmentTitleList.get(position);
}
return "";
}
}
Then in your fragment just add the fragments you want to show in the viewPager:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
...
viewPager = (ViewPager) view.findViewById(R.id.viewpager);
adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(SlideToutesPlaylist.newInstance(), getString(R.string.title));
adapter.addFragment(SlideToutesPlaylist.newInstance(), getString(R.string.title));
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(2);
I have a TabLayout with 4 tabs in my Activity and I have made a Fragment per each Tab.
Below is my Activity code:
public class MyActivity extends AppCompatActivity {
private static final String TAG = "RecyclerView";
private Toolbar toolbar;
private static ViewPager viewPager;
private static TabLayout tabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Allow activity to show indeterminate progressbar */
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.student_regulations_list);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewPager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(onTabSelectedListener(viewPager));
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1(), getString(R.string.titleA));
adapter.addFragment(new Fragment2(), getString(R.string.titleB));
adapter.addFragment(new Fragment3(), getString(R.string.titleC));
adapter.addFragment(new Fragment4(), getString(R.string.titleD));
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}
private TabLayout.OnTabSelectedListener onTabSelectedListener(final ViewPager viewPager) {
return new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());//setting current selected item over viewpager
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
};
}
//View Pager fragments setting adapter class
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();//fragment arraylist
private final List<String> mFragmentTitleList = new ArrayList<>();//title arraylist
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
//adding fragments and title method
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
I have a RecyclerView in each fragment, and I fetch data from a Web Service using AsyncTask to show in the RecyclerView. Each item in RecyclerView has an ID and I want to When I switch between tabs and click on an item in RecyclerView, a Toast shows it's ID.
Below is a Fragment code:
public class Fragment1 extends Fragment implements ClickListener {
private static final String TAG = "RecyclerView";
private List<FeedItem> feedItemList;
private RecyclerView mRecyclerView;
private FeedsRecyclerAdapter mAdapter;
final String url = "a valid url";
private View rootView;
private ProgressBar progressBar;
public StuRegGeneralListFragment() {
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_student_regulations_list, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
progressBar = (ProgressBar) rootView.findViewById(R.id.progress_bar);
/* Initialize recyclerview */
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
/*Downloading data from below url*/
new AsyncHttpTask().execute(url);
}
#Override
public void itemClicked(View view, int position) {
FeedItem item = feedItemList.get(position);
Intent intent = new Intent(getActivity(), JsonRequestFeedActivity.class);
intent.putExtra("url", Const.URL_JSON_OBJECT_REGS + item.getID());
intent.putExtra("pid", item.getID());
//startActivity(intent);
Toast.makeText(getActivity(), "Item ID: " + item.getID(), Toast.LENGTH_SHORT).show();
}
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
feedItemList = new ArrayList<FeedItem>();
}
#Override
protected Integer doInBackground(String... params) {
InputStream inputStream = null;
Integer result = 0;
HttpURLConnection urlConnection = null;
try {
/* forming th java.net.URL object */
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
/* for Get request */
urlConnection.setRequestMethod("GET");
int statusCode = urlConnection.getResponseCode();
/* 200 represents HTTP OK */
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
progressBar.setVisibility(View.GONE);
/* Download complete. Lets update UI */
if (result == 1) {
updateRecyclerView();
} else {
Log.e(TAG, "Failed to fetch data!");
}
}
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.optJSONArray("posts");
/*Initialize array if null*/
if (null == feedItemList) {
feedItemList = new ArrayList<FeedItem>();
}
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
FeedItem item = new FeedItem();
item.setID(post.optString("id"));
item.setDate(post.optString("date"));
item.setTitle(post.optString("title"));
item.setThumbnail(post.optString("thumbnail"));
feedItemList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void updateRecyclerView() {
mAdapter = new FeedsRecyclerAdapter(getActivity(), feedItemList);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setClickListener(this);
}
}
Assuming each fragment has 5 items in RecyclerView (from ID 1 to 5 in fragment1, from ID 6 to 10 in fragment2, ...) I expect when I enter to my Activity and click on an item in fragment1 (for example first item), ID=1 be shown in Toast, but ID=16 is shown!
In fact because of viewPager.setOffscreenPageLimit(3); in my Activity, fragment1 and fagment2 and fragment3 and fragment4 are created and at the end, mAdapter contains item IDs 16-20, although I am in fragment1.
I expect after creating specified fragments by viewPager.setOffscreenPageLimit(int); each fragment has it's own adapter, but it's not happened.
Any help is appreciated.
I found out my mistake!
My Activity and Fragments code are correct, my mistake was in ClickListener of RecyclerView. It's implementation was not suitable in my case.
I had used a static clickListener in it, that was the point!
I am using view-pager with fragment and pass hash-map through bundle instance to fragment. But it does not show all images in view-pager , only 3rd image show by default.
I am stuck on this... Any help will be appreciable.
Below is my java code
public class MainActivity extends AppCompatActivity {
ViewPager viewPager;
List<Fragment> fragments1;
public MyPagerAdapter adapter1;
static final ArrayList<HashMap<String, Integer>> list = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
viewPager = (ViewPager) findViewById(R.id.pager1);
fragments1 = getFragments1();
adapter1 = new MyPagerAdapter(getSupportFragmentManager(), fragments1);
viewPager.setAdapter(adapter1);
}
public class MyPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
#Override
public int getItemPosition (Object object)
{
if (object instanceof MyImageSlider ) {
return POSITION_NONE;
}
return POSITION_UNCHANGED;
}
}
private List<Fragment> getFragments1() {
List<Fragment> fList = new ArrayList<>();
for(int i = 0; i < 5; i++){
HashMap<String, Integer> map = new HashMap<>();
map.put("0",R.drawable.first);
map.put("1",R.drawable.second);
map.put("2",R.drawable.three);
map.put("3",R.drawable.four);
map.put("4",R.drawable.xiaomi);
list.add(map);
fList.add(MyImageSlider.newInstance(list.get(i)));
}
return fList;
}
public static class MyImageSlider extends Fragment {
HashMap<String, Integer> imageid;
ArrayList<HashMap<String, Integer>> listArray = new ArrayList<>();
public static MyImageSlider newInstance(HashMap<String, Integer> id)
{
MyImageSlider slider=new MyImageSlider();
Bundle b=new Bundle();
b.putSerializable("imageid", id);
slider.setArguments(b);
return slider;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
imageid=(HashMap<String, Integer>) getArguments().getSerializable("imageid");
listArray.add(imageid);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.content_main, container, false);
ImageView iv=(ImageView)view.findViewById(R.id.img);
for (String key : imageid.keySet()) {
iv.setImageResource(imageid.get(key);
}
return view;
}
}
}
why are you creating List of Fragment, you can create a single Fragment which is holding imageView and pass List of images through adapter and show image on that Fragment.
Please check below code -
and let me know if you have any concern.
// This is your MainActivity.java
package com.sample.stack;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import java.util.ArrayList;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity {
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager1);
HashMap<String,Integer> sliderDataList = new HashMap<String,Integer>();
sliderDataList.put("0",R.drawable.tc);
sliderDataList.put("1",R.drawable.tc);
sliderDataList.put("2",R.drawable.tc);
sliderDataList.put("3",R.drawable.tc);
sliderDataList.put("4",R.drawable.tc);
PagerAdapter adapter1 = new PagerAdapter(getSupportFragmentManager(), sliderDataList, MainActivity.this);
viewPager.setAdapter(adapter1);
}
}
// This is your FragmentPagerAdapter
package com.sample.stack;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.HashMap;
/**
* Created by on 06-12-2016.
*/
public class PagerAdapter extends FragmentPagerAdapter {
private final HashMap<String, Integer> hMap;
private final Context context;
public PagerAdapter(FragmentManager fm, HashMap<String,Integer> hMap, Context context) {
super(fm);
this.hMap=hMap;
this.context=context;
}
#Override
public Fragment getItem(int position) {
return new SliderFragment(hMap,context,position);
}
#Override
public int getCount() {
return hMap.size();
}
}
// This is your Fragent containg ImageView
package com.sample.stack;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Created by Syscraft on 06-12-2016.
*/
#SuppressLint("ValidFragment")
public class SliderFragment extends Fragment {
private final HashMap<String, Integer> urls;
private int imageResourceId;
private Context ctx;
public SliderFragment(HashMap<String,Integer> urls, Context c,
int pos) {
this.urls = urls;
this.imageResourceId = pos;
this.ctx = c;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.slider_adapter, container, false);
final ImageView imageView = (ImageView) view
.findViewById(R.id.sliderImages);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setImageResource(urls.get(imageResourceId+""));
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
return view;
}
}
public class MainActivity extends AppCompatActivity {
ViewPager viewPager;
public PagerAdapter adapter1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager1);
final HashMap<String,Integer> sliderDataList = new HashMap<String,Integer>();
sliderDataList.put("0",R.drawable.first);
sliderDataList.put("1",R.drawable.second);
sliderDataList.put("2",R.drawable.three);
sliderDataList.put("3",R.drawable.four);
sliderDataList.put("4",R.drawable.xiaomi);
adapter1 = new PagerAdapter(getSupportFragmentManager(), sliderDataList, MainActivity.this);
viewPager.setAdapter(adapter1);
// sliderDataList.remove("3");
adapter1.notifyDataSetChanged();
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
remove("3");
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
public void remove(String s){
adapter1.remove(s);
}
public class PagerAdapter extends FragmentPagerAdapter {
private final HashMap<String, Integer> hMap;
private final Context context;
public PagerAdapter(FragmentManager fm, HashMap<String,Integer> hMap, Context context) {
super(fm);
this.hMap=hMap;
this.context=context;
}
#Override
public Fragment getItem(int position) {
return new SliderFragment(hMap,context,position);
}
#Override
public int getCount() {
return hMap.size();
}
public void remove(String s){
Iterator<Map.Entry<String,Integer>> iter = hMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,Integer> entry = iter.next();
if(s.equalsIgnoreCase(entry.getKey())){
iter.remove();
}
}
hMap.remove(s);
adapter1.notifyDataSetChanged();
}
}
#SuppressLint("ValidFragment")
public static class SliderFragment extends Fragment {
private final HashMap<String, Integer> urls;
private int imageResourceId;
private Context ctx;
public SliderFragment(HashMap<String,Integer> urls, Context c, int pos) {
this.urls = urls;
this.imageResourceId = pos;
this.ctx = c;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.content_main, container, false);
final ImageView imageView = (ImageView) view
.findViewById(R.id.img);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setImageResource(urls.get(imageResourceId +""));
return view;
}
}
}
I want to create soemthing like this:
The ViewPager is attached to an adapter which has 2 fragments. One to list the upcoming orders and the other to list the past orders.
So the image shown above has a main fragment which hosts the ViewPager, and the adapter creates 2 fragments as children of the main fragment.
For sake of simplicity I'll call the main fragment as "Parent fragment" and the two fragments supplied by the adapter as "children fragments".
Once the parent fragment is created or resumed it has to fetch a list of data from the server and pass it to the two children fragment(The children fragments will process the list of data and display the necessary data). Both the children fragments have a listView, and each listView row item is clickable.
Now, the data fetched by the parent fragment has to be passed to the children fragments before the ViewPager is attached to the adapter. So I do not attach the adapter to the ViewPager in the onCreate method of the parent fragment, but rather once the list of data is fetched, I attach the adapter to the ViewPager in the onPostExecute method of the async task after the data is fetched.
This works fine the first time, but once I click on a listView row item of the child fragment and then press the back button, the getItem() method of the adapter is not called, but the onResume methods of the children fragments are called even before the data is fetched from the server.
So I guess the android framework remembers that the children fragment have already been created, and does not recreate them again.
How do I ensure that the children fragments are created/called only after the data is fetched from the server in the parent fragment?
I am adding some code for clarity.
BookingHistory.java(Parent Fragment)
public class BookingHistory extends android.support.v4.app.Fragment {
ViewPager mPager;
SlidingTabLayout mTabs;
Toolbar toolBar;
View view;
private ProgressDialog progress;
private OrderTask mOrderTask = null;
UserFunctions userFunctions = null;
OrderFunctions orderFunctions = null;
private BookingHistoryListener mListener;
private List<Order> mOrderList;
PlacedOrders upcomingOrders;
PlacedOrders pastOrders;
public BookingHistory() {
// Required empty public constructor
}
#Override
public void onResume() {
super.onResume();
mOrderList = null;
mPager = null;
mTabs = null;
upcomingOrders = null;
pastOrders = null;
progress = new ProgressDialog(getActivity());
fetchOrders();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_booking_history, container, false);
toolBar = (Toolbar) view.findViewById(R.id.toolbar_s);
if (toolBar != null) {
TextView tv = (TextView) view.findViewById(R.id.toolbar_title);
toolBar.setTitle("");
tv.setText("History");
}
return view;
}
class MyPagerAdapter extends FragmentPagerAdapter {
String tabs[] = {"Upcoming", "Past"};
public MyPagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
if (position == 0) {
upcomingOrders = PlacedOrders.newInstance(Constants.DATE_TODAY_FUTURE);
upcomingOrders.getOrderList(mOrderList);
return upcomingOrders;
} else {
pastOrders = PlacedOrders.newInstance(Constants.DATE_PAST);
pastOrders.getOrderList(mOrderList);
return pastOrders;
}
}
#Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
#Override
public int getCount() {
return 2;
}
}
public void fetchOrders() {
if (mOrderTask != null) {
return;
}
progress.show();
mOrderTask = new OrderTask(getActivity());
mOrderTask.execute((Void) null);
}
public class OrderTask extends AsyncTask<Void, Void, Boolean> {
private final Activity mActivity;
OrderTask(Activity activity) {
mActivity = activity;
}
#Override
protected Boolean doInBackground(Void... params) {
userFunctions = new UserFunctions();
orderFunctions = new OrderFunctions();
return orderFunctions.getList(userFunctions.getToken(mActivity));
}
#Override
protected void onPostExecute(final Boolean success) {
mOrderTask = null;
progress.dismiss();
if (success) {
mOrderList = UserProfile.getOrders();
//attaching the view pager to adapter here!
mPager = (ViewPager) view.findViewById(R.id.pager);
mTabs = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
mTabs.setDistributeEvenly(true);
mTabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.white);
}
});
mPager.setAdapter(new MyPagerAdapter(getChildFragmentManager()));
mTabs.setViewPager(mPager);
} else {
//Error handling stuff
}
}
}
}
PlacedOrders.java(Children Fragments)
public class PlacedOrders extends android.support.v4.app.Fragment {
private static String flag;
private int dateFlag;
private PlacedOrdersListener mListener;
UserFunctions userFunctions = null;
OrderFunctions orderFunctions = null;
private PlacedOrdersAdapter ordersAdapter;
private ProgressDialog progress;
private List<Order> mOrderList;
private List<Order> mPendingOrderList;
private List<Order> mCompletedOrderList;
public static PlacedOrders newInstance(int date) {
PlacedOrders fragment = new PlacedOrders();
Bundle args = new Bundle();
args.putInt(flag, date);
fragment.setArguments(args);
return fragment;
}
public void getOrderList(List<Order> orderList) {
this.mOrderList = orderList;
}
public PlacedOrders() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
dateFlag = getArguments().getInt(flag);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mPendingOrderList = new ArrayList<Order>();
mCompletedOrderList = new ArrayList<Order>();
return inflater.inflate(R.layout.fragment_placed_orders, container, false);
}
#Override
public void onResume() {
super.onResume();
displayOrders();
}
private void displayOrders() {
if (isVisible() && (mOrderList != null)) {
mPendingOrderList.clear();
mCompletedOrderList.clear();
ListView listViewOrder = (ListView) getView().findViewById(R.id.orderList);
if(dateFlag == Constants.DATE_TODAY_FUTURE) {
for(int i = 0; i < mOrderList.size(); i++) {
String status = mOrderList.get(i).status;
if(status.equals("PENDING") || status.equals("PROCESSING")) {
mPendingOrderList.add(mOrderList.get(i));
ordersAdapter = new PlacedOrdersAdapter(mPendingOrderList, getActivity().getLayoutInflater());
listViewOrder.setAdapter(ordersAdapter);
}
}
}
else if(dateFlag == Constants.DATE_PAST) {
for(int i = 0; i < mOrderList.size(); i++) {
String status = mOrderList.get(i).status;
if(status.equals("COMPLETE")) {
mCompletedOrderList.add(mOrderList.get(i));
ordersAdapter = new PlacedOrdersAdapter(mCompletedOrderList, getActivity().getLayoutInflater());
listViewOrder.setAdapter(ordersAdapter);
}
}
}
listViewOrder.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//Display a new fragment on clicking
});
}
}
}
I had same issue and this was my solution :
In container fragment (fragment that contains tabs) in onViewCreated() method I created startFetch() method:
#Override
public void onViewCreated(View v, Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
mViewPager = (ViewPager) v.findViewById(R.id.home_tab_pager);
mTabsHost= (TabLayout) getActivity().findViewById(R.id.appTabs);
startFetch();
}
Then in startFetch method i use Volley request and in onResponse method i update data and then add tabs :
public void startFetch(){
//Create volley request
String url = BuildConfig.API_GET_CATEGORIES;
final RequestQueue queue = VolleyService.getInstance(this.getContext()).getRequestQueue();
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// we got the response, now our job is to handle it
try {
updateCategoryData(response);
} catch (RemoteException | OperationApplicationException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//something happened, treat the error.
Log.e("ErrorFETCH", error.networkResponse.toString());
}
});
queue.add(request);
}
My udpateCategory() method :
public void updateCategoryData(final String stream) throws RemoteException, OperationApplicationException {
//Update the data to SQLITE
setupTabs();
}
My setupTabs() method :
public void setUpTabs(){
ArrayList<Category> categories = new ArrayList<>();
Cursor data = getActivity().getContentResolver().query(
Category.Entry.CONTENT_URI, // URI
Category.PROJECTION, // Projection
Category.Entry.COLUMN_NAME_PARENT_ID + " = ?", // Selection
new String[]{"0"}, // Selection args
null);
if (data != null) {
while(data.moveToNext()){
categories.add(new Category(data));
}
}
TabsPagerAdapter mAdapter = new TabsPagerAdapter(getActivity().getSupportFragmentManager(), this.getActivity(), categories);
mViewPager.setAdapter(mAdapter);
mTabsHost.setupWithViewPager(mViewPager);
}
I have created action bar and viewpager, I have three fragment. Each of the fragment I parsed json and can show each listview . My problem is : If I click second fragment and then I go back(click firs fragmet) when I go to the next fragment and then if I go to a front fragment at this situation Loading information from the server occurs twice, I use AsyncTask class to load info from server.
Below is a my code :
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new SendItemsFragment();
case 1:
return new RecivedItemsFragment();
case 2:
return new FavoriteItemsFragment();
}
return null;
}
#Override
public int getCount() {
return 3;
}
public class MainActivity extends FragmentActivity implements TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
private String[] tabs = { "test1", "test2", "test3" };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setIcon(R.color.white);
actionBar.setDisplayShowTitleEnabled(true);
Drawable d = getResources().getDrawable(R.drawable.acttitle);
getActionBar().setBackgroundDrawable(d);
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
viewPager = (ViewPager) findViewById(R.id.vp_main);
viewPager.setAdapter(mAdapter);
getActionBar().setCustomView(R.layout.menu_example);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// actionBar.setStackedBackgroundDrawable(getResources().getDrawable(
// R.drawable.background)); background viewpager
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
This is - one of the fragment's code. Similar to all three of them. The only difference is that the load of data from the server, And also use the AsyncTask class, each of which had a different.
public class SendItemsFragment extends Fragment {
private String URL = "*******************************************";
public static String KEY_title = "title";
public static String KEY_description = "description";
public static String KEY_image = "image";
public static String KEY_journal = "journal";
public static String KEY_JournalID = "JournalID";
public static String KEY_pubDate = "pubDate";
public static String KEY_statID = "statID";
public JSONArray jsonarray;
public ListView list;
public TransparentProgressDialog pd;
public JSONParser jsonparser;
static DealBoxAdapter adapter;
ProgressDialog pDialog, pDialog1;
static String fontPath2 = "font.ttf";
public static Typeface tf2;
ArrayList<HashMap<String, String>> itemList = new ArrayList<HashMap<String, String>>();
public ImageLoader imageLoader;
static final int DIALOG_ERROR_CONNECTION = 1;
private int screenSize;
private LoadDataAllChanelsToServer loader;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.send_items, container, false);
list = (ListView) rootView.findViewById(R.id.listView1);
pd = new TransparentProgressDialog(getActivity(), R.drawable.loader);
screenSize = getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK;
loader=new LoadDataAllChanelsToServer();
loader.execute();
return rootView;
}
private class LoadDataAllChanelsToServer extends
AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected String doInBackground(String... urls) {
jsonparser = new JSONParser();
JSONObject jsonobject = jsonparser.getJSONfromURL(URL);
try {
jsonarray = jsonobject.getJSONArray("data");
for (int i = 0; i < jsonarray.length(); i++) {
jsonobject = jsonarray.getJSONObject(i);
HashMap<String, String> map = new HashMap<String, String>();
map.put("journal", jsonobject.getString(KEY_journal));
map.put("image", jsonobject.getString(KEY_image));
map.put("title", jsonobject.getString(KEY_title));
map.put("description",
jsonobject.getString(KEY_description));
map.put("JournalID", jsonobject.getString(KEY_JournalID));
map.put("pubDate", jsonobject.getString(KEY_pubDate));
map.put("statID", jsonobject.getString(KEY_statID));
itemList.add(map);
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return itemList.toString();
}
#Override
protected void onPostExecute(String result) {
try {
if (pd != null) {
pd.dismiss();
}
} catch (Exception e) {
}
try {
adapter = new DealBoxAdapter(getActivity(), itemList,
screenSize);
list.setAdapter(adapter);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
}
that's all :)
if anyone knows solution please help me
thank you
You should cancel async task when your Fragment is destroyed.
private LoadDataAllChanelsToServer mLoader;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
mLoader = new LoadDataAllChanelsToServer();
mLoader.execute();
...
}
#Overide
public onDestroy() {
super.onDestroy();
if(mLoader != null) {
mLoader.cancel(true);
mLoader = null;
}
this way when fragment is destroyed AsyncTask will be canceled.
You can also set ViewPager.setOffscreenPageLimit(2). This way, since you have only 3 Fragments, no Fragments will be destroy and therefore your onViewCreated will only be called once.