I, know this question is already asked on community but still I am not able to resolve my issue. That's why posting this again. How to pass data from recyclerview adapter to fragment. I have successfully pass data from adapter to the activity. But not able to get how to pass data from adapter to the fragment. I have two Parameters in my database (1) mSliderImage and (2) mTitle. The mSliderImage is shown on home fragment. but now I want when user click on particular image of slider a new fragment get opens and there mTitle will be shown. I successfully able to open new fragment on click of image-slider base on image position. But not getting how to pass mTitle in that fragment. Please someone help me the whole code because I have to submit this college level project by 17th of January. I am only posting the important code not my whole code. I just want coding solution of how to pass mSliderTitle from adapter to the fragment. when I click on some image of Image Slider.
Below is my code:
In Model I have passed 2 Getters ans Setters already mentioned above. (1) mSliderImage and (2) mTitle.
Slider Adapter:
public class SliderImageAdapter extends SliderViewAdapter<SliderImageAdapter.SliderAdapterVH>{
public List<Banner> bannerList;
public Context context;
private OnItemClicked onClick;
public interface OnItemClicked {
void onItemClick(int position);
}
public SliderImageAdapter(Context context, List<Banner> bannerList, OnItemClicked onClick) {
this.bannerList = bannerList;
this.context = context;
this.onClick = onClick;
}
#Override
public SliderAdapterVH onCreateViewHolder(ViewGroup parent) {
View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_slider_myshop, parent, false);
return new SliderAdapterVH(inflate);
}
#Override
public void onBindViewHolder(final SliderAdapterVH viewHolder, final int position) {
Glide.with(viewHolder.itemView)
.load(bannerList.get(position).getmSliderImage())
.into(viewHolder.imageViewBackground);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onClick.onItemClick(position);
}
});
}
#Override
public int getCount() {
return bannerList.size();
}
public int getItemPosition (Object object) {
return POSITION_NONE;
}
public void setOnClick(OnItemClicked onClick) {
this.onClick = onClick;
}
class SliderAdapterVH extends SliderViewAdapter.ViewHolder {
View itemView;
ImageView imageViewBackground;
public SliderAdapterVH(View itemView) {
super(itemView);
imageViewBackground = itemView.findViewById(R.id.iv_auto_image_slider);
this.itemView = itemView;
}
}
Home Fragment: (Here Image Slider is Shown. and I want when user click a new fragment get open and show mTitle).
public class HomeFragment extends Fragment implements SliderImageAdapter.OnItemClicked {
private SliderImageAdapter sliderImageAdapter;
private List<Banner> bannerList;
bannerList = new ArrayList<>();
sliderImageAdapter = new SliderImageAdapter(getActivity(), bannerList, this);
#Override
public void onItemClick(int position) {
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_container_dashboard, SliderClickFragment.newInstance());
ft.addToBackStack(null);
ft.commit();
}
Slider Click Fragment XML:
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/mSliderTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Slider Click Fragment Java: (Here I want to show mTitle when user click on image)
public class SliderClickFragment extends Fragment {
public static SliderClickFragment newInstance() {
Bundle args = new Bundle();
SliderClickFragment fragment = new SliderClickFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.slider_click_listner,container,false);
return view;
}
}
Try this. I haven't tested but this flow should get what you are trying to achieve.
HomeFragment.java
public class HomeFragment extends Fragment implements SliderImageAdapter.OnItemClicked {
private SliderImageAdapter sliderImageAdapter;
private List<Banner> bannerList;
bannerList = new ArrayList<>();
sliderImageAdapter = new SliderImageAdapter(getActivity(), bannerList, this);
#Override
public void onItemClick(int position) {
//GET THE TITLE STRING HERE
String title = bannerList.get(position).getmSliderTitle();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//PASS THIS TITLE TO THE FRAGMENT INSTANCE LIKE THIS
ft.add(R.id.fragment_container_dashboard, SliderClickFragment.newInstance(title));
ft.addToBackStack(null);
ft.commit();
}
SliderClickFragment.java
public class SliderClickFragment extends Fragment {
//EDIT the newInstance Method definition to include title like this:
public static SliderClickFragment newInstance(String title) {
Bundle args = new Bundle();
//PASS THE STRING IN THE BUNDLE WHICH WILL THEN BE FETCHED IN ONCREATEVIEW LATER LIKE THIS
args.putString("title", title);
SliderClickFragment fragment = new SliderClickFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.slider_click_listner,container,false);
//GET THE STRING HERE AND THEN USE IT HOWEVER YOU LIKE
String title = getArguments().getString("title");
return view;
}
}
Related
I have one activity HomeActivity and I have HomePageFragment which have some categories with icon and title of data, when I click on any category I'm sending the clicked item Title name with bundle and opening MultipleFragment and I'm getting clicked title name from the previous fragment, on this multiple fragments I have viewpager inside it..
1) PostFragment,
2) TextFragment
now here's my main question that I want to send clicked item title name to PostFragment and TextFragment,
HomeFragment
public void onItemClick(int position) {
MultiplePost multiplePost = new MultiplePost();
Bundle args = new Bundle();
Categories categoriesClicked = categoriesList.get(position);
args.putString(Title, categoriesClicked.getTitle());
args.putString(ImageUrl, categoriesClicked.getIcon());
multiplePost.setArguments(args);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.main_frame,multiplePost)
.addToBackStack(null)
.commit();
}
MultiplePost
public class MultiplePost extends Fragment {
private TabLayout tabLayout;
private ViewPager viewPager;
private ViewPageAdapter viewPageAdapter;
private View view;
private FragmentManager mFragmentManager;
public static String title ;
public MultiplePost() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_multiple_post, container, false);
title = getArguments().getString("title");
tabLayout = view.findViewById(R.id.tablayout_id);
viewPager = view.findViewById(R.id.viewPager_id);
viewPageAdapter = new ViewPageAdapter(getChildFragmentManager());
viewPageAdapter.AddFragment(new PostFragment(), "");
viewPageAdapter.AddFragment(new TextFragment(), "");
viewPager.setAdapter(viewPageAdapter);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.photo);
tabLayout.getTabAt(1).setIcon(R.drawable.file);
PostFragment post = new PostFragment();
Bundle args = new Bundle();
args.putString("title", title);
post.setArguments(args);
getActivity().getSupportFragmentManager().beginTransaction();
.replace(R.id.main_frame, post)
.commit();// and this's changing whole fragment with PostFragment and
//so i can't see my viewpager on MultiplePost
return view;
}
}
ViewPagerAdapter
public class ViewPageAdapter extends FragmentPagerAdapter {
private final List<Fragment> listFragment = new ArrayList<>();
private final List<String> listTitle = new ArrayList<>();
public ViewPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return listFragment.get(position);
}
#Override
public int getCount() {
return listTitle.size();
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return listTitle.get(position);
}
public void AddFragment(Fragment fragment, String title){
listFragment.add(fragment);
listTitle.add(title);
}
}
How to send title onto PostFragment and TextFragment into viewpager
Sorry for my english. I have one activity and in this activity in FragmentPagerAdapter exist 5 fragments. All fragments use one object model for inforation(product name, product image ...).
My activity get data from data base. And then it data send to all fragments. My example Activity:
#BindView(R.id.tabs_sep_prod) TabLayout tabs_sep_prod;
#BindView(R.id.viewpager_sep_prod) ViewPager viewpager_sep_prod;
PrepBaseProdFragment prepBaseProdFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sep_product);
ButterKnife.bind(this);
prepBaseProdFragment = new PrepBaseProdFragment();
// there i have another fragments
// ...
setupViewPager(viewpager_sep_prod);
tabs_sep_prod.setupWithViewPager(viewpager_sep_prod);
}
private void setupViewPager(ViewPager viewPager) {
SepProductActivity.ViewPagerAdapter adapter = new SepProductActivity.ViewPagerAdapter(
adapter.addFrag(prepBaseProdFragment, getString(R.string.sep_prep_base));
// there i have another addFrag
// ...
viewPager.setOffscreenPageLimit(5);
viewPager.setAdapter(adapter);
}
#Override
public void onResume() {
super.onResume();
// this i call method from presenter, it return data in method setData
if(idCat != null && idProd != null)
sepProductPresenter.getSepProd(idCat, idProd);
}
#Override
public void setData(SepProductModel sepProductModel) {
// there i send data to fragment
prepBaseProdFragment.setDataInf(sepProductModel);
// ...
}
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 addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
my fragment
public class PrepBaseProdFragment extends BaseFragment {
#BindView(R.id.text) TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_about_prod_prepare_base, parent, false);
ButterKnife.bind(this, view);
Log.e("PrepBaseProdFragment", "PrepBaseProdFragment");
return view;
}
public void setDataInf(SepProductModel sepProductModel) {
text.setText(sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT());
}
}
My question: when i send data from activity to fragment, my view do not have time to initialize. In fragment line text.setText(sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT()); error
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.TextView.setText(java.lang.CharSequence)' on a null
object reference
Please, help me solve my problem. I spend many times for this
You can check if the text view is null save the data in a variable inside the fragment and in onCreateView use the data variable if it is filled and set the textview text.
Something like this:
// Inside the Fragment body
private SepProductModel sepProductModel;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_about_prod_prepare_base, parent, false);
ButterKnife.bind(this, view);
Log.e("PrepBaseProdFragment", "PrepBaseProdFragment");
if(this.sepProductModel != null)
text.setText(this.sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT());
return view;
}
public void setDataInf(SepProductModel sepProductModel) {
if(text != null){
// use text
}
else this.sepProductModel=sepProductModel;
}
I can advise you to wait for your data and then show fragments to adapter, moreover all of them use the same model. While you dont have data, you can show progress bar.
When you have needed model, you can create instances of your fragments and set bundle arguments for them. You can use method like this:
public static MyFragment newInstance(MyModel model){
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putSerializable(KEY, model);//or args.putParcelable(KEY, model);
fragment.setArguments(args);
return fragment;
}
Notice: your model need to implement Serializable or Parcelable to be putted in bundle. You may read about difference here.
Then in your set data method, when you already have your model you can setup your adapter and set it to view pager, but with this approach:
adapter.addFrag(MyFragment.newInstance(model), getString(R.string.sep_prep_base));
It have to help you, ask me if you have some questions.
Friends, I've spent enough time to find an answer to my question(here and on android's site) But no luck.
Here is the logic:
From DialogFragment upon finishing putting user's data he clicks OK button:
import de.greenrobot.event.EventBus;
...
public class AddDialogFragment extends DialogFragment implements
DialogInterface.OnClickListener {
...
public void onClick(DialogInterface dialog, int which) {
StringBuilder date = new StringBuilder(today.getText().subSequence(0,
today.getText().length()));
date = (date.toString().equals(getString(R.string.today))) ? new StringBuilder("20150104") : date;
int weight = 89;
String[] bsi = rb.getSelectedItems();
String[] gsi = rg.getSelectedItems();
DatabaseManipulation dm = new DatabaseManipulation(getActivity());
dm.run(date, weight, bsi, gsi);
dm.destroy();
DialogDataModel toSend = new DialogDataModel(weight, date.toString(), bsi, gsi);
/*
Context activity = getActivity();
if (activity instanceof WDActivity)
((WDActivity) activity).updateListItemFragment();
*/
EventBus.getDefault().post(new UpdateItemEvent(toSend));
Log.d(LOG_TAG, "send event");
Toast.makeText(getActivity(), R.string.saved_data, Toast.LENGTH_LONG).show();
}
...
Event is successfully sent to Adapter class which is registered for receiving this event:
...
import de.greenrobot.event.EventBus;
public class ItemsAdapter extends BaseAdapter implements ListAdapter {
private static final String LOG_TAG = "Logs";
private ArrayList<DialogDataModel> list = new ArrayList<DialogDataModel>();
private Context activity;
public ItemsAdapter (ArrayList<DialogDataModel> list, Context context) {
this.list = list;
this.activity = context;
registerEventBus();
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
return list.get(pos);
}
#Override
public long getItemId(int pos) {
return pos;
//just return 0 if your list items do not have an Id variable.
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.row_item, null);
}
DialogDataModel curData = list.get(position);
TextView itemDate = (TextView)view.findViewById(R.id.item_date);
itemDate.setText(curData.getDate());
TextView itemWeight = (TextView)view.findViewById(R.id.item_weight);
itemWeight.setText( Integer.toString(curData.getWeight()) );
TextView itemEvents = (TextView)view.findViewById(R.id.item_events);
itemEvents.setText(curData.getEventsShort());
//Handle buttons and add onClickListeners
ImageButton editBtn = (ImageButton)view.findViewById(R.id.item_edit_btn);
editBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (activity instanceof WDActivity)
((WDActivity) activity).AddNewData(v, list.get(position));
notifyDataSetChanged();
}
});
ImageButton deleteBtn = (ImageButton) view.findViewById(R.id.item_delete_btn);
deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String date = list.get(position).getDate();
DatabaseManipulation dm = new DatabaseManipulation(activity);
dm.deleteItem(date);
dm.destroy();
list.remove(position);
notifyDataSetChanged();
}
});
return view;
}
public void registerEventBus(){
if (!EventBus.getDefault().isRegistered(this)) EventBus.getDefault().register(this);
Log.d(LOG_TAG, "Registred from adapter");
}
public void unregisterEventBus(){
EventBus.getDefault().unregister(this);
}
public void onEventMainThread(UpdateItemEvent event) {
Log.d(LOG_TAG, "Event fired!");
list = DialogDataModel.replaceFieldsInArray(list,event.getModel());
notifyDataSetChanged();
}
}
After clicking OK in dialog window the user sees the list of items and the item he's updated is up to date. Without this logic he sees the old version of this item item in the list and to refresh the list he needs to relaunch the app.
Yes, it's working with EventBus.
But as you can see here in the class there is no place for unregistering it from listening for UpdateItemEvent. Since there are no destructors in java(I don't believe that garbage collector should do this for me) I should handle this. Moreover the class registeres as listener in constructor (it happens several times, that's why you see this ugly if statement(if (!EventBus.getDefault().isRegistered(this))) You may ask me why not getting this adapter through Activity (there is the only one in the app) I tried building a chain AddDialogFragment -> WDActivity -> PlaceholderFragment -> ItemsAdapter
//AddDialogFragment
Context activity = getActivity();
if (activity instanceof WDActivity)
((WDActivity) activity).updateListItemFragment();
//WDActivity --beginTransaction().replace does not work here
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wd);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
...
public void updateListItemFragment() {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.Fragment currentFragment = fragmentManager.findFragmentById(R.id.container);
if (currentFragment instanceof PlaceholderFragment && currentFragment != null) {
fragmentManager.beginTransaction().remove(currentFragment).commit();
fragmentManager.beginTransaction().add(R.id.container, currentFragment).commit();
((PlaceholderFragment)currentFragment).fillList();
}
//PlaceholderFragment
public class PlaceholderFragment extends Fragment {
private static final String LOG_TAG = "Logs";
private static final String ARG_SECTION_NUMBER = "section_number";
private ListView listViewItem;
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(getArguments().getInt(ARG_SECTION_NUMBER)==1)
return onCreateViewInputChart(inflater, container, savedInstanceState);
if(getArguments().getInt(ARG_SECTION_NUMBER)==2)
return onCreateViewManual(inflater, container, savedInstanceState);
return onCreateViewInputData(inflater, container, savedInstanceState);
}
private View onCreateViewManual(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_howto, container, false);
return rootView;
}
private View onCreateViewInputData(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list_data, container, false);
findViewsByIdListItem(rootView);
fillList();
return rootView;
}
private View onCreateViewInputChart(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_chart, container, false);
return rootView;
}
//listViewItems
private void findViewsByIdListItem(View v) {
listViewItem = (ListView) v.findViewById(R.id.listViewItems);
}
public void fillList(){
Context activity = getActivity();
DatabaseManipulation dm = new DatabaseManipulation(activity);
ArrayList<DialogDataModel> aldm = dm.getItemsList();
dm.destroy();
ItemsAdapter innerAdapter = new ItemsAdapter(aldm, activity);
listViewItem.setAdapter(innerAdapter);
( (BaseAdapter) listViewItem.getAdapter() ).notifyDataSetChanged();
}
#Override
public void onAttach(Context activity) {
super.onAttach(activity);
}
#Override
public void onDetach(){
super.onDetach();
}
}
//SectionsPagerAdapter - just for your information
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
return PlaceholderFragment.newInstance(position);
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Enter your data";
case 1:
return "Chart";
case 2:
return "How to use it";
}
return null;
}
}
//ItemsAdapter is placed higher
This did not work. Finally I found out that the bottleneck is in linking PlaceholderFragment and ListAdapter: listViewItem is null everywhere except onCreateViewInputData. I could not figure out why. Google didn't give me the answer and I took it as a magic. Btw due to this feature I cannot use PlaceholderFragment's onAttach and onDetach for saying ItemsAdapter to register/unregister for receiving the event. This:
#Override
public void onAttach(Context activity) {
super.onAttach(activity);
( (ItemsAdapter) listViewItem.getAdapter() ).registerEventBus();
}
doesn't work for the same reason listViewItem is null. Maybe there is some way to manage with this more accurately?
Finally I cope with this: the bottleneck is in linking PlaceholderFragment and ListAdapter: listViewItem is null everywhere except onCreateViewInputData . Below is rewised SectionsPagerAdapter:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
Context activity;
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public SectionsPagerAdapter(FragmentManager fm, Context activity) {
super(fm);
this.activity = activity;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
return PlaceholderFragment.newInstance(position);
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return activity.getString(R.string.chart);
case 1:
return activity.getString(R.string.weight_diary);
case 2:
return activity.getString(R.string.how_to);
}
return null;
}
#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);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
//maybe use adapater.getRegisteredFragment(viewPager.getCurrentItem());
}
}
and here is my call to the widget in the one of 3 fragments:
public void updateListItemFragment() {
android.support.v4.app.Fragment inputData = mSectionsPagerAdapter.getRegisteredFragment(1);
ListView lv = ((PlaceholderFragment)inputData).listViewItem;
//for test purposes I refill listview with no items - here you need to hand filled BaseAdapter instance: CustomAdapter innerAdapter = new CustomAdapter(ArrayList<yourDataModel>, getContext());
lv.setAdapter(null);
}
And as you've may already wondered there is no need for event bus anymore. Btw if the fragment is not crated yet you need to check it: details are here. Thanks to CommonsWare for quik reply and advice.
I am trying to pass an object that is retrieved and created during my main activities on create method to one of the fragments of my sliding tabs layout.
Since this object is created over a network connection my plan was to receive the data during the creation of the Main Activity then pass the resulting object to my fragments. However this seems easier said than done. The resulting object will then get passed to a recycler view in the Forecast fragment.
I have read various methods including implementing the parcelable interface on my model object, storing it as a bundle and trying to send it over to the fragment. However it always came up null. I believe this was due to me creating a new fragment in memory and not passing the bundle to the fragment that was displayed. I also don't have any ID's for the fragments so locating them by ID isn't possible, at least to my knowledge.
If anyone could point me in the right direction Id be greatly appreciative.
Main Activity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MAIN ACTIVITY";
#Bind(R.id.toolBar) Toolbar mToolbar;
#Bind(R.id.viewPager) ViewPager mViewPager;
#Bind(R.id.tabLayout) SlidingTabLayout mTabLayout;
private ViewPagerAdapter mAdapter;
private String mForecastsTabName = "Forecasts";
private String mAlertsTabName = "Alerts";
private String mTabTitles[] = {mForecastsTabName, mAlertsTabName};
private int mNumberOfTabs = 2;
private Forecast[] mForecasts;
private JsonParser mJsonParser = new JsonParser();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(mToolbar);
setupSlidingTabs();
}
private void setupSlidingTabs() {
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
mAdapter = new ViewPagerAdapter(getSupportFragmentManager(), mTabTitles, mNumberOfTabs);
// Assigning the ViewPages View and setting the adapter
mViewPager.setAdapter(mAdapter);
// Assigning the Sliding Tab Layout View
mTabLayout.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
// Setting Custom Color for the Scroll bar indicator of the Tab View
mTabLayout.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.ColorAccent);
}
});
mTabLayout.setViewPager(mViewPager);
}
Forecast Fragment.java
public class ForecastFragment extends Fragment {
private static final String FORECAST_KEY = "FORECAST_KEY";
private static final String TAG = "FRAGMENT";
private Forecast[] mForecasts;
#Bind(R.id.recyclerView) RecyclerView mRecyclerView;
#Bind(R.id.emptyView) TextView mEmptyView;
#Bind(R.id.locationButton) Button mLocationButton;
public static ForecastFragment newInstance(Forecast[] forecasts) {
ForecastFragment fragment = new ForecastFragment();
Bundle bundle = new Bundle();
bundle.putParcelableArray(FORECAST_KEY, forecasts);
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialize dataset, this data would usually come from a local content provider or
// remote server.
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.forecast_tab_fragment, container, false);
ButterKnife.bind(this, view);
displayEmptyViewIfNoData();
ForecastAdapter adapter = new ForecastAdapter(getActivity(), mForecasts);
mRecyclerView.setAdapter(adapter);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(layoutManager);
return view;
}
private void displayEmptyViewIfNoData() {
if (mForecasts == null || mForecasts.length < 1) {
mRecyclerView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.VISIBLE);
mLocationButton.setVisibility(View.VISIBLE);
}
else {
mRecyclerView.setVisibility(View.VISIBLE);
mEmptyView.setVisibility(View.GONE);
mLocationButton.setVisibility(View.GONE);
}
}
#OnClick(R.id.locationButton)
public void selectLocations(View view) {
Intent intent = new Intent(getActivity(), LocationSelectionActivity.class);
intent.putExtra(ActivityConstants.CALLING_ACTIVITY, ActivityConstants.FORECAST_ACTIVITY);
startActivity(intent);
}
}
ViewPagerAdapter.java
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
// This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
String mTitles[];
// Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
int mNumberOfTabs;
SparseArray<Fragment> registeredFragments = new SparseArray<>();
public ViewPagerAdapter(FragmentManager fm, String titles[], int numberOfTabs) {
super(fm);
mTitles = titles;
mNumberOfTabs = numberOfTabs;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if (position == 0) {
ForecastFragment forecastFragment = new ForecastFragment();
return forecastFragment;
}
else if (position == 1) {
AlertFragment alertFragment = new AlertFragment();
return alertFragment;
}
return null;
}
#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);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return mTitles[position];
}
#Override
public int getCount() {
return mNumberOfTabs;
}
}
Forecast_tab_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/ColorPrimaryLight">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/activity_vertical_margin"/>
<TextView
android:id="#+id/emptyView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/empty_forecast_message"
android:textColor="#color/ColorTextPrimary"
android:gravity="center"
android:visibility="gone"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="115dp"/>
<Button
android:id="#+id/locationButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button_shape"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:textColor="#color/ColorTextPrimary"
android:text="#string/add_forecast_button"
android:visibility="gone"
android:layout_alignParentBottom="false"
android:layout_centerHorizontal="true"
android:layout_below="#+id/emptyView"
android:layout_marginTop="24dp"/>
</RelativeLayout>
When you do this code below, you can hand the data to your fragment.
In your Activity, call below, when the data is ready:
mAdapter.getFragment(index).setData(dataObject);
or
mAdapter.getFragment(mViewPager.getCurrentItem()).setData(dataObject);
Your FragmentPagerAdater should be like this:
class CustomPagerAdapter extends FragmentPagerAdapter {
SparseArray<App4StoreBaseSubFragment> registeredFragments = new SparseArray<App4StoreBaseSubFragment>();
public CustomPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
App4StoreBaseSubFragment fragment = (App4StoreBaseSubFragment) 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);
}
public ForecastFragment getFragment(int position){
return registeredFragments.get(position);
}
}
Your Fragment should be like this:
public class ForecastFragment extends Fragment {
public void setData(Forecast forecast){
//write code here to change UI
}
}
I am new to android. I have a sliding tab layout and a viewpager with a fragment. I have setup a basic link between these to switch tabs for a count of 5(i.e 5 tabs) The problem is that, in each of these tabs, I want to populate a listview using simplecursoradapter, for which I need the position of each fragment so that I could populate it accordingly. I have got the position in the fragment adapter class, but I am unable to pass it to the main activity. Also, How can I access DBadapter inside my fragment class to populate listview from the database? or is there some other way to do this? Below is my code. Any help is greatly appreciated. Thanks in advance.
public class myFragment extends Fragment{
private ListView mainList;
public static myFragment getInstance(int position){
myFragment MyFragment = new myFragment();
Bundle args = new Bundle();
args.putInt("position", position);
MyFragment.setArguments(args);
return MyFragment;
}
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_main_list,container, false);
mainList = (ListView)layout.findViewById(R.id.mainListView);
Bundle bundle = getArguments();
if(bundle!=null){
if(bundle.getInt("position")==0){
mainList.setBackgroundColor(getResources().getColor(R.color.primary500));
}
else if(bundle.getInt("position")==1){
mainList.setBackgroundColor(getResources().getColor(R.color.primary100));
}
else if(bundle.getInt("position")==2){
mainList.setBackgroundColor(getResources().getColor(R.color.primary700));
}
else if(bundle.getInt("position")==3){
mainList.setBackgroundColor(getResources().getColor(R.color.accent));
}
else if(bundle.getInt("position")==4){
mainList.setBackgroundColor(getResources().getColor(R.color.black));
}
}
return layout;
}
}
The Main Activity is as follows:
public class MainActivity extends ActionBarActivity {
private Toolbar toolbar;
private ViewPager mPage;
private SlidingTabLayout mTabs;
DBadapter myDb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
openDB();
toolbar = (Toolbar)findViewById(R.id.app_bar);
mPage = (ViewPager)findViewById(R.id.pager);
mTabs = (SlidingTabLayout)findViewById(R.id.tabs);
mFab = (FloatingActionButton)findViewById(R.id.fab);
setSupportActionBar(toolbar);
mPage.setAdapter(new myPagerAdapter(getSupportFragmentManager()));
mTabs.setViewPager(mPage);
}
public class myPagerAdapter extends FragmentPagerAdapter{
String[] tabs;
public myPagerAdapter(FragmentManager fm) {
super(fm);
tabs = getResources().getStringArray(R.array.tabs);
}
#Override
public Fragment getItem(int position) {
myFragment MyFragment = myFragment.getInstance(position);
return MyFragment;
}
#Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
#Override
public int getCount() {
return 5;
}
}
Use this method :
mPage.setOnPageChangeListener(new SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int pos) {
// pos is the position of fragment that app showing
});
UPDATE
in your view pager adapter :
public Fragment getItem(int position) {
return new myFragment(position);
}
And in your fragment class :
public class myFragment extends Fragment{
private int pos
public void myFragment(int position){
this.pos = position;
}
// other code of your class