The issue I'm having is that I don't know how to get a pointer to a layout within a fragment. It's obvious that to get a layout pointer in Java you would do something like this:
LinearLayout llTemp = (LinearLayout) findViewById(R.id.llTemp)
Something along those lines.
Now what I'm doing is grabbing information from a server in the main class and load a fragment within the same class. I would like to populate the fragment with the information loaded from the outer class. Is there any way to do this? I would have just grabbed the layout from within the fragment and do it that way but I cannot make a reference to it as it's in the fragment.
I'm sure this is a common problem but I couldn't find anything on it specifically like this.
Thanks in advance,
Cheers,
Jake
To Answer the comment:
View view = inflater.inflate(R.layout.main_frag, container, false);
mainLayout = (LinearLayout) view.findViewById(R.id.ll_MainFrag);
return view;
This is what is in my onCreateView.
Okay, just to add how I'm instantiating the Fragment:
private int MAIN = 1;
FragmentManager fm = getSupportFragmentManager();
fragments[MAIN] = new MainFragment();
FragmentTransaction transaction = fm.beginTransaction();
transaction.commit();
getSupportFragmentManager().beginTransaction().add(R.id.flMain, fragments[MAIN]).commit();
From here I would like to be able to do something like:
fragments[MAIN].createTextView();
When creating a Fragment, create public methods to set data:
public class MyFragment extends Fragment {
private TextView text1;
private TextView text2;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = LayoutInflater.from(getActivity()).inflate(R.layout.simple_list_item_2,container,false);
text1 = (TextView) layout.findViewById(R.id.text1);
text2 = (TextView) layout.findViewById(R.id.text2);
return super.onCreateView(inflater, container, savedInstanceState);
}
public void setData(String t1, String t2){
text1.setText(t1);
text2.setText(t2);
}
}
When adding a fragment in parent activity, give it a unique tag:
MyFragment f = new MyFragment();
getFragmentManager().beginTransaction().add(f,"my_fragment").commit();
Later, you can search the fragment from parent activity and call some methods on it:
MyFragment frg = (MyFragment) getFragmentManager().findFragmentByTag("my_fragment");
if(frg != null){
frg.setData("abc","def");
}
Also, if fragment was added from a layout, you can find the fragment by its id.
Related
I am having trouble to navigate from one fragment to another through a button in my android application. I have considered several questions about this issue but the solutions provided are not solving my problem. Here is my code and I don't know what I am doing wrong.
public class fragment_profile extends Fragment {
TextView txtFname, txtLname, txtGender, txtAge, txtPhone, txtEmail;
Button btImages, btVideos;
ImageButton btProfilePic;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_profile, container, false);
btProfilePic = (ImageButton)rootView.findViewById(R.id.ProfilePic);
txtFname = (TextView)rootView.findViewById(R.id.tvFName);
txtLname = (TextView)rootView.findViewById(R.id.tvLName);
txtGender = (TextView)rootView.findViewById(R.id.tvGender);
txtAge = (TextView)rootView.findViewById(R.id.tvAge);
txtPhone = (TextView)rootView.findViewById(R.id.tvPhone);
txtEmail = (TextView)rootView.findViewById(R.id.tvEmail);
btImages = (Button)rootView.findViewById(R.id.btnImages);
btVideos = (Button)rootView.findViewById(R.id.btnVideos);
//The code to replace fragment is not good, the clicklistener is working fine as I have tested it with a toast message
btImages.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//An object of the fragment tree is created
fragmentImages ImageGallery = new fragmentImages();
//The fragment is finally added
fragmentTransaction.replace(R.id.fragment_profile, ImageGallery, "Image Gallery").commit();
//Set title of action bar = title of fragment
getActivity().setTitle(getTag());
}
});
btVideos.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//An object of the fragment tree is created
fragmentVideos VideoGallery = new fragmentVideos();
//The fragment is finally added
fragmentTransaction.replace(R.id.fragment_profile, VideoGallery, "Video Gallery").commit();
//Set title of action bar = title of fragment
getActivity().setTitle(getTag());
}
});
return rootView;
}
}
The issue is with the code inside the onClickListener. Can anyone tell me what I am doing wrong? Thank you.
You want to use the supportFragmentManager. Within your onClickListener(s), make your transaction this:
//An object of the fragment tree is created
fragmentImages ImageGallery = new fragmentImages();
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_profile, ImageGallery).commit();
//rest of your setting the activity title below
It is also best practise to make write your classes like FragmentImages and then your variables as imageGallery for example or even fragmentImages so you know what the object is.
I think you have to add your fragment_profile fragment to the backstack so you can recall it afterwards after you have triggered the other fragments. Try the following:
fragmentTransaction.replace(R.id.fragment_profile, ImageGallery, "Image Gallery").addToBackStack(null).commit();
Same with the latter:
fragmentTransaction.replace(R.id.fragment_profile, VideoGallery, "Video Gallery").addToBackStack(null).commit();
I got the information from here: Fragment Replacing Existing Fragment
I am trying to add a fragment, then find a view inside said fragment, and add a view into it. However I keep getting a NullPointerException on this statement
FrameLayout container2 = (FrameLayout) fragment.getActivity().findViewById(R.id.content_frame);
Here is my code. Can someone tell me how to fix this please? thanks
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment fragment = new FragmentNavigationDrawer();
ViewGroup decor = (ViewGroup) getActivity().getWindow().getDecorView();
View child = decor.getChildAt(0);
decor.removeView(child);
fragmentTransaction.add(decor.getId(), fragment);
fragmentTransaction.commit();
FrameLayout container2 = (FrameLayout) fragment.getActivity().findViewById(R.id.content_frame);
container2.addView(child);
Just use a getter. Set a tag on your fragment so you can access it later, then either call getView() on your fragment to return its root view, or use a getter to access a specific View:
public class MainActivity extends AppCompatActivity {
//In onCreate
if (getFragmentManager().findFragmentByTag(FragmentNavigationDrawer.TAG) == null) {
getFragmentManager()
.beginTransaction()
.add(android.R.id.content, new FragmentNavigationDrawer(), FragmentNavigationDrawer.TAG)
.commit();
}
//Later, when you want to add said View:
FragmentNavigationDrawer frag =
(FragmentNavigationDrawer) getFragmentManager().findFragmentByTag(FragmentNavigationDrawer.TAG)
//Return the root view:
View fragRootView = frag.getView();
//Return a specific view:
frag.getUpdatableViewGroup().addView(newViewToAdd):
}
For your Fragment:
public class FragmentNavigationDrawer extends Fragment {
public static final String TAG = FragmentNavigationDrawer.class.getSimpleName();
FrameLayout updatableViewGroup;
//Can do this inside onCreateView() whilst inflating your Fragment's Views
//That's up to you.
#Override
public void onViewCreated (View view, Bundle savedInstanceState) {
updateableViewGroup = view.findViewById(R.id.updateable_view_group);
}
public FrameLayout getUpdatableViewGroup() {
return updateableViewGroup;
}
Be conscious of the Activity and Fragment life cycles however, and be careful not to attempt to access the Fragment's Views until they have finished inflating - onStart() of your Activity and later should be ok.
Please see the javadoc for FragmentTransaction.commit(). It says it will schedule a change to the fragment back stack. It doesn't happen immediately. It looks like you're expecting the fragment and its views to be instantly available.
Also, I'm really confused why you're reaching in a decor view to make changes. Usually you call out a view by id in the host activity's layout and make changes inside it.
I have an issue with fragment navigation in frame-layouts. Namely I cannot find out in which frame the fragment is currently being displayed in.
My setup is the following:
I have 3 parent fragments (PA, PB, PC), each with their own unique framelayouts. Additionally I have 3 Childfragments (CA,CB, CC) and two Grandchildfragments (GA, GB)
The parent fragments call the childfragments into the appropriate framelayouts (works fine), but now I want the childfragments to replace themselves with the appropriate grandchildren, but I have no way of finding out in which framelayout the childfragments are currently displayed in. (I hope that makes sense)
Pseudo-code example:
public class Parent extends Fragment{
//lots of stuff here
public void replaceFragmentWithChild(){
Fragment frg = new childFragment();
FragmentManager mgr = ((FragmentActivity) getActivity()).getSupportFragmentManager();
FragmentTransaction trx = mgr.beginTransaction();
trx.addToBackStack(null);
trx.replace(R.id.content_view_a, childFragment).commit();
}
}
public class Child extends Fragment{
//lots of stuff here
public void replaceFragmentWithGrandChild(){
Fragment frg = new GrandChildFragment();
FragmentManager mgr = ((FragmentActivity) getActivity()).getSupportFragmentManager();
FragmentTransaction trx = mgr.beginTransaction();
trx.addToBackStack(null);
//here is the problem. I would like to call trx.replace(GET-CURRENT-CONTENT-VIEW, frg)
trx.replace(???, frg).commit();
}}
Any input would be much appreciated.
Edit: Ok, I have found a possible solution by saving the ViewGroup Container in the onCreateView and passing that to the trx.replace function.
But unfortunately I am getting the following Message: java.lang.IllegalArgumentException: No view found for id 0x7f0c0057 (de.tel.quenference.activities:id/sara_content_view) for fragment PaperviewFragment{421da470 #2 id=0x7f0c0057} which makes little sense to me, because the view is the same one I am in,or?
What am I missing?
Ok, I figured it out and I sort of want to shoot myself.
First off, the 'No View Found' error stems from the fact, that my parentfragment did not call transaction.addToBackStack (I added it into my example code but not my production code...)
Just putting that in unfortunately did not fix everything, but I had to also change the ParentFragment to not call getChildFragmentManager, but rather the normal FragmentManager
otherwise the grandchildfragment would not appear in the frameLayout.
Basically my working code looks like this:
public class Parent extends Fragment{
//lots of stuff here
public void replaceFragmentWithChild(){
Fragment frg = new childFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
trx.addToBackStack(null);
trx.replace(R.id.content_view_a, childFragment).commit();
}
}
public class Child extends Fragment{
private ViewGroup locContainer;
//lots of stuff here
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
locContainer = container;
return super.onCreateView(inflater, container, savedInstanceState);
}
public void replaceFragmentWithGrandChild(){
Fragment frg = new GrandChildFragment();
FragmentTransaction trx = getFragmentManager().beginTransaction();
trx.addToBackStack(
trx.replace(locContainer.getId(), frg).commit();
}}
Let say the target application is built from 3 fragments which are all in the same activity public class MainActivity extends android.support.v4.app.FragmentActivity implements ActionBar.TabListener. Starting fragment is public class ButtonSectionFragment extends Fragment where there is a Button:
public class ButtonSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.btn, container, false);
Button mybutton = (Button) rootView.findViewById(R.id.mybutton);
mybutton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
????????????????????
}
});
}
There are ?? in the onClick method, I will get to that. And there is another fragment like this:
public static class TextSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tv, container, false);
TextView textv = (TextView) rootView.findViewById(R.id.texty);
}
Both of the fragments are using different layouts so this is why rootView is being used right in front of findViewById.
The outcome I would like to achieve is: by Button from 1st fragment click set the TextView from 2nd fragment to Hello. What should I put in the ??? part to make it all work?
You need to use interface as callback to the activity then set the textview in fragment.
Two framgents should never communicate directly.
http://developer.android.com/training/basics/fragments/communicating.html.
Framgent1 -->Activity -->Fragment2.
You can comunicate value from fragment2 to activity first then from activity to fragment2. Then set text in fragment2
You just have to use getActivity().findViewById() instead of getView().findViewById()
final TextView tv = (TextView) getActivity().findViewById(R.id.texty);
if (tv != null)
tv.setText("Hello");
Fragments are just branches inside the common layout tree of activity. All fragment views of a common activity can be accessed through Activity.findViewByXXX(). The only complication is that fragments can be dynamically added, removed, replaced, etc. So you to be sure that the needed fragment is already inflated into the layout hierarchy. You can make initialization of the UI in onViewCreated() of the other fragment. That guarantees you the layout has been loaded already.
Fragment frag1 = new ButtonSectionFragment ();
Fragment frag2 = new TextSectionFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(layout, frag1);
ft.add(layout, frag2);
ft.commit();
View frag1RootView = frag1.getView();
View frag2RootView = frag2.getView();
Button btn = (Button)frag1RootView.findViewById(id);
TextView tv = (TextView)frag2RootView.findViewById(id);
untested but... I think that would do it...
EDIT: You should get the root views onActivityCreated(); or it'll throw you a null...
In continuation to Raghunandan's answer, you could check similar implementation in the link.
update TextView in fragment A when clicking button in fragment B
Do not forget to get a reference of the textview of the TextSectionFragment into the MainActivity.
First time posting here and also a new developer for Android Apps.
Desire Function of Example App:
1) Activity starts in fullscreen A
2) Fragment B then populates/inflates container of A fullscreen
3) Fragment B has a button, button is press
4) Fragment B is now replaced with Fragment C
5) Fragment C is now full screen and has data that is inputted by users, user then hits button to send to next Fragment
6) Fragment C is replaced with Fragment D and presents data to view which was inputted from Fragment C
Summary Functionality:
I am trying to keep everything on one screen going from
A (Activity) -> B (Fragment replace) -> C (Fragment replace to type data) -> D (Fragment replace and see last fragment data)
Problem/Issue
My code crashes when I try to populate the last screen with data obviously. It seems to throw an error in MainActivity at this specific line when I debug it
CartFragmentCode addCartInfoTextFragment = (CartFragmentCode) getSupportFragmentManager().findFragmentById(R.id.maincontainer);
I am definitely passing the values correctly through the interface I created, but during the debug process, I found out that my current program is trying to populate information into the same container since it seems like it didn't commit yet to replace the fragment to assign the variables to the right UI.
I was checking if I was able to replace the Fragment C with D, and I was able to only if I remove that above line of code.
Code Below
Main
public class MainActivity extends FragmentActivity implements OrderFragmentCode.FragUIListeners{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment AllMenu = new AllMenuFragmentCode();
FragmentManager fragManager = getSupportFragmentManager(); //getSupportFragmentManager setup
FragmentTransaction ft = fragManager.beginTransaction(); //setup fragmentTranscation = ft
ft.add(R.id.maincontainer, AllMenu);
ft.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void onCartButtonClicked(String editFood, String editType, String editName){
CartFragmentCode addCartInfoTextFragment = (CartFragmentCode) getSupportFragmentManager().findFragmentById(R.id.maincontainer);
addCartInfoTextFragment.UpdateCartTexts(editFood, editType, editName);
}}
Fragment A
public class AllMenuFragmentCode extends Fragment implements OnClickListener {
private Button Order;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.all_menu_fragment, container, false);
Order = (Button) view.findViewById(R.id.orderButton);
Order.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
Fragment OrderFragmentCode = new OrderFragmentCode();
FragmentManager fragManager = getFragmentManager(); //getSupportFragmentManager setup
FragmentTransaction ft = fragManager.beginTransaction(); //setup fragmentTranscation = ft
ft.replace(R.id.maincontainer, OrderFragmentCode);
ft.addToBackStack(null);
ft.commit();
}}
Fragment C
public class OrderFragmentCode extends Fragment implements OnClickListener {
FragUIListeners activityCallback;
public interface FragUIListeners {
public void onCartButtonClicked(String foodText, String typeText, String nameText);
}
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
activityCallback = (FragUIListeners) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement FragUIListeners");
}
}
private EditText editTextFood;
private EditText editTextType;
private EditText editTextName;
private Button AddToCartButton;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.order_fragment, container, false);
editTextFood = (EditText) view.findViewById(R.id.editText);
editTextType = (EditText) view.findViewById(R.id.editText2);
editTextName = (EditText) view.findViewById(R.id.editText3);
AddToCartButton = (Button) view.findViewById(R.id.addToCart);
AddToCartButton.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
Fragment Cart = new CartFragmentCode();
FragmentManager fragManager = getFragmentManager();
FragmentTransaction ft = fragManager.beginTransaction();
ft.replace(R.id.maincontainer, Cart);
ft.addToBackStack(null);
ft.commit();
activityCallback.onCartButtonClicked(editTextFood.getText().toString(), editTextType.getText().toString(), editTextName.getText().toString());
}}
Fragment D
public class CartFragmentCode extends Fragment{
private TextView foodView;
private TextView typeView;
private TextView nameView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.cart_fragment, container, false);
foodView = (TextView) view.findViewById(R.id.foodView);
typeView = (TextView) view.findViewById(R.id.typeView);
nameView = (TextView) view.findViewById(R.id.nameView);
return view;
}
public void UpdateCartTexts(String editfood, String edittype, String editname)
{
foodView.setText(editfood);
typeView.setText(edittype);
nameView.setText(editname);
}}
--Final Say--
Sorry for the long post, this has been bugging me for HOURS and I even tried to use bundles and setting the arguements but I wasnt able to get that working either (I thought if i were able to obtain values correctly I could work around and use this to assign values to my textviews through getArguments on my last Fragment).
Please help!!!! Thanks!!!
In the line CartFragmentCode addCartInfoTextFragment = (CartFragmentCode) getSupportFragmentManager().findFragmentById(R.id.maincontainer);
findFragmentById sholule be passed that you use as 2nd argument in add while adding fragment to container for e.g. ft.add(R.id.maincontainer, AllMenu); if you want to get this fragment then you use findFragmentById(AllMenu) which is the tag that is associated with the fragment. R.id.maincontainer is the container in which that fragment is being displayed.
I guess the problem is you call onCartButtonClicked inside fragment C (where fragment C still exist) so the fragment D isn't created and take C place yet.
Try to call onCartButtonClicked by a Handler in your MainActivity
This is was one of my resource at the time to mimic a solution (he was using two fragments in one activity, while my app is trying to use one activity and replacing the main framelayout): http://www.techotopia.com/index.php/Using_Fragments_in_Android_-_A_Worked_Example
After playing around with example codes and using the available documentations. I cannot use these two lines to transfer the information as suggested in my MainActivity:
CartFragmentCode addCartInfoTextFragment = (CartFragmentCode) getSupportFragmentManager().findFragmentById(R.id.maincontainer);
addCartInfoTextFragment.UpdateCartTexts(editFood, editType, editName);
I think I finally found a workaround or a solution? I am not sure if this is the correct way of passing information to fragments or other classes, but here it is...
I basically Took away those two lines and rework my MainActivity's Click method and changed it to this...
public void onCartButtonClicked(String editFood, String editType, String editName){
CartFragmentCode.passFood = editFood;
CartFragmentCode.passType = editType;
CartFragmentCode.passName = editName;
}
I then went to my last fragment Code which was OrderFragmentCode.java and declared my Strings to retrieve them at the top of the Class and they were...
public static String passFood;
public static String passType;
public static String passName;
I then took the those values and setText them to my textViews. Wallah! It works as intented, however I am not sure if this is the right way to do things... If you guys are able to find a more professional way to handle data across multiple fragments, please let me know!