I have been trying to replace the fragment with another fragment if user clicks on one of the list item. Now the problem is the other fragment is getting displayed but it is not replacing previous frame but it is just getting displayed on top of the previous fragment. This is how I am calling my new fragment on list item click:
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String sender = ((TextView) view.findViewById(R.id.sender)).getText() .toString();
String subject = ((TextView) view.findViewById(R.id.subject)).getText() .toString();
String fname = ((TextView) view.findViewById(R.id.file_name)).getText() .toString();
Fragment frag =new DisplayFragment();
Bundle bundle = new Bundle();
bundle.putString("file_name", fname);
frag.setArguments(bundle);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_frame, frag);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
and activity associated with this fragment is:
<FrameLayout
android:id="#+id/fragment_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
now the code for new fragment is:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.activity_displayfile, container, false);
return rootView;
}
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
TextView tv=(TextView)getView().findViewById(R.id.textView1);
Bundle bundle = this.getArguments();
String myfile = (String)bundle.get("file_name");
tv.setText(myfile);
}
and its associated activity is :
<FrameLayout
android:id="#+id/display_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
the desired output should be the textview in new fragment should replace whole content of previous fragment. but the output after clicking item that I am getting is:
this "hi" should get displayed alone not with the list. It seems my code is correct. Thanks in advance.
Issue here is that you have a frame layout n a list view in a single view. You are replacing your frame with the fragment but your list view is still there.
Use fragment in your xml instead of frame layout and list view
Create a list fragment
On create of activity add list fragment to the view
On list item click replace list fragment with your fragment.
Hope this helps.
Related
Solved! Thanks everyone for your help.
I am struggling with Fragments as a concept, and especially seem stuck on this one thing. What I'm trying to do is, using my fragment, manipulate its own layout's data. Every time I try to access an ImageButton from within the Fragment, it crashes the application. It works fine from the activity. Am I just misunderstanding Fragments fundamentally?
Code(cut down for size)-
This is the beginning of the activity my fragment is called from:
Display.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragmentClass MyFragment = new MyFragmentClass();
fragmentTransaction.add(R.id.fragment_container, MyFragment);
fragmentTransaction.commit();
The XML for that Activity:
activity_display.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.mycompanyname.myprojectname.Display"
android:id="#+id/display_layout">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container">
</FrameLayout>
</RelativeLayout>
The Fragment
MyFragmentClass.java
public class MyFragmentClass extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_layout_screen, container, false);;
}
public void MethodTest()
{
}
}
The Fragment's XML file:
fragment_layout_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_layout_screen"
tools:context="com.mycompanyname.myprojectname.MyFragmentClass">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/my_button"
android:clickable="true"
android:onClick="buttonPress"
android:src="#drawable/button"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
Basically I had all of this originally in Display.java, but wanted to add fragments, so I'm trying to move stuff out and into fragments, but I still need the ability to manipulate the xml info, I just can't.
From inside the Display.java activity I can easily call the ImageButton like this:
ImageButton myButton = (ImageButton) findViewById(R.id.my_button)
but if I do the same from MethodTest in the fragment, the app crashes.
I've searched many suggestions on here, trying various solutions from here: findViewById in Fragment but none of those seemed to work.
I've been reading through this for the setup: http://developer.android.com/guide/components/fragments.html and can't seem to find what I'm doing wrong.
Any help would be appreciated, and if you have any questions about my setup, please ask.
declare on fragment private View rootView;
On the onCreateView(...) set rootView = inflater.Inflate(..); and then access the imagebutton as ImageButton mButton =(ImageButton) rootView.findViewById(..);
Do like this in fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.gridview, container, false);
GridView gridview = (GridView) view.findViewById(R.id.grid);
return view ;
I am creating an application which consists of a viewpager with different fragments.And these fragments contains different imagebuttons.I want to open fragments when each of these image button is clicked.But i don't know how to do it.I am new to fragments and i don't know much about them.I am trying to make this code since 2 days.Please if you can help me out.So i will be able to complete my project app.
My layout for NoticeBoard.java is as below: This contains2 imagebuttons and a listview.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns : android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:id="#+id/relative">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:background="#AAAAAA"
android:id="#+id/line">
<ImageButton
android:id="#+id/ptu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:background="#CCCCCC"
android:clickable="true"
android:onClick="OnClick"
android:contentDescription="#string/mko"
android:paddingBottom="10dp"
android:paddingLeft="9.9dp"
android:paddingRight="20dp"
android:paddingTop="10dp"
android:src="#drawable/img" />
<ImageButton
android:id="#+id/ku"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="1dp"
android:background="#CCCCCC"
android:clickable="true"
android:contentDescription="#string/mn"
android:paddingBottom="10dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="10dp"
android:src="#drawable/image" />
</LinearLayout>
<ListView
android:id="#+id/nb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/line"
android:layout_alignParentTop="true"
>
</ListView>
</RelativeLayout>
And my layout for the ptu,cu,ku,htu is same as above but with different adapter set on the above same listview.I have defined different adapters for ptu,hptu,cu and ku in their .java classes
My NoticeBoard.java class is a fragment with the noticeboard layout set as view and a listview.
public class Notice_Board extends Fragment {
ListView l;
ImageButton i1,i2,i3,i4;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_noticeboard, container, false);
l = (ListView) rootView.findViewById(R.id.nb);
String[] title = new String[]{"Important Announcements", "Datesheet", "Results","Placement Drives","Admissions","Entrance exams"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, title);
l.setAdapter(adapter);
i1 = (ImageButton ) rootView
.findViewById(R.id.ptu);
i2 = (ImageButton ) rootView
.findViewById(R.id.cu);
i3 = (ImageButton ) rootView
.findViewById(R.id.ku);
i4 = (ImageButton ) rootView
.findViewById(R.id.hptu);
i1.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.layout.activity_noticeboard,new PTU(),"PTU");
}
return rootView;
}
}
Below is my ptu.java class that contains the same view and the listview same as noticeboard but setting different values to listview by setting adapter with different values on it.
public class PTU extends Fragment{
ListView l;
ImageButton i2;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_noticeboard, container, false);
String[] array = new String[] {"Important Announcements", "Results",Programme","Syllabus","Fees","Events","Placement Drives"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, array);
l = (ListView) rootView.findViewById(R.id.nb);
l.setAdapter(adapter);
return rootView;
}
}
I want that each time a button is clicked the layout for notice board should appear but with different listview.And i also want when the noticeboard layout opens the ptu imagebutton should appear clicked having the listview in its fragment.
Below is my ku.java class that contains the same view and the listview that is for ptu but setting different values to listview by setting adapter with different values on it.
public class KU extends Fragment{
ListView l;
ImageButton i2;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_noticeboard, container, false);
String[] array = new String[] {"Important Announcements", "Results",Programme","Syllabus","Fees","Events","Placement Drives"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, array);
l = (ListView) rootView.findViewById(R.id.nb);
l.setAdapter(adapter);
return rootView;
}
}
I think issue is in your initialisation of fragment manager.
FragmentManager fm = getFragmentManager();
Instead of it, use
FragmentManager fragmentManager = ((MainActivity)getActivity()).getSupportFragmentManager();
Here MainActivity is your fragment activity from which you are calling your all fragments.
You have a Main fragment manager Activity name fragment activity. this is the main fragment activity manager. you have to set all fragment using by this activity.
i1 = (ImageButton ) rootView
.findViewById(R.id.ptu);
i2 = (ImageButton ) rootView
.findViewById(R.id.cu);
i3 = (ImageButton ) rootView
.findViewById(R.id.ku);
i4 = (ImageButton ) rootView
.findViewById(R.id.hptu);
i1.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
fragmentActiivty.setFragment();
}
Notes: :SetFragment function is made in fragment-activity class
public static void set_view_FAQ() {
FragmentManager fm = act.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = new yourFragnmentName();
ft.add(R.id.activity_main_content_fragment, fragment);
ft.commit();
}
Note: new yourFragmentNAme means yous fragment class likes Ku,ptu,etc
I am trying to get a fragment to show that contains an EditText and a button. I am new to using fragments, so I am not sure exactly what the error message I get when trying to create the fragment means.
I have a class that extends Fragment, this is where the EditText and button are created.
public class EditNameFragment extends android.support.v4.app.Fragment {
EditText editText;
ImageButton button;
public EditNameFragment(){
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_name_dialog, container, false);
editText = (EditText) view.findViewById(R.id.editTextDialog);
button = (ImageButton) view.findViewById(R.id.submitNewItemButtonDialog);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//stuff
}
});
return view;
}
Here is edit_name_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:id="#+id/edit_name_dialog"
>
<EditText
android:id="#+id/editTextDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageButton
android:id="#+id/submitNewItemButtonDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
And here in my main activity (which must extend FragmentActivity because of another part) is where I try to set up my Fragment. I think it has something to do with what id I am referencing. I have seen some people using container classes when using fragments, but I do not understand why this is done.
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
EditNameFragment fragment = new EditNameFragment();
fragmentTransaction.add(R.id.edit_name_dialog, fragment, "tag");
fragmentTransaction.commit();
I get the error message when trying to run the code above
No view found for id 0x7f09002a (com.myapp:id/edit_name_dialog) for fragment EditNameFragment
If anyone could explain what I am missing here/ why people use container classes, that would be great. I know some people add fragments using XML, but I would like to do this only using java.
EDIT
I have added a class that extends FragmentActivity, following the model for a container class
public class EditNameFragmentActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_name_fragment_container);
}
}
Is the parameter for setContentView supposed to be the layout, or an id?
Here is the xml file that defines where the fragment should be
edit_name_fragment_container.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<fragment android:name="com.returnjump.spoilfoil.EditNameFragment"
android:id="#+id/edit_name_fragment_container"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/edit_name_fragment" />
</LinearLayout>
So for the parameter in
fragmentTransaction.add(R.id.edit_name_dialog, fragment, "tag");
this is supposed to reference the id of the fragment, correct?
It still gives me the same error, what am I missing?
There are basically two ways to add a fragment to an activity like the documentation say:
"statically": by declaring the fragment inside the activity's layout file.
"dynamically": adding the fragment programmatically. Like you tried to do.
Here is the documentation: http://developer.android.com/guide/components/fragments.html
If you wish to add it dynamically, here is the documentation part that you want to read:
At any time while your activity is running, you can add fragments to your activity layout. You simply need to specify a ViewGroup in which to place the fragment.
To make fragment transactions in your activity (such as add, remove, or replace a fragment), you must use APIs from FragmentTransaction. You can get an instance of FragmentTransaction from your Activity like this:
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
You can then add a fragment using the add() method, specifying the fragment to add and the view in which to insert it. For example:
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
The first argument passed to add() is the ViewGroup in which the fragment should be placed, specified by resource ID, and the second parameter is the fragment to add.
Once you've made your changes with FragmentTransaction, you must call commit() for the changes to take effect.
And about why to use dynamic fragments instead of static fragments, it has been made for interactive UI allowing you to simply handle different fragments into one activity as you please.
I've been trying to solve this for a while now, I've looked through quite a number of questions but still nothing works.
I have a MainActivity with a SlideMenu, all items open a Fragment. One of these Fragments extends to a ListFragment. What I'm trying to do is once a ListItem is selected another Fragment is called and displays some data...for now just a title.
When a ListItem is selected, I am creating an instance of the new Fragment, save the data in the Bundle and call the new Fragment to be displayed.
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// do something with the data
Article a = articleList.get(position);
Fragment articleFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putString("title", a.title);
articleFragment.setArguments(args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.frame_container, articleFragment);
transaction.commit();
}
The onCreateView of the new Fragment attempts to set the text of the TextView with the Bundle's data.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_pages, container, false);
TextView titleTextView = (TextView) rootView.findViewById(R.id.article_title);
String title = getArguments().getString("title");
titleTextView.setText(title);
return rootView;
}
The layout xmls are these two files:
activity_article_fragment.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.androidhive.slidingmenu.ArticleFragment"
tools:ignore="MergeRootFrame" />
fragment_article.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="info.androidhive.slidingmenu.ArticleFragment$PlaceholderFragment" >
<TextView
android:id="#+android:id/article_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
I've tried to do as many suggested...using the View to get the id from the xml (accessing textview within a fragment in activity, Android : How do I update my textView in a Fragment) but it's still null.
Whilst debugging everything is working but obviously stops when attempting to set the text of the TextView as it is null.
UPDATE
Just did as suggested by Karakuri...text being displayed but it looks like this:
I am trying to make my app more tablet-friendly, and so I'm trying to learn fragments. I want the typical two-pane layout, where the left side is the "navigation", and you click on one of the elements, and it changes the fragment on the right.
I can duplicate the tutorials that use a ListFragment for the left, and if you click on one of them, it updates the "details" fragment on the right.
I've tried the best I can to duplicate that code, and just use a LinearLayout, with buttons for the left side, so that if a button is clicked, it loads the appropriate fragment on the right, but it's not working.
When I commit the FragmentTransaction, I get java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. What is the child's parent, and why do I have to call removeView on it?
I'm trying to load the fragment into a FrameLayout, but I've also just tried replacing another Fragment in the layout, and still get the error.
Ideally I want the left fragment to take up the whole screen until a button is pressed that requires a fragment to come in from the left, but one problem at a time I suppose.
Code
Main Activity
public class FragmentExample2Activity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
SelectorFragment (Left side)
public class SelectorFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View fragment = inflater.inflate(R.layout.selector, container);
Button button1 = (Button) fragment.findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
getFragmentManager().beginTransaction().replace(R.id.detail_holder, new DetailsFragment(), "stuff").commit();
}
});
return fragment;
}
}
DetailsFragment
public class DetailsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.details, container);
}
}
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<fragment class="com.coreno.testfragment.SelectorFragment"
android:id="#+id/select"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
/>
<fragment class="com.coreno.testfragment.DetailsFragment"
android:id="#+id/detail_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
/>
<!--
<FrameLayout
android:id="#+id/detail_holder"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="2"
/>
-->
</LinearLayout>
When you inflate a layout xml file, don't specify the parent view. It sounds very counter-intuitive to not specify where you're putting this inflated view but it works.
So, for example, in your SelectorFragment change the line:
View fragment = inflater.inflate(R.layout.selector, container);
to
View fragment = inflater.inflate(R.layout.selector, null);
or even better
View fragment = inflater.inflate(R.layout.selector, container, false);
Don't forget to do the same in your DetailsFragment too.
When you inflate a layout inside the getView method of a Fragment, you must use the next inflate method:
inflater.inflate(R.layout.details, container, false);
The key is the third parameter. It must be false not to attach the inflated layout to the container, because the system already done it. If it is true or is not indicated a redundant group view is created.