develop tabs using JSON - android

i want to know if we can develop tabs using JSON.i want as many tabs depending upon the categories in JSON and each tab must contain the list view if it is possible please let me know how to do it please
MainActivity.class
private void catmethod(){
String url="http://www.souqalkhaleejia.com/webapis/menus.php";
JsonObjectRequest catreq=new JsonObjectRequest(Request.Method.GET, url, (String) null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray menuarray=response.getJSONArray("menu");
for (int i=0;i<menuarray.length();i++){
JSONObject menuobj=menuarray.getJSONObject(i);
tabs.addTab(tabs.newTab().setText(menuobj.getString("title")));
Toast.makeText(MainActivity.this, menuobj.getString("title"), Toast.LENGTH_SHORT).show();
}
TabsAdapter tabsAdapter=new TabsAdapter(getSupportFragmentManager(),menuarray.length());
viewpager.setAdapter(tabsAdapter);
tabs.setupWithViewPager(viewpager);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("CatMenu", String.valueOf(error));
}
});
AppController.getInstance().addToRequestQueue(catreq);
}

Your fragment
public class OneFragment extends Fragment{
public OneFragment() {
// Required empty public constructor
}
public static Fragment getInstance(int position){
OneFragment fragment = new OneFragment();
Bundle bundle = new Bundle();
bundle.putInt("position", position)
fragment.setArgument(bundle);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_one, container, false);
int position = getArguments().getInt("position", 0);
// set your list base on position
if(position == 0){
//list 1
} else if(position == 1) {
// list 2
} else {
// list 3
}
return view;
}
}
Your ViewPagerAdapter
class ViewPagerAdapter extends FragmentPagerAdapter {
private JSONArray jsonArray;
public ViewPagerAdapter(FragmentManager manager, JSONArray jsonArray) {
super(manager);
this.jsonArray= jsonArray;
}
#Override
public Fragment getItem(int position) {
return OneFragment.getInstance(position);
}
#Override
public int getCount() {
return jsonArray.length();
}
#Override
public CharSequence getPageTitle(int position) {
return jsonArray.getJSONObject(position).getString("key");
}
}
Tablayout setup
tabLayout = (TabLayout) findViewById(R.id.tabs);
// get your json list
JSONArray jsonArray = your_json_array;
for(int i = 0; i < yourJsonArray.length(); i++){
JSONObject json = yourJsonArray.get(i);
tabLayout.addTab(tabLayout.newTab().setText(json.getString("key")));
}
viewPager = (ViewPager) findViewById(R.id.viewpager);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), yourJsonArray);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);

//JSON => [{"key":"TAB1", "list":[your list]}, {"key":"TAB2", "list":[your list]}, {"key":"TAB3", "list":[your list]}]
Using JSON you can add tab dynamically like...
tabLayout = (TabLayout) findViewById(R.id.tabs);
// get your json list
JSONArray jsonArray = your_json_array;
for(int i = 0; i < yourJsonArray.length(); i++){
JSONObject json = yourJsonArray.get(i);
tabLayout.addTab(tabLayout.newTab().setText(json.getString("key")));
}
Now using ViewPager you can display your list into Fragment base on your tab position.
This link will helpful to setup TabLayout android-material-design-working-with-tabs
You can also your google Gson library to parse your JSON object.

Related

How to add Fragments in ViewPager to TabLayout from a web service?

I'm trying to add tabs to my TabLayout-ViewPager-Fragment based application dynamically.The TabLayout uses a custom view with an ImageView on top of a TextView.
What I want now is to add tabs according to the number of JSONObjects in my JSONArray created from a PHP/MySQL web service. I tried the method below in my PagerAdapter but it throws:
java.lang.IllegalStateException: Can't change tag of fragment TstFrag{df80bc8 #0 id=0x7f080157 android:switcher:2131231063:0}: was android:switcher:2131231063:0 now android:switcher:2131231063:1.
The method is as in my Adapter below
public class FrgAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragmentList = new ArrayList<>();
private List<String> mFragmentTitleList = new ArrayList<>();
public FrgAdapter(FragmentManager fm) {
super(fm);
}
public FrgAdapter(FragmentManager fm, List<Fragment> mFragmentList, List<String> mFragmentTitleList) {
super(fm);
this.mFragmentList = mFragmentList;
this.mFragmentTitleList = mFragmentTitleList;
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public void insertFromJSONObject(JSONObject jsonObject, Fragment fragment, CircularImageView imageView, TextView textView) throws JSONException {
JSONArray dataArray = jsonObject.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject sectionObj = (JSONObject) dataArray.get(i);
JSONArray sectionsArray = sectionObj.getJSONArray("section");
for (int j = 0; j < sectionsArray.length(); j++) {
JSONObject obj = (JSONObject) sectionsArray.get(j);
Picasso.get().load(obj.getString("imag")).into(imageView);
mFragmentList.add(fragment);
mFragmentTitleList.add(obj.getString("name"));
textView.setText(obj.getString("name"));
notifyDataSetChanged();
}
}
}
#Override
public CharSequence getPageTitle(int position) {
return null;
}}
Here is where the method is called in my activity to add the fragments:
private void setUpViewPager(ViewPager viewPager, View view) {
adapter = new FrgAdapter(getSupportFragmentManager());
/*adapter.addFragment(new MleFrag(), "Men");
adapter.addFragment(new FmlFrag(), "Women");
adapter.addFragment(new ChdFrag(), "Children");
adapter.addFragment(new AceFrag(), "Accessories");
*/
String url = "https://44091ee6.ngrok.io/Glam/men.json";
AndroidNetworking.get(url)
.setPriority(Priority.MEDIUM)
.build()
.getAsJSONObject(new JSONObjectRequestListener() {
#Override
public void onResponse(JSONObject response) {
try {
adapter.insertFromJSONObject(response, new TstFrag(), view.findViewById(R.id.circularImageView), view.findViewById(R.id.text_header));
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onError(ANError anError) {
Toast.makeText(getApplicationContext(), anError.toString(), Toast.LENGTH_LONG).show();
}
});
adapter.notifyDataSetChanged();
viewPager.setAdapter(adapter);
}
and here is my Fragment. In my mind I want to reuse this one Fragment for each of the times I will be requiring one.
public class TstFrag extends Fragment {
public TstFrag() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.layout_cht, container, false);
}}
You may try this:
adapter.insertFromJSONObject(response, view.findViewById(R.id.circularImageView), view.findViewById(R.id.text_header));
adapter.notifyDataSetChanged();
and
public void insertFromJSONObject(JSONObject jsonObject, CircularImageView imageView, TextView textView) throws JSONException {
JSONArray dataArray = jsonObject.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject sectionObj = (JSONObject) dataArray.get(i);
JSONArray sectionsArray = sectionObj.getJSONArray("section");
for (int j = 0; j < sectionsArray.length(); j++) {
JSONObject obj = (JSONObject) sectionsArray.get(j);
Picasso.get().load(obj.getString("imag")).into(imageView);
mFragmentList.add(new TstFrag());
textView.setText(obj.getString("name"));
//mFragmentTitleList.add(obj.getString("name"));
notifyDataSetChanged();
}
}
}
The basic idea here is to create a new instance of TstFrag for each entry of the FrgAdapter.
Consider NOT to add fragments to viewPager manually but just implement getItem && instantiateItem methods on viewPager adapter. Then viewPager will control the instantiation of new TstFrag or just reuse created one. Check this answer for complete adapter.
#Override
public Fragment getItem(final int pos) {
return TstFrag.getInstance(dataList.get(pos));
}
#NonNull
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
Update
public class DataModel implements Serializable{
private String name;
private String image;
// GETTER && SETTER
}
Replace
private List<String> mFragmentTitleList = new ArrayList<>();
With
private List<DataModel> dataList = new ArrayList<>();
insertFromJSONObject
dataList.clear();
for (int j = 0; j < sectionsArray.length(); j++) {
JSONObject obj = (JSONObject) sectionsArray.get(j);
final DataModel model = new DataModel();
model.setName(obj.getString("name"));
model.setImage(obj.getString("imag"));
// Picasso.get().load(obj.getString("imag")).into(imageView);
// No need to load image here just fetch for cache if you want.
Picasso.get().load(model.getImage()).fetch();
// mFragmentList.add(fragment); // no need handle adding fragment here as mentioned above.
dataList.add(dataModel);
// textView.setText(obj.getString("name")); // It's not good to update UI here but update there with fragment on create called mention below.
// notifyDataSetChanged(); DON'T call this inside the loop but after finish your stuff.
}
// Just notify here...
notifyDataSetChanged();
TstFrag
public class TstFrag extends Fragment {
private DataModel model;
public TstFrag() {
}
public static TstFrag getInstance(DataModel model){
TstFrag fragment = new TstFrag();
Bundle bundle = new Bundle();
bundle.putSerializable("mData", model);
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = (DataModel)getArguments().getSerializable("mData");
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.layout_cht, container, false);
// findViewById() for imageView and nameTextView
Picasso.get().load(model.getImage()).into(imageView);
nameTextView.setText(model.getName());
}}

How to pass rest api list to fragment activity in android

I'm having MainActivity and three fragment activity. in MainActivity it gets data from REST service call. I want to pass REST data to all three fragments. how to achieve it?
here my code
MainActivty
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private CustomListAdapter adapter;
private static final String TAG = MainActivity.class.getSimpleName();
public List<MenuItem> mainList = new ArrayList<MenuItem>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
JsonArrayRequest itemReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
try {
JSONArray jsonArray = response.getJSONArray(0);
// Parsing json
for (int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject obj = jsonArray.getJSONObject(i);
MenuItem menuItem = new MenuItem();
menuItem.setName(obj.getString("name"));
menuItem.setImage(obj.getString("image"));
menuItem.setPrice(obj.getString("price"));
menuItem.setDesc(obj.getString("desc"));
mainList.add(menuItem);
} catch (JSONException e) {
e.printStackTrace();
}
}
}catch (JSONException e){
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new First(), "FIRST");
adapter.addFragment(new Second(), "SECOND");
adapter.addFragment(new Third(), "THIRD");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
Fragment Activity
public class First extends Fragment{
private ProgressDialog pDialog;
private GridView gridView;
private CustomListAdapter adapter;
public First() {
}
#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.fragment_one, container, false);
gridView = (GridView) view.findViewById(R.id.list);
adapter = new CustomListAdapter(getActivity(), startersList);
gridView.setAdapter(adapter);
return view;
}
}
In this line adapter = new CustomListAdapter(getActivity(), startersList);
I want to get list data from MainActivity
If you can make your menu item class implement Parcelable
How can I make my custom objects Parcelable?
Then it's simply a matter of passing arguments to the Fragment
Bundle args = new Bundle();
args.putParcelableArrayList("list", mainList) ;
Fragment first = new First();
first.setArguments(first);
adapter.addFragment(first, "FIRST");
Within the Fragment, you would use
getArguments().getParcelableArrayList("list")
Alternatively, you could also pass the JSON string into the arguments and parse it within the Fragment.
Note: however, that this only works if you move the viewpager setup method within onResponse. Otherwise, your Fragments are already created with empty lists.
Or you could implement that above logic here in the adapter
#Override
public Fragment getItem(int position) {
Fragment f = mFragmentList.get(position);
// TODO f.setArguments()
return f;
}

RecyclerView Adapter Conflict in a TabLayout

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!

ViewPager + RecyclerView issue in android

Hi I have Tablayout with Viewpager and i am using Fragment for tablayout. Now in every Tablayout fragments I have Recyclerview and displaying items.Please See this my json response
http://pastebin.com/nUswad9s
here in "typeMaster": array i have categories "typeName": "Dogs", and i am displaying typenames in tablayout i have 4 tablayout, and inside typemaster i have subcategoreis named "catMaster": and i am trying to display catmaster data in recyclerview,but the issue is in every fragment it shows last data "catName": "Vitamins & Minerals",
Activity
public class CategoriesActivity extends AppCompatActivity{
private Header myview;
private ArrayList<SubcategoryModel> subct;
private ArrayList<CategoryModel> filelist;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.categoris_activity);
filelist = (ArrayList<CategoryModel>)getIntent().getSerializableExtra("categorylist");
System.out.println("Category list size"+filelist.size());
myview = (Header) findViewById(R.id.categorisactivity_headerView);
myview.setActivity(this);
TabLayout tabLayout = (TabLayout) findViewById(R.id.cat_tab_layout);
for(int i = 0; i < filelist.size(); i++){
subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
System.out.println("SubCategory list size"+subct.size());
}
for(int i = 0; i < filelist.size(); i++){
tabLayout.addTab(tabLayout.newTab().setText(filelist.get(i).getCategory_typename()));
ArrayList<SubcategoryModel> subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
}
Bundle bundleObject = new Bundle();
bundleObject.putSerializable("key", filelist);
FirstFragment ff=new FirstFragment();
ff.setArguments(bundleObject);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final ViewPager viewPager = (ViewPager) findViewById(R.id.categories_pager);
CategoriesAdapter mPagerAdapter = new CategoriesAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(mPagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public class CategoriesAdapter extends FragmentStatePagerAdapter {
ArrayList<CategoryModel> catlist;
int numoftabs;
public CategoriesAdapter(FragmentManager fm, int numoftabs) {
super(fm);
this.numoftabs = numoftabs;
}
#Override
public Fragment getItem(int position) {
Log.v("adapter", "getitem" + String.valueOf(position)+subct.size());
return FirstFragment.create(position,subct);
}
#Override
public int getCount() {
return numoftabs;
}
}
}
Fragment
public class FirstFragment extends Fragment {
// Store instance variables
public static final String ARG_PAGE = "page";
private int mPageNumber;
private Context mContext;
private int Cimage;
private ArrayList<SubcategoryModel> subcatlist;
private RecyclerView rcylervw;
private ArrayList<CategoryModel> filelist;
ArrayList<SubcategoryModel> subct;
public static FirstFragment create(int pageNumber,ArrayList<SubcategoryModel> subct){
FirstFragment fragment = new FirstFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
args.putSerializable("key", subct);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPageNumber = getArguments().getInt(ARG_PAGE);
subct= (ArrayList<SubcategoryModel>) getArguments().getSerializable("key");
System.out.println("Frag Category list size"+subct.size());
/* for(int i = 0; i < filelist.size(); i++){
subct=filelist.get(i).getItems();
for(int j=0;j<subct.size();j++)
{
}
System.out.println("Frag SubCategory list size"+subct.size());
}*/
// image uri get uri of image that saved in directory of app
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater
.inflate(R.layout.test, container, false);
rcylervw=(RecyclerView)rootView.findViewById(R.id.subcategory_recycler_view);
rcylervw.setHasFixedSize(true);
MyAdapter adapter = new MyAdapter(subct);
rcylervw.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rcylervw.setLayoutManager(llm);
return rootView;
}
// this method is not very important
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<SubcategoryModel> mDataset;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public MyViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.subcategory_text);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<SubcategoryModel> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_subcategory, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTextView.setText(mDataset.get(position).getSubCategory_name());
}
#Override
public int getItemCount() {
return mDataset.size();
}
}
Output i am getting right now
As you can see it shows same result "Vitamin & Minerals" in every tabs..i want different subcategories instead of same.
I see a lot of problems with your code, but let's get your UI displaying the subcategories since that's your main concern.
Change the getItem in your adapter to this:
#Override
public Fragment getItem(int position) {
ArrayList<SubcategoryModel> subcategories = filelist.get(position).getItems();
Log.v("adapter", "getitem" + String.valueOf(position)+subcategories.size());
return FirstFragment.create(position,subcategories);
}
What caused the problem:
Let's focus on ArrayList<SubcategoryModel> subct in your activity:
First your code did this:
for(int i = 0; i < filelist.size(); i++){
ArrayList<SubcategoryModel> subct=filelist.get(i).getItems();
// for(int j=0;j<subct.size();j++) ...
}
So at the end of this loop subct is set the subcategories of the last category in filelist.
After that, you did another loop to load the tabs, but that used a different subct variable that was declared inside the loop, and that had no effect on the subct field of your activity.
Then you created your view pager and adapter.
In your pager adapter you had this:
#Override
public Fragment getItem(int position) {
Log.v("adapter", "getitem" + String.valueOf(position)+subct.size());
return FirstFragment.create(position,subct);
}
Since subct was set to the last category's subcategories from the loop before, every single fragment created was receiving those subcategories, no matter what position (category) the fragment was for. All I did was change the code to go back to filelist and get the correct category (and subcategories) for the position of the fragment being created.
When you're writing code, you think about what you want the code to do. However, at the point where you run the code and discover you have a problem, you have to forget what you wanted the code to do, then pretend you're the computer and run the code in your head. You want to understand what effect every line of code is having. When you do it that way it's easier to find the problem.
Problem:
There's no way to pass a Serializable ArrayList in a Bundle. Look at the docs page here Bundle docs
Solution:
Change your SubCategoryModel to implement Parcelable and then use bundle.putParcelableArrayList(key, list) and bundle.getParcelableArrayList(key) to pass the ArrayList to the FragmentArgs and get them from the Fragment
this is the main logic of your code I guess... Try it and let me know if you need more help or you find it helpful...
private void parseJsonData() {
try {
listDogs.clear();
JSONArray jsonArray = new JSONArray(loadJSONFromAsset());
JSONObject firstJsonobject = jsonArray.optJSONObject(0);
JSONArray itemListJsonArray = firstJsonobject.optJSONArray("itemList");
JSONObject secondJsonobject = itemListJsonArray.optJSONObject(0);
JSONArray typeMasterArray = secondJsonobject.optJSONArray("typeMaster");
JSONObject thirdJsonobject = typeMasterArray.optJSONObject(0);
JSONArray catMasterArray = thirdJsonobject.optJSONArray("catMaster");
for(int i=0; i<catMasterArray.length(); i++) {
JSONObject jsonObject = catMasterArray.optJSONObject(i);
ModelClass modelClass = new ModelClass();
modelClass.setTypeId(jsonObject.optString("catID"));
modelClass.setTypeName(jsonObject.optString("catName"));
listDogs.add(modelClass);
}
RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(getActivity(), listDogs);
recyclerView.setAdapter(recyclerViewAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
Note: To parse data for dogs category I've passed 0 position in variable thirdJsonobject. Pass 1 for cats and 2 for horse and you will find your desired output
Screenshots:
Dogs category
Cats category
Horse category

populate each fragment in ViewPager with different JSON object without loading again

i have a ViewPager that has a Fragment which contains a GridView into it
my code works fine only when i'm scrolling page with delay and each time retrieve's content's from internet again
all i want to do is just get each page content's once and use it when user scroll's a page
one of my issues is that JSON downloding simultaneously when several pages has been scrolled and i don't know how to store my gridview content's for next usage that a page called
is there a standard way to conquer this issue ?
here is PagerAdapter for my ViewPager :
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
String[] tabName;
public ViewPagerAdapter(FragmentManager fm, String[] tabArray) {
super(fm);
this.tabName = new String[tabArray.length];
this.tabName = tabArray;
}
#Override
public Fragment getItem(int position) {
TabPageFragment tabPageFragment = new TabPageFragment(position);
return tabPageFragment;
}
#Override
public int getCount() {
return tabName.length;
}
#Override
public CharSequence getPageTitle(int position) {
return tabName[position];
}
}
each page of ViewPager use's this class for populate Fragment :
public class TabPageFragment extends Fragment {
private GridView mgridview; // gridView inside Fragment
private int tabPosition;
private ArrayAdapterGridview arrayadapter; //adapter for my gridView
public TabPageFragment(int tabposition) {
this.tabPosition = tabposition;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mgridview = (GridView) rootView.findViewById(R.id.gridView2);
View rootView = inflater.inflate(R.layout.fragment_grid_view, container,false);
DownloadContentTab dct = new DownloadContentTab();
dct.execute();
return rootView;
}
// DownloadJSON AsyncTask
private class DownloadContentTab extends AsyncTask<Void, Void, Integer> {
#Override
protected Integer doInBackground(Void... params) {
JSONfunctions jsf = new JSONfunctions(); //this function retrieve's json for me
JSONArray jsonarray = jsf.getJSONfromURL(myUrl); // this url is differ for each page
String[] gridNameArray = new String[jsonarray.length()];
String[] gridPicArray = new String[jsonarray.length()];
for (int j = 0; j < jsonarray.length(); j++) {
try {
JSONObject jsonobject = jsonarray.getJSONObject(j);
gridNameArray[j] = jsonobject.getString("title");
gridPicArray[j] = jsonobject.getString("pic");
} catch (JSONException e) {
e.printStackTrace();
}
}
arrayadapter = new ArrayAdapterGridview(context, gridPicArray, gridNameArray);
return 0;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
mgridview.setAdapter(arrayadapter);
}
}
}

Categories

Resources