Accessing a list from a different fragment - java

So I have my MainActivity.java, I also have a FragmentA.java and a FragmentB.java.
In my MainActivity I have a BottomNavigation which allows me to switch between the two fragments.
MainActivity.java
private BottomNavigationView.OnNavigationItemSelectedListener navListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Fragment selectedFragment = null;
switch (menuItem.getItemId()) {
case R.id.nav_a:
selectedFragment = new FragmentA();
break;
case R.id.nav_b:
selectedFragment = new FragmentB();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, selectedFragment).commit();
return true;
}
};
Inside FragmentA I have a RecyclerView with an adapter of course and on each CardView there is a button, when i click that button i want to pass the corresponding object to the RecyclerView in FragmentB.
FragmentA.java
adapter.setOnItemClickListener(new RewardItemAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
//When I click the item, pass theItem to FragmentB
CustomObject theItem = items.get(position);
}
});
FragmentB.java
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_b, container, false);
itemsList = new ArrayList<>();
itemsList.add(new CustomObject(R.drawable.picture, "Text", "More text.", 200));
//I'm guessing I want to add the CustomObject that I clicked to the list here so that I can display it in the RecyclerView
recyclerView = v.findViewById(R.id.fragmentBRecyclerView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getContext());
adapter = new FragmentBItemAdapter(itemsList);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
return v;
}
The only issue is I have no idea how to, I tried using Interfaces but I couldn't implement it properly, I'm not sure if it's because I am instantiating a new instance of the fragments.

You could achieve this by two ways:
1) Through Interface Contract between the Fragment and Activity
class FragmentA: Fragment() {
interface SomeInterfaceName {
fun setSelectedItem(item: SomeItem)
}
}
class FragmentA: Fragment() {
interface AnotherInterfaceName {
fun getSelectedItem(): SomeItem
}
}
class ContainerActivity: Activity(), AnotherInterfaceName, SomeInterfaceName {
var someItem: SomeItem? = null
fun setSelectedItem(item: SomeItem) {
someItem = item
// inflate your FragmentB
}
fun getSelectedItem(): SomeItem {
return someItem;
}
}
But the best solution in my opinion is to use a shared ViewModel for this case.
You can read about this he here under "Share data between fragments" section.

Doing the job by interface is correct, But you have to bind it to the Fragment in the onAttached lifeCycle method.
Define an Interface. OnFragmentInteractionListener.java
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(String args);
}
Then Implement your activity with the interface.
public class MainActivity extends ActionBarActivity implements OnFragmentInteractionListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
onFragmentInteraction(String args){
**// Made the Change Here**
// Send Local Broadcast Receiver
Intent intent = new Intent("UPDATE_LIST");
intent.putExtra("TYPE", 0);
// Change the args to get position or the relevant param
intent.putExtra("POSITION", selectedPosition);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
In the FragmentA.java,
public class FragmentA extends Fragment {
OnFragmentInteractionListener mCallback;
#Override
public void onAttach(Context context) {
super.onAttach(context);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnFragmentInteractionListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
...
adapter.setOnItemClickListener(new RewardItemAdapter.OnItemClickListener()
{
#Override
public void onItemClick(int position) {
//When I click the item, pass theItem to FragmentB
CustomObject theItem = items.get(position);
// Send the selected Item Name to Main Activity through args
mCallback.onFragmentInteraction(theItem.getName);
}
});
}
On your FragmentB.java class add Local Broadcast Receiver
public class FragmentBt extends Fragment{
public static Fragment newInstance(){
...
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.layout, container, false);
return v;
}
...
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
// Register Local Broadcast Receiver
LocalBroadcastManager.getInstance(getContext()).registerReceiver(mMessageReceiver, new IntentFilter("UPDATE_LIST"));
}
#Override
public void onDestroy() {
super.onDestroy();
// Destroy the Local Broadcast Receiver
LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mMessageReceiver);
}
// Create Broadcast Receiver instance
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.hasExtra("POSITION")){
mAdapter.notifyItemChanged(intent.getIntExtra("POSITION", 0));
// Update Adapter as the requirement
}
}
};
}
Hope this will help.
Cheers!!

Related

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.

How to sort adapter from another fragment

I have RecyclerView on LightsFragment, and I want to sort it from the MainActivity which contain this fragment.
Here is what I have now:
Thats the function that sorting my adapter:
Collections.sort(lights);
lightsAdapter.updateData(lights);
LightsFragment - handling the adapter that should be sorted.
public class LightsFragment extends Fragment implements LightsPresenter, View.OnClickListener {
private RecyclerView RVLights;
private ArrayList<Light> lights = new ArrayList<>();
private Light light;
private LightsAdapter lightsAdapter;
private LightsView presenter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_lights, container, false);
presenter = new LightsView(lights, light, this);
RVLights = view.findViewById(R.id.RVLights);
presenter.loadData();
return view;
}
#Override
public void setAdapter() {
lightsAdapter = new LightsAdapter(getActivity(), lights);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), 3);
RVLights.setLayoutManager(layoutManager);
RVLights.setAdapter(lightsAdapter);
}
}
MainActivity - handling 3 buttons, one of the buttons should sort adapter.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Greetings mGreetings = new Greetings();
private TextView mTVgreetings;
private Button BTNmLights, BTNmGarage, BTNmSortBy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
mTVgreetings = findViewById(R.id.TVgreetings);
initFunctions();
}
public void showLightsFragment() {
getSupportFragmentManager().beginTransaction().add(R.id.main_fragment_container, new LightsFragment())
.commit();
}
public void initFunctions() {
showLightsFragment();
showGreetings();
}
public void showGreetings() {
mTVgreetings.setText(mGreetings.getGreetings());
}
public void initView() {
BTNmLights = findViewById(R.id.BTNlights);
BTNmGarage = findViewById(R.id.BTNgarage);
BTNmSortBy = findViewById(R.id.BTNsort);
BTNmLights.setOnClickListener(this);
BTNmGarage.setOnClickListener(this);
BTNmSortBy.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.BTNlights:
//TODO open lights fragment...
break;
case R.id.BTNgarage:
//TODO open garage fragment...
break;
case R.id.BTNsort:
//TODO make drop down with sort light and garage.
break;
}
}
}
I want that when i pressing on sort button on main activity,
the adapter from LightsFragment will be sorted.
I already have a function that sorting adapter.
Just don't know how to access the adapter from the Main activity.
Store the Fragment instance in Activity and access it any time.
private LightsFragment lightsFragment= new LightsFragment();
public void showLightsFragment() {
getSupportFragmentManager()
.beginTransaction().add(R.id.main_fragment_container, this.lightFragment)
.commit();
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.BTNlights:
//TODO open lights fragment...
break;
case R.id.BTNgarage:
//TODO open garage fragment...
break;
case R.id.BTNsort:
this.lightFragment.sortLights()
//TODO make drop down with sort light and garage.
break;
}
}
and in your LightFragment you should have a method to find the RecylerView and get it's adapter to update the list and notifyDataSetChanged
First, create a getter method for your LightsAdapter in Fragment.
After, get the fragment in the mainActivity with the help of
Fragment yourFragment=getSupportFragmentManager().findFragmentById(R.id.main_fragment_container);
Later, check if the fragment is your fragment or not:
if(yourFragment instanceOf LightsFragment)
{
yourFragment.getAdapter();
}
You can do that using interface.
create an interface like
public interface UpdateFrag {
void sortAdapter(int sortType);
}
In your Activity do the following
UpdateFrag updatFrag ;// add this line
public void showLightsFragment() {
Fragment lightsFragment = new LightsFragment();
updatFrag = lightsFragment; // here you initialize updatFrag
fragment.getSupportFragmentManager().beginTransaction().add(R.id.main_fragment_container, lightsFragment)
.commit();
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.BTNlights:
break;
case R.id.BTNgarage:
//TODO open garage fragment...
break;
case R.id.BTNsort:
// here you should call sortAdapter method.
updatFrag.sortAdapter(1) // suppose 1 for light and 2 for garage
break;
}
}
Now in your LightsFragment implement the interface.
public class LightsFragment extends Fragment implements LightsPresenter, View.OnClickListener, UpdateFrag {
// ....
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// ....
}
#Override
public void setAdapter() {
// ....
}
#Override
public void sortAdapter(int sortType) {
if (sortType == 1){
// here you can sort your adapter according to light
}else{
// here you can sort your adapter according to garage
}
}
}

How can I pass a ArrayList<String> created in a fragment to the main activity

I have a drawer menu with 3 items (Restaurant, Movie, Food). They are basically 3 to do lists. Each list has its on fragment and in the view there is a way to add items to the list.
The restaurant list, the movie list ad the groceries list.
I need to be able to share that list (via any share-channel) by clicking the share icon that is in the toolbar.
This is my fragment where i populate the items list that i want to use when i click the share icon that is on the toolbar. Basically i need to pass "items" to the MainActivity and use it.
package com.example.mylists;
import android.content.Intent;
public class FoodFragment extends Fragment {
public FoodFragment() {
// Required empty public constructor
}
private ArrayList<String> items;
private ArrayAdapter<String> itemsAdapter;
private ListView lvItems;
private static final String TAG = "FoodFragment";
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.i(TAG, "in on onCreateView ");
View view = inflater.inflate(R.layout.fragment_food, container, false);
lvItems = (ListView) view.findViewById(R.id.lvItems);
items = new ArrayList<String>();
readItems();
itemsAdapter = new ArrayAdapter<String>(view.getContext(),android.R.layout.simple_list_item_1, items);
lvItems.setAdapter(itemsAdapter);
if (items.isEmpty())
items.add("Dummy Item");
final EditText newTask = (EditText) view.findViewById(R.id.etNewItem);
Button btnAdd = (Button) view.findViewById(R.id.btnAddItem);
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String itemText = newTask.getText().toString();
itemsAdapter.add(itemText);
newTask.setText("");
writeItems();
Log.i(TAG, "in on send data ");
}
});
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
Log.i(TAG, "in on onViewCreated ");
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.i(TAG, "in on onActivityCreated ");
super.onActivityCreated(savedInstanceState);
OnItemLongClickListener listener = new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position, long id) {
//Log.i(TAG, "in on onItemLongClick ");
//Toast.makeText( getActivity().getBaseContext() , "Long Clicked " , Toast.LENGTH_SHORT).show();
items.remove(position);
itemsAdapter.notifyDataSetChanged();
writeItems();
//return true;
return false;
}
};
lvItems.setOnItemLongClickListener(listener);
}
private void readItems() {
File filesDir = getContext().getFilesDir();
File todoFile = new File(filesDir, "todo.txt");
try {
items = new ArrayList<String>(FileUtils.readLines(todoFile));
} catch (IOException e) {
items = new ArrayList<String>();
}
}
private void writeItems() {
File filesDir = getContext().getFilesDir();
File todoFile = new File(filesDir, "todo.txt");
try {
FileUtils.writeLines(todoFile, items);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You should declare ArrayList<String> items in your MainActivity. Then create a public setter method for items.
public void setItems(ArrayList<String> items){
this.items = items;
}
Then you should call setItems() method in your fragment.
((MainActivity) getActivity()).setItems(items);
Interface for Callback
interface MyInterface {
void setItems(ArrayList<String> items);
}
In your activity:
class MyActivity {
ArrayList<String> items;
MyInterface itemsCallback = new MyInterface(){
#Override
void setItems(ArrayList<String> items){
this.items = items;
}
}
myFragment.setItemsCallback(itemsCallback);
}
And then in fragment
class MyFragment {
private MyInterface itemsCallback;
public void setItemsCallback(MyInterface itemsCallback){
this.itemsCallback = itemsCallback;
}
private void readItems(){
...
itemsCallback.setItems(items);
}
}
I guess it's better then public setter in MainActivity. Because, you know, it's like more SOLID code. In this case your Fragment doesnt hold reference to Activity and doesnt even know about it existence.
1.Define an interface , 2.Let your Activity implements the interface 3.use (interface)getActivity() to cast your Activity to that interface,then you can call the method in the interface to send your ArrayList "items"

How to implement listener interface in fragment?

I am trying to communicate between an activity and the fragment that sits on top of it, I want new data (image/text - retrieved from the db) to be passed into the frag every time an onclick occurs (onclick is in the activity). I made a simple interface to test (let me know if this is not suitable for images or if it is too slow or inefficient), and I am trying to have it included in my fragment so when an onclick occurs the fragment changes the image and the text.
Here is the simple interface code:
public interface FragmentCommunicator {
public void passDataToFragment(String someValue);
}
Here is the activity code:
public class RandomActivity extends FragmentActivity implements ActivityCommunicator {
//viewpager adapter
private PageAdapter mAdapter;
private ViewPager viewPager;
//interface through which communication is made to fragment
public FragmentCommunicator fragmentCommunicator;
//Buttons for yes, no, skip
Button btnYesRandom, btnNoRandom, btnSkipRandom;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_random);
//set buttons
btnYesRandom = (Button) findViewById(R.id.btnYesRandom);
// Initializing pager
viewPager = (ViewPager) findViewById(R.id.random_pager);
//calling bundle to attach data to fragment
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
RandomFragment randFrag = new RandomFragment();
randFrag.setArguments(bundle);
//Setting up fragment
FragmentManager fm = getFragmentManager();
mAdapter = new PageAdapter(getSupportFragmentManager(), new UserUpVotesFragment(), randFrag, new UserDownVotesFragment());
viewPager.setAdapter(mAdapter);
// Here you would declare which page to visit on creation
viewPager.setCurrentItem(1);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
public void onPageSelected(int position) {
// Check if this is the page you want.
if(position !=1) {
//swiping to the right
if(position == 0) {
Log.e("Swiping", "SWIPING TO THE Right BUT RESET ERR");
getIntent().removeExtra("edttext");
}
//swiping to the left
if(position == 2) {
Log.e("Swiping", "SWIPING TO THE left BUT RESET ERR");
}
// RandomFragment randomFrag = (RandomFragment) getFragmentManager().findFragmentById(R.id.fra);
viewPager.setCurrentItem(1);
}
}
});
btnYesRandom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if(fragmentCommunicator != null)
fragmentCommunicator.passDataToFragment("Hi from FragmentActivity");
}
});
}
Code for Fragment:
public class RandomFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//call data from activity bundle
String strtext = getArguments().getString("edttext");
View rootView = inflater.inflate(R.layout.fragment_random, container, false);
RelativeLayout random_frag_layout = (RelativeLayout) rootView.findViewById(R.id.random_frag_layout);
activityButton = (ImageView) rootView.findViewById(R.id.imagehere);
//setRetainInstance(true);
texthere = (TextView) rootView.findViewById(R.id.texthere);
texthere.setText(strtext);
return rootView;
}
//FragmentCommunicator interface implementation
public void passDataToFragment(String someValue){
activityAssignedValue = someValue;
Log.e("ACTIVITY", activityAssignedValue);
}
}
If you have only one fragment, then you can access it directly and send any data just via method: make your fragment a field and call your passDataToFragment() on it from activity.
To access an activity from fragment, call ((RandomActivity)getActivity()).activityMethod()
What is ActivityCommunicator?
If you wish to go down this route have your RandomActivity class implement the FragmentCommunicator interface, which should either be declared as an inner-public interface in the RandomFragment class say, or publicly (or package local) in its own file.

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