Subclassed fragment onCreateView - java

for the sake of not duplicating the code I've decided in my program to create a BaseFragment (which extends Fragment) to hold for some boilerplate data and provide proper handling of pause/resume, as well as the newInstance(String myPram) method. Long story short: The role of the BaseFragment is to ensure the saving and restoring of the state, i.e. restoring myPramas a local variable...
What I wanted to do next was to extend that BaseFragment in order to handle two different types of layout for two different Fragments (each of the needs the handling of the MyParam filed): EditFragment and DetailFragment.
The problem arises now, because no View is inflated for the Fragment, though they are added as a transaction (so they are transparent!).
EditFragment and DetailFragment both provide the onCreateView() method, in order to build their own views, I am they are correct since I managed to create them without the "subclassing mechanism", and of course BaseFragment does not provide an implementation of the onCreateView() but no result, they draw no UI.
I tried putting some super.onCreateView() here and there, with no result as well...What am I doing wrong?
Here's the base Fragment:
public class TimetableBaseFragment extends Fragment {
public static String ID_FIELD = "id";
public static String ID_DESC = "desc";
private String id;
private String desc;
// Constructor to deliver previous position along with itself
public static Fragment newInstance(String id, String desc) {
TimetableBaseFragment f = new TimetableBaseFragment();
Bundle args = new Bundle();
args.putString(ID_FIELD, id);
args.putString(ID_DESC, desc);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
id = args.getString(ID_FIELD);
desc = args.getString(ID_DESC);
}
if (savedInstanceState != null) {
id = savedInstanceState.getString(ID_FIELD);
desc = savedInstanceState.getString(ID_DESC);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(ID_FIELD, id);
outState.putString(ID_DESC, desc);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
id = savedInstanceState.getString(ID_FIELD);
desc = savedInstanceState.getString(ID_DESC);
}
}
public String getExamId() {
return id;
}
public String getExamDesc() {
return desc;
}
}
And the one I am trying to add is:
public class TimetableEditFragment extends TimetableBaseFragment {
private LinearLayout mLlEditEmpty;
private ArrayList<ScheduleUser> lessons;
private TimetableEditRecyclerViewAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lessons = new ArrayList<>();
mAdapter = new TimetableEditRecyclerViewAdapter(getActivity());
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_timetable_edit, container, false);
mLlEditEmpty = (LinearLayout) rootView.findViewById(R.id.LOGIC_empty);
RecyclerView mRvEdit = (RecyclerView) rootView.findViewById(R.id.HEADER_rv);
mRvEdit.setHasFixedSize(true);
mRvEdit.setLayoutManager(new LinearLayoutManager(getActivity()));
mRvEdit.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
mRvEdit.setAdapter(mAdapter);
Toolbar examDesc = (Toolbar) rootView.findViewById(R.id.HEADER_examDesc);
examDesc.setTitle("TOOLBAR Testing");
FloatingActionButton add_fab = (FloatingActionButton) rootView.findViewById(R.id.EDIT_fab);
add_fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addLesson(new ScheduleUser());
}
});
return rootView;
}
public void addLesson(ScheduleUser newItem) {
lessons.add(newItem);
mAdapter.notifyItemInserted(lessons.size() - 1);
}
public class TimetableEditRecyclerViewAdapter extends RecyclerView.Adapter<TimetableEditRecyclerViewAdapter.ViewHolder> {
/* Lots of stuff */
}
}
PS: I've noticed that it's very likely that the child onCreateView() does not get called at all, since I had an error, which was due to be fund at runtime, but the system did not notify.
Please help!

Related

Dialog on close: Keep the view changes

This is my dialog:
#SuppressLint("ValidFragment")
public class Popup extends DialogFragment {
private final int _layout;
#SuppressLint("ValidFragment")
public Popup(int layout) {
_layout = layout;
}
#SuppressLint({"ClickableViewAccessibility", "ResourceType"})
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Nullable
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(_layout, container, false);
return view;
}
And this is how I invoke it:
public class MainActivity extends AppCompatActivity implements View.OnClickListener, Popup.ICustomTts, Popup.ITarget, Popup.IDialog, Popup.IControl {
private final Popup mPopupTurbine = new Popup(R.layout.fragment_turbine);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button turbineBtn = findViewById(R.id.turbine);
turbineBtn.setOnClickListener(view -> {
mPopupTurbine.show(getSupportFragmentManager(), "Speak");
});
When I click outside of that dialog, it will be closed. The problem is, I do some changes in that dialog (e.g. typed a text in TextView) and then I close that dialog. When I want to show it again, all the changes are lost. So how can I just hide the dialog so that the changes are still there when I re-display it?
I think in MainActivity I could add mPopupTurbine.getDialog().hide(); but where do I add this line of code?
You can use a ViewModel that lives throughout the life of your activity and remember your Popup fragment lives inside your activity.
Every time you make a change inside Popup save that data in a LiveData or Flow. Observe the LiveData inside Popup and update your UI.
You can post back entered data to your MainActivity:
#SuppressLint("ValidFragment")
public class Popup extends DialogFragment {
public Popup() {
// fragment constructor must be empty
}
private static final String LAYOUT_ID_KEY = "LAYOUT_ID_KEY";
private static final String PARAM1_KEY = "PARAM1_KEY";
public static Popup newInstance(int layoutId, String initialParam1) {
Popup popup = new Popup();
Bundle bundle = new Bundle();
bundle.putInt(LAYOUT_ID_KEY, layoutId);
bundle.putString(PARAM1_KEY, initialParam1);
popup.setArguments(bundle);
return popup;
}
private PopupCallback popupCallback;
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
popupCallback = (PopupCallback) context;
}
#Nullable
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
int layoutId = getArguments().getInt(LAYOUT_ID_KEY);
final View view = inflater.inflate(layoutId, container, false);
EditText editText = view.findViewById(R.id.edittext);
// set latest value of param1
editText.setText(getArguments().getString(PARAM1_KEY));
return view;
}
#Override
public void onDismiss(#NonNull DialogInterface dialog) {
EditText v = getView().findViewById(R.id.edittext);
// post back the param1
popupCallback.onDismissPopup(v.getText().toString());
super.onDismiss(dialog);
}
interface PopupCallback {
void onDismissPopup(String param1);
}
}
and receive and keep them in MainActivity:
public class MainActivity extends AppCompatActivity implements Popup.PopupCallback {
private String param1Backup;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button turbineBtn = findViewById(R.id.turbine);
turbineBtn.setOnClickListener(view -> {
Popup.newInstance(R.layout.fragment_turbine, param1Backup).show(getSupportFragmentManager(), "Speak");
});
}
#Override
public void onDismissPopup(String param1) {
param1Backup = param1;
}
}
Use viewModel to save your current values and attach the lifecycle of viewModel with your activity to save the current state.
Purpose of viewModel is to survive the configuration changes in your app.
You can use Singleton Class to save those data temporarily and moment you invoke it check if you have saved any data in it and put it back in your dialog.
public class SingletonClass{
public boolean isDialogDone;
public string dialogTitle, dialogMsg;
public static SingletonClass getInstance(){
if (instance == null) {
synchronized(SingletonClass.class) {
if (instance == null) {
instance = new SingletonClass();
}
}
}
return instance;
}
}
Then while invoking your dialogBox, you can simply check
if(!SingletonClass.getInstance().isDialogDone){
editText.setText(SingletonClass.getInstance().dialogMsg);
}
Ofc you also need to add listener to your EditText so that you can save the msg user is typing.

How to handle configuration change for fragment with view model

I want to make my fragment wont re-load the data when configuration change with view model.
So, i try to make an App about gitHub User.
My Main Activity contain Search view to search user and show the result with recyclerview.
My Detail Activity is showing the detail of user when one of user in the list clicked, and in my detail activity i use Tab Layout and view pager to show user's followers and following.
My ViewModel for activity works well and can keep my data when orientation change.
But when i do the same to my fragment, my fragment keep re-loading new data when orientation change.
Here my fragment
i use View Model to request data
public class FollowingFragment extends Fragment {
public static final String KEY_FOLLOWING = "key_following";
private RecyclerView recyclerView;
private FollowingViewModel followingViewModel;
private FollowingAdapter followingAdapter;
ShimmerFrameLayout shimmerFrameLayout;
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
ArrayList<FollowingResponse> followingResponse = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_following, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.rv_following);
shimmerFrameLayout = view.findViewById(R.id.shimmer_frame_layout2);
followingViewModel = ViewModelProviders.of(this).get(FollowingViewModel.class);
followingAdapter = new FollowingAdapter();
followingAdapter.setOnItemClickCallback(new FollowingAdapter.OnItemClickCallback() {
#Override
public void onItemClicked(FollowingResponse followingResponse) {
showSelectedItem(followingResponse);
}
});
//this is what i've tried and worked, but my fragment result with double or triple the data.
if (savedInstanceState == null){
}
else {
followingResponse = savedInstanceState.getParcelableArrayList(KEY_FOLLOWING);
}
showRecyclerView();
getData();
}
private void getData() {
followingViewModel.setDataFollowing(DetailUserActivity.clickedUser);
followingViewModel.getDataFollowing().observe(getViewLifecycleOwner(), new Observer<ArrayList<FollowingResponse>>() {
#Override
public void onChanged(ArrayList<FollowingResponse> followingResponses) {
shimmerFrameLayout.setVisibility(View.GONE);
shimmerFrameLayout.stopShimmer();
followingAdapter.setData(followingResponse);
followingResponse.addAll(followingResponses);
recyclerView.setAdapter(followingAdapter);
followingAdapter.notifyDataSetChanged();
}
});
}
private void showRecyclerView() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
}
#Override
public void onResume() {
super.onResume();
followingViewModel.setDataFollowing(DetailUserActivity.clickedUser);
}
private void showSelectedItem(FollowingResponse item) {
Intent intent = new Intent(getContext(), DetailUserActivity.class);
intent.putExtra("EXTRA_DATA", item.getLogin());
startActivity(intent);
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
outState.putParcelableArrayList(KEY_FOLLOWING, followingResponse);
super.onSaveInstanceState(outState);
}
}
Detail Activity
public class DetailUserActivity extends AppCompatActivity {
private TextView tvName, tvNickname, tvLocation, tvCompany, tvEmail, tvWebsite;
private TextView tvCountFollowers, tvCountRepository, tvCountFollowing;
private ImageView imgProfile;
ProgressBar progressBar;
public static String clickedUser;
UserViewModel userViewModel;
private ViewPager viewPager;
TabLayout tabLayout;
private final String EXTRA_DATA = "EXTRA_DATA";
private static final String EXTRA_FOLLOW = "extra_follow";
// Fragment followingFragment;
// FragmentTransaction transaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail_user_activity);
// i've tried this, but when the orientation change, my detail activity force close and throw me to my main activity.
// if (savedInstanceState != null){
// followingFragment = getSupportFragmentManager().getFragment(savedInstanceState, KEY_FOLLOWING);
// } else {
// followingFragment = new FollowingFragment();
//
// getSupportFragmentManager().beginTransaction().replace(R.id.tv_view_pager, followingFragment).commit();
// }
tvName = findViewById(R.id.tv_item_name);
tvNickname = findViewById(R.id.tv_item_nickname);
tvLocation = findViewById(R.id.tv_item_location);
tvCompany = findViewById(R.id.tv_item_company);
tvEmail = findViewById(R.id.tv_item_email);
tvWebsite = findViewById(R.id.tv_item_website);
imgProfile = findViewById(R.id.img_item_photo);
tvCountFollowers = findViewById(R.id.tv_count_follower);
tvCountRepository = findViewById(R.id.tv_count_repo);
tvCountFollowing = findViewById(R.id.tv_count_following);
progressBar = findViewById(R.id.progressbar2);
setForUserData();
setForTabLayout();
}
private void setForUserData(){
Intent detailIntent = getIntent();
clickedUser = detailIntent.getStringExtra("EXTRA_DATA");
userViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(UserViewModel.class);
userViewModel.setUserUVM(clickedUser);
userViewModel.getUserUVM().observe(this, new Observer<UserResponse>() {
#Override
public void onChanged(UserResponse userResponse) {
progressBar.setVisibility(View.GONE);
Glide.with(getApplicationContext())
.load(userResponse.getAvatarUrl())
.into(imgProfile);
tvName.setText(userResponse.getLogin());
tvLocation.setText(userResponse.getLocation());
tvNickname.setText(userResponse.getName());
tvCompany.setText(userResponse.getCompany());
tvEmail.setText(userResponse.getEmail());
tvWebsite.setText(userResponse.getBlog());
tvCountRepository.setText(String.valueOf(userResponse.getPublicRepos()));
tvCountFollowers.setText(String.valueOf(userResponse.getFollowers()));
tvCountFollowing.setText(String.valueOf(userResponse.getFollowing()));
}
});
}
private void setForTabLayout(){
tabLayout = findViewById(R.id.tv_tab_layout);
viewPager = findViewById(R.id.tv_view_pager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount()));
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setTabMode(TabLayout.MODE_FIXED);
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 ViewPagerAdapter extends FragmentStatePagerAdapter {
int totalTab;
#SuppressWarnings("deprecation")
ViewPagerAdapter(FragmentManager fragmentManager, int totalTabs) {
super(fragmentManager);
this.totalTab = totalTabs;
}
#SuppressWarnings("ConstantConditions")
#NonNull
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new FollowersFragment();
case 1:
return new FollowingFragment();
default:
return null;
}
}
#Override
public int getCount() {
return totalTab;
}
}
// #Override
// protected void onSaveInstanceState(#NonNull Bundle outState) {
// getSupportFragmentManager().putFragment(outState, KEY_FOLLOWING, followingFragment );
// super.onSaveInstanceState(outState);
// }
}
im trying to solve my FollowingFragment first, then ill do the same on my FollowerFragment.
im really new in programming, and have no one to ask.. can someone help me to solve my problem with keep data in fragment when orientation change?
followingViewModel = ViewModelProviders.of(this).get(FollowingViewModel.class);
In Fragment insted of writing this code in onViewCreated() write it inside OnCreate()
onViewCreated() will get called everytime the orientation changes so it will create new instance of view model everytime the orientation changes making viewmodel to reload the data
If you need to load data only once for the FollowingViewModel a good place to do it should be inside the constructor of the view model in this way you won't need to worry about the orientation change of the fragment.

Parse Recyclerview Data between fragments

I have a recyclerview in a fragment which displays a list of movies. i want to when user clicks item, it opens a new fragment which will be detailed page of that item.
I have tried bundles and intent putExtra but does not work, keeps coming up with null pointer error.
i have tried with Hardcoded strings as a test and works fine but trying to get item POJO data does not.
Anyone have an idea how to parse data between fragments from recyclerview onclick function?
1st Fragment which displays recyclerview data:
public class HomeFragment extends Fragment {
private static final String TAG = HomeFragment.class.getSimpleName();
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private MovieAdapter mAdapter;
private List<Movie> movieList;
private TextView title;
private final static String API_KEY = "670d03a721dd007862c0181bfd097e5d";
public HomeFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
// Inflate the layout for this fragment
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.movies_recycler_view);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getContext(), new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
FragmentTransaction fragTrans = getFragmentManager().beginTransaction();
MovieDetail movieDetail = new MovieDetail();
//Bundle Send Data
Bundle bundle = new Bundle();
bundle.putString("title", movieList.get(position).getTitle());
movieDetail.setArguments(bundle);
fragTrans.replace(R.id.container_body, movieDetail);
fragTrans.isAddToBackStackAllowed();
fragTrans.addToBackStack(null);
fragTrans.commit();
}
}));
return rootView;
}
private void initData() {
ApiInterface api = ApiClient.getClient().create(ApiInterface.class);
Call<MovieResponse> call = api.getMostPopularMovies(API_KEY);
call.enqueue(new Callback<MovieResponse>() {
#Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
int statusCode = response.code();
List<Movie> movies = response.body().getResults();
mRecyclerView.setAdapter(new MovieAdapter(movies, R.layout.list_item_movie, getContext()));
}
#Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
Log.d(TAG, t.toString());
}
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
}
Detail Fragment:
public class MovieDetail extends Fragment {
private TextView titleTv;
public MovieDetail() {
// Required empty public constructor
}
#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_movie_detail, container, false);
titleTv = (TextView) view.findViewById(R.id.detailTitleTV);
Bundle bundle = getArguments();
titleTv.setText(String.valueOf(bundle.getString("title")));
return view;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
/**
* .
*/
}
i have looked at other questions similar but they deal with hardcoded Strings not POJO data for item click. Any help appreciated
You should create a class which extends parcelable and then pass the object in the bundle, then access each field with get methods.

How to deal with bad_alloc in android java

I am using a ViewPager to show fragments. When i swipe it multiple times it gives following error:
E/libc++abi: terminating with uncaught exception of type std::bad_alloc: std::bad_alloc
--------- beginning of crash
A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 6900
I am showing and caching image (using this) as well as i am using TextView to show text on Fragment.
I tried to get help from other links but could not get succeed.
I tried to duplicate your issue on my side, however I'm not getting the error but the images are not loaded. But the files got cached in my internal storage. By the way, in your case, it is advisable to use Picasso or Universal Image Loader as those libraries will handle loading, caching and even error. This may not be your direct solution to your problem, but just in case if you're looking for alternative, you can try this solution.
For the sake of simplicity, I am using Picasso. I have created an example project just in case if you need reference. You need to add compile 'com.squareup.picasso:picasso:2.5.2' in your gradle dependency;
1) Fragment
public class FragmentImage extends Fragment {
private TextView imageName;
private ImageView image;
public static final String IMAGE_URL = "link";
public static final String POSITION = "position";
private String url = null;
private int position = 0;
public static FragmentImage newInstance(String link, int position) {
// Required empty public constructor
FragmentImage fragmentImage = new FragmentImage();
Bundle bundle = new Bundle();
bundle.putString(IMAGE_URL, link);
bundle.putInt(POSITION, position);
fragmentImage.setArguments(bundle);
return fragmentImage;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(null != getArguments()){
url = getArguments().getString(IMAGE_URL);
position = getArguments().getInt(POSITION);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_fragment_image, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
image = (ImageView)view.findViewById(R.id.image);
imageName = (TextView)view.findViewById(R.id.imageName);
imageName.setText("Position "+position);
Picasso.with(getActivity())
.load(url)
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(image);
}
}
2) FragmentAdapter
public class FragmentImagePager extends FragmentPagerAdapter {
private String[] imageUrls = {"https://www.ricoh.com/r_dc/caplio/r7/img/sample_04.jpg",
"http://i-cdn.phonearena.com/images/articles/47012-image/photo2.jpg",
"http://www.flooringvillage.co.uk/ekmps/shops/flooringvillage/images/request-a-sample--547-p.jpg",
"http://www.cameraegg.org/wp-content/uploads/2013/03/Canon-EOS-100D-Rebel-SL1-Sample-Image.jpg",
"http://imgsv.imaging.nikon.com/lineup/lens/singlefocal/wide/af-s_35mmf_14g/img/sample/sample4_l.jpg"};
public FragmentImagePager(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return FragmentImage.newInstance(imageUrls[position], position);
}
#Override
public int getCount() {
return imageUrls.length;
}
}
3) Activity
public class MainActivity extends AppCompatActivity{
private ViewPager fragmentList;
private FragmentImagePager fragmentImagePager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentList = (ViewPager)findViewById(R.id.fragmentList);
fragmentImagePager = new FragmentImagePager(getSupportFragmentManager());
fragmentList.setAdapter(fragmentImagePager);
fragmentList.setOffscreenPageLimit(fragmentImagePager.getCount());
}
}

communicating between fragments when only one of them is visible

I have a problem with comuunicating between fragments that are chnged dynamicaly, i mannaged to use the interface system to cimmunicate if the fragments are all viewble but when i am viewing them sepretly i can't use a their actions since they dont have a tag yet, any thoughts?
main activty
public class MainActivity extends FragmentActivity implements OnClickListener, Communicator {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (isSingleFragment()) {
Button btn_color = (Button) findViewById(R.id.button_color);
Button btn_text = (Button) findViewById(R.id.button_text);
Button btn_list = (Button) findViewById(R.id.button_list);
btn_color.setOnClickListener(this);
btn_list.setOnClickListener(this);
btn_text.setOnClickListener(this);
singleFragActions();
} else {
doubleFragActions();
}
// some more stuff happens
#Override
public void apply(String data) {
Log.d("data", data+"");
FragmentManager fm = getSupportFragmentManager();
Frag_list frag_list = (Frag_list) fm.findFragmentByTag("list");
//i cannot use id because the fragment in
//MainActivity are in a layout and are enterd dynamicaly
frag_list.addItem(data);
}
three fragments here, when on small screen, on is shown and three button on the top change them arrounf, if on tablet, all three are displyed, this is the interface
public interface Communicator {
public void apply(String data);
}
frag_text (first fragment)
public class Frag_text extends Fragment implements OnClickListener{
Communicator comm;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// stuff
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
comm = (Communicator) getActivity();
}
#Override
public void onClick(View v) {
EditText input = (EditText) getView().findViewById(R.id.frag_text_edit);
TextView output = (TextView) getView().findViewById(R.id.frag_text_show);
String text_get = input.getText().toString();
output.setText("hello "+text_get+" how are you today?");
comm.apply(text_get);
}
}
frag_list (other fragment)
public class Frag_list extends Fragment{
ArrayList<String> list;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_list, container, false);
list = new ArrayList<String>();
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, list);
ListView lv = (ListView) view.findViewById(R.id.list_frag);
lv.setAdapter(adapter);
return view;
}
public void addItem(String data){
list.add(data);
}
}
how to i access the other fragment if it doesnt have a tag yet?
If you happen to know what fragment you will be calling then FragmentActivity could act as a mediator in this case, as it is a mere "host". You already have this Communicator interface. Have it communicate to a given fragment:
public interface Communicator {
public void apply(String data, String tag);
}
And the override:
#Override
public void apply(String data, String tag) {
FragmentManager fm = getSupportFragmentManager();
Frag_list frag_list = (Frag_list) fm.findFragmentByTag(tag);
//Fallback plan in case the fragment has not been created.
if(frag_list == null) {
frag_list = new Frag_list();
//Include the fragment for future reference.
//This fragment has no view
fm.beginTransaction().add(frag_list, tag);
}
frag_list.addItem(data);
}
And modify the fragment to always have the list available:
public class Frag_list extends Fragment{
ArrayList<String> list = new ArrayList<String>();
//...
public void addItem(String data){
//Add check to avoid problems
if(list != null) {
list.add(data);
}
}
}

Categories