I am trying to do a very basic example with Fragments.
Structure : Fragment1 -> Fragment1Activity, Fragment2 -> Fragment2Activity.
Both activities have a STATIC Fragment in it.
Here are the XMLs:
activity_for_fragment_1.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.xx.fragmentstutorial1.Fragment1"
tools:context="com.xx.fragmentstutorial1.Fragment1Activity"/>
fragment1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textview_fragment_1"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="0.60"
android:text="This is Fragment 1"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="#+id/edittext_fragment_1_text"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="0.20"
android:text="Type your message here..." >
<requestFocus />
</EditText>
<Button
android:id="#+id/button_fragment_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click Me" />
</LinearLayout>
activity_for_fragment_2.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.xx.fragmentstutorial1.Fragment2"
tools:context="com.xx.fragmentstutorial1.Fragment2Activity"/>
fragment_2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textview_fragment_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="This is Fragment 2"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textview_fragment_2_result"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="I will display text from \nFragment 1"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
Now, I have an Edittext and button in the fragment_1. When I click on the button, I want to get the text entered in EditText and set it to the textview(textview_fragment_2_result) in fragment_2
I was able to achieve this, but, I am not very convinced, that the approach I took was good enough. Please look at the java code below..
Fragment1Activity.java
public class Fragment1Activity extends SherlockFragmentActivity implements Fragment1.ButtonClickListener{
Fragment1 fragment1;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_for_fragment_1);
System.out.println("onCreate Fragment1Activity");
fragment1 = (Fragment1) getSupportFragmentManager().findFragmentById(R.id.fragment_1);
}
#Override
public void onButtonClick(String message) {
System.out.println("onButtonClick Fragment1Activity");
startActivity(new Intent(this, Fragment2Activity.class).putExtra("message", message));
}
}
Fragment1.java
public class Fragment1 extends SherlockFragment {
EditText message;
Button clickme;
ButtonClickListener listener;
public interface ButtonClickListener{
public void onButtonClick(String message);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof ButtonClickListener)
listener = (ButtonClickListener) activity;
else {
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
System.out.println("onCreateView Fragment1");
View view = inflater.inflate(R.layout.fragment_1, container, false);
message = (EditText) view.findViewById(R.id.edittext_fragment_1_text);
clickme = (Button) view.findViewById(R.id.button_fragment_1);
clickme.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (!message.getText().toString().equalsIgnoreCase("")) {
System.out.println("Message in Fragment1 = "+message.getText().toString());
listener.onButtonClick(message.getText().toString());
} else {
Toast.makeText(getActivity(),
"Please enter some message...", Toast.LENGTH_LONG)
.show();
}
}
});
return view;
}
}
Fragment2Activity.java
public class Fragment2Activity extends SherlockFragmentActivity {
Fragment2 fragment2;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_for_fragment_2);
fragment2 = (Fragment2) getSupportFragmentManager().findFragmentById(R.id.fragment_2);
fragment2.setMessage(getIntent().getExtras().getString("message").toString());
}
}
Fragment2.java
public class Fragment2 extends SherlockFragment {
String msg;
TextView textview;
public Fragment2() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_2, container, false);
textview = (TextView) view
.findViewById(R.id.textview_fragment_2_result);
textview.setText(msg);
return view;
}
public void setMessage(String message) {
msg = message;
textview.setText(msg);
}
}
I have set the text for textview in setMessage() of Fragment2.java, which I think is not a good approach. If i comment that out, I don't see any text in the textview of Fragment2.
Can someone help me out, on how to pass values between two static fragments correctly.
You should go with interface
Follow the Diagram Here :
Communication Between Two Fragment is Done Via Activity using Interface
Fragment A-------------------------->Activity-------------------->Fragment B
(defines Interface) (Implement interface) (pass it other Fragment B)
Hope this could help
Check This Out
What you have is mostly good. The part of transferring the data from Fragment1 to Activity1 is good. Once the data gets to Activity2, you are setting it in Fragment2. I would change this part a little.
In Activity2:
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_for_fragment_2);
fragment2 = (Fragment2) getSupportFragmentManager().findFragmentById(R.id.fragment_2);
fragment2.setArguments(getIntent().getExtras());
}
and in Fragment2.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle bundle = getArguments();
String message = bundle.getString("message");
View view = inflater.inflate(R.layout.fragment_2, container, false);
textview = (TextView) view
.findViewById(R.id.textview_fragment_2_result);
textview.setText(message);
return view;
}
Your approach seems correct. The connection between your Fragment1 and Activity1 is just like in the fragments guideline. Your fragment1 shouldn't know about fragment2 therefore it's OK to pass the responsibility to the fragment's container/parent - activity1 - that knows what to do with the data. This time again your approach is correct - activity1 starts it's slave/child etc. and is responsible to start it with correct data (passed through the intent extras). And then again you have a correct approach - when your activity2 is created you populate it's views with the appropriate content/data (the message) that was meant to be displayed in this activity and given to it by the "parent" activity.
Related
I'm trying to display log value on the console, when I click on a Button inside a fragment. I don't know why but nothing happens when I click.
I tried by all possible ways (onClick directly on the layout, setOnClickListener extends OnClickListener, setting "clickable"=true).
Thank you for the help!
public class displayFacesFragment extends Fragment {
public static final String TITLE = "Faces";
public String selectedPeriod;
public Set<String> idFurnitures;
Button button75;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View inputFragmentView = inflater.inflate(R.layout.fragment_display_faces, container, false);
button75 =(Button) inputFragmentView.findViewById(R.id.button75);
button75.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Log.d("Test", "onClickListener");
}
});
return inputFragmentView;
}
<FrameLayout 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_faces"
tools:context="com.example.haddad.managemyrounds.controller.fragment.displayFacesFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
<Button
android:id="#+id/button75"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</FrameLayout>
I have a Fragment with a ListView of row items. A row consist in just am ImageView
fragment_1.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:id="#+id/fragment_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragment1">
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#b5b5b5"
android:dividerHeight="1dp"
android:listSelector="#drawable/list_selector"/>
</RelativeLayout>
row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/row"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip">
<!-- Rightend Play Button. -->
<ImageView
android:id="#+id/play_button"
android:layout_width="50dip"
android:layout_height="50dip"
android:src="#drawable/ic_play"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
I have a ResourceCursorAdapter to fill this ListView. I just assign to each ImageView a click listener. It plays a record saved in the provided path.
private abstract class MyAdapter extends ResourceCursorAadpter {
#Override
public void bindView(View view, Context context, final Cursor cursor) {
// Play button.
ImageView playButton = (ImageView) view.findViewById(R.id.play_button);
playButton.setOnClickListener(new View.OnClickListener() {
String record = cursor.getString(cursor.getColumnIndex(DbAdapter.RECORD));
public void onClick(View v) {
// Play record in path [record]. Not the problem.
}
});
}
}
Now I want to open a new fragment Fragment_2 in a row click. This fragment has the same play_button, and has to play the same record.
fragment_2.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:id="#+id/fragment_audio"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragment2">
<!-- Play Button. -->
<ImageView
android:id="#+id/play_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/ic_play"/>
</RelativeLayout>
How can I manage that this button plays the same record than in Fragment_1? I think I could be able if I have a hidden TextView with the path of the record, but sure you have a smarter solution.
In my onCreateView of Fragment_1.
mList = (ListView) root.findViewById(R.id.list);
// Click event for single row.
mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO: Go to fragment_2 and has the same view [view.findViewById(R.id.play_button)]
}
});
Communication between fragments should be done through the associated Activity. You can use interface for this. it Will serve as contract and bridge between them.
Let's have the following components:
An activity hosts fragments and allow fragments communication
FragmentA first fragment which will send data
FragmentB second fragment which will receive datas from FragmentA
FragmentA's implementation is:
public class FragmentA extends Fragment {
DataPassListener mCallback;
public interface DataPassListener{
public void passData(String data);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Make sure that container activity implement the callback interface
try {
mCallback = (DataPassListener)activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement DataPassListener");
}
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Suppose that when a button clicked second FragmentB will be inflated
// some data on FragmentA will pass FragmentB
// Button passDataButton = (Button).........
passDataButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (view.getId() == R.id.passDataButton) {
mCallback.passData("Text to pass FragmentB");
}
}
});
}
}
MainActivity implementation is:
public class MainActivity extends ActionBarActivity implements DataPassListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.container) != null) {
if (savedInstanceState != null) {
return;
}
getFragmentManager().beginTransaction()
.add(R.id.container, new FragmentA()).commit();
}
}
#Override
public void passData(String data) {
FragmentB fragmentB = new FragmentB ();
Bundle args = new Bundle();
args.putString(FragmentB.DATA_RECEIVE, data);
fragmentB .setArguments(args);
getFragmentManager().beginTransaction()
.replace(R.id.container, fragmentB )
.commit();
}
}
FragmentB implementation is:
public class FragmentB extends Fragment{
final static String DATA_RECEIVE = "data_receive";
TextView showReceivedData;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_B, container, false);
showReceivedData = (TextView) view.findViewById(R.id.showReceivedData);
}
#Override
public void onStart() {
super.onStart();
Bundle args = getArguments();
if (args != null) {
showReceivedData.setText(args.getString(DATA_RECEIVE));
}
}
https://developer.android.com/training/basics/fragments/communicating.html
This document has given information in detail, you can go through it.
In your situation, you can apply this way to communicate between two fragments.
Trying to Communicating FragmentA to FragmentB, doing is taking numeric value from fragmentA adding them and displaying result in fragmentB using interface, but I got nullpointerException, I have look many times in the code but seems everything is fine but getting nullpointerException showing line 34 in FragmentA
listener.setResult(result+" ");
Here's My FragmentA
public class FragmentA extends Fragment{
MyFragmentInterface listener;
Button buton;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.fragment_a,container,false);
final EditText editText= (EditText) view.findViewById(R.id.edit_text1);
final EditText editText2= (EditText) view.findViewById(R.id.edit_text2);
buton= (Button) view.findViewById(R.id.button);
buton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int num1=Integer.parseInt(editText.getText().toString());
int num2=Integer.parseInt(editText2.getText().toString());
int result=num1+num2;
listener.setResult(result+" ");
}
});
return view;
}
#Override
public void onAttach(Context context) {
listener= (MyFragmentInterface) context;
super.onAttach(context);
}
}
Here's my fragment_a.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/edit_text1"
android:inputType="number"
android:textSize="30sp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:id="#+id/edit_text2"
android:textSize="30sp"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Calculate"
android:id="#+id/button"
android:background="#null"
android:textAllCaps="false"/>
</LinearLayout>
FragmentB.java
public class FragmentB extends Fragment {
TextView textView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
textView= (TextView) getActivity().findViewById(R.id.textview);
return inflater.inflate(R.layout.fragment_b,container,false);
}
public void putresult(String r){
textView.setText(r);
}
}
fragment_b.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:id="#+id/textview"
android:text="Text will appear here"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements MyFragmentInterface {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentA fragmentA=new FragmentA();
FragmentManager fragmentManager=getFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.linear1,fragmentA);
fragmentTransaction.commit();
FragmentB fragmentB=new FragmentB();
FragmentManager fragmentManager1=getFragmentManager();
FragmentTransaction fragmentTransaction1=fragmentManager1.beginTransaction();
fragmentTransaction1.addToBackStack(null);
fragmentTransaction1.replace(R.id.linear2,fragmentB);
fragmentTransaction1.commit();
}
#Override
public void setResult(String result) {
FragmentB fragmentnew=new FragmentB();
fragmentnew= (FragmentB) getFragmentManager().findFragmentById(R.id.linear2);
fragmentnew.putresult(result);
}
}
MyFragmentInterface.java
public interface MyFragmentInterface {
public void setResult(String result);
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="queendevelopers.com.communicate.MainActivity"
android:weightSum="2"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/linear1"
android:orientation="vertical" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/linear2"
android:orientation="vertical" />
</LinearLayout>
error log:
08-16 16:11:42.307 7630-7630/queendevelopers.com.communicate E/AndroidRuntime: FATAL EXCEPTION: main
Process: queendevelopers.com.communicate, PID: 7630
java.lang.NullPointerException: Attempt to invoke interface method 'void queendevelopers.com.communicate.MyFragmentInterface.setResult(java.lang.String)' on a null object reference
at queendevelopers.com.communicate.FragmentA$1.onClick(FragmentA.java:34)
at android.view.View.performClick(View.java:4832)
at android.view.View$PerformClick.run(View.java:19844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5319)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1016)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811)
To expand on the comment I made that solved the problem:
The original issue was not to do with your interface callback (this was not the root cause of the NullPointerException).
When the callback method setResult(String result) was invoked this line :
fragmentnew.putresult(result); was causing the null pointer because, in the method putresult in your fragment there is a null reference to your textView (textView.setText(r);).
For every Activity you can have an associated view heirarchy (your XML file), this is set by setContentView() in onCreate(). Now if you try and reference any #+id widgets from the XML layout you can cast relevant object type : TextView, EditText, ListView. Fragments (which are attached to a hosting Activity) can also have their own layouts, this is inflated in onCreateView(). Your final code should look something like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_b,container,false);
textView = (TextView) view.findViewById(R.id.textview);
return view;
}
Your view object now contains your view hierarchy for the inflated XML Layout, from which you can access all widgets.
The line of code that was incorrect was:
textView = (TextView) getActivity().findViewById(R.id.textview);
The reason being you are using the convenience method getActivity() this will return the hosting Activity reference - thus you now will have access to the hosting Activity - used a lot for gaining a Context of other purposes, however your view id reference is invalid because it is in the view hierarchy of your inflated layout in your fragment.
Try this method inside your Fragment
#Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (MyFragmentInterface) getActivity();
}
try this
(((MyFragmentInterface)getActivity()).setResult(result+" ");
Change in Fragment A:
from:
buton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int num1=Integer.parseInt(editText.getText().toString());
int num2=Integer.parseInt(editText2.getText().toString());
int result=num1+num2;
listener.setResult(result+" ");
}
});
To
buton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int num1=Integer.parseInt(editText.getText().toString());
int num2=Integer.parseInt(editText2.getText().toString());
int result=num1+num2;
((MainActivity) getActivity()).setResult(result+" ");
}
});
Because I think your listener object is not initialised before being used so try this answer please.
I am new to the android platform so I know I am just missing something by here is what I have
<!-- activity_main -->
<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="com.example.example_app.MainActivity"
tools:ignore="MergeRootFrame" >
<fragment
android:id="#+id/mainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.example.example_app.MainFragment"
/>
</FrameLayout>
Then I created a fragment called MainFragment.java.
public class MainFragment extends Fragment {
public TextView displayTextView;
public MainFragment() { }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
this.displayTextView = (TextView)rootView.findViewById(R.id.displayTextView);
return rootView;
}
}
I add the fragment in the OnCreate function in the activity and it seems to be adding everything okay but when I click on the button nothing happens, I logged the function to see its being called but setting the textview doesn't do anything. What am I doing wrong?
<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="com.example.example_app.MainActivity$PlaceholderFragment" >
<Button
android:id="#+id/button10"
android:textColor="#ffffff"
android:textSize="34dp"
android:text="10%"
android:layout_below="#id/amountEditText"
android:background="#drawable/pct_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="doSomething"
/>
<TextView
android:text="Blah Blah Blah"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/displayTextView"
></TextView>
</RelativeLayout>
And here is the click Event in the MainActivity.java
public void doSomething(View v) {
this.mainFragment.displayTextView.setText("Nothing to set for some reason!");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
//
this.mainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.mainFragment);
mainFragment = new MainFragment();
getSupportFragmentManager().beginTransaction().add(mainFragment, "mainFragment").commit();
}
}
Declaring onClick-Listeners via XML is possible if you work with Activities. According to the Google API, however, you need to declare OnClickListeners programmatically if you use Fragments.
[...] You can also declare the click event handler programmatically rather than in an XML layout. This might be necessary if you instantiate the Button at runtime or you need to declare the click behavior in a Fragment subclass.
Source:
http://developer.android.com/guide/topics/ui/controls/button.html
So you may want to use this instead:
public class MainFragment extends Fragment {
public TextView displayTextView;
public Button yourButton;
public MainFragment() { }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
this.displayTextView = (TextView)rootView.findViewById(R.id.displayTextView);
yourButton = (Button)rootView.findViewById(R.id.button10);
yourButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
displayTextView.setText("Nothing to set for some reason!");
}
});
return rootView;
}
}
The problem is the way you try to execute the button click. From your question i understand that Button and TextView is in Fragment view. So do why are Trying to access it in activity ?? It is wrong, then there is no point of using Fragments. Also this will lead to many serious issues later .
Fragments are Reusable components so all the functionalities of a fragment must stay inside the Fragment Class
Change Fragment code :
public class MainFragment extends Fragment {
public TextView displayTextView;
public Button yourButton;
public MainFragment() { }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
this.displayTextView = (TextView)rootView.findViewById(R.id.displayTextView);
yourButton = (Button)rootView.findViewById(R.id.button10);
//Setting click listener for button in fragment
yourButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
displayTextView.setText("Nothing to set for some reason!");
}
});
return rootView;
}
}
and remove android:onClick="doSomething" from XML
In a class i am adding a Fragment programatically.
This Fragment contains a Button, which i want to have an onClick implementation.
Here is the class i have:
public class ShareProduct extends SherlockFragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.share_product);
FragmentManager fragmentManager = getSupportFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
ProductFragment1 fragment = new ProductFragment1();
fragmentTransaction.add(R.id.share_product_parent, fragment);
fragmentTransaction.commit();
Button done_button = (Button) fragment.getView().findViewById(
R.id.done_product_1);
done_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
ProductFragment2 fragment = new ProductFragment2();
fragmentTransaction
.replace(R.id.share_product_parent, fragment);
fragmentTransaction.commit();
}
});
}
}
and my ProductFragment1 class is:
public class ProductFragment1 extends SherlockFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater
.inflate(R.layout.share_product_1, container, false);
return view;
}
}
and the layout my main class uses is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/share_product_parent"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="right|center_vertical"
android:orientation="horizontal" >
</RelativeLayout>
and the layout my ProductFragment1 uses is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/tv1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="25dp" />
<EditText
android:id="#+id/et1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/tv1"
android:textSize="25dp" />
<Button
android:id="#+id/done_product_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/et1"
android:text="Done" />
</RelativeLayout>
The problem is:
I am getting a NullPointerException at this line in my main class:
Button done_button = (Button) fragment.getView().findViewById(R.id.done_product_1);
done_button.setOnClickListener ....
when i searched for what getView() on a fragment returns. I found out that it returns the view from onCreateView();
I checked it doesn't return null.
Thank You
You are on the wrong track here. You get the NPE because the Fragments views is not created yet. Fragments also have a lifecycle just like Activities.
What you should be doing is assigning the OnClickListener inside your Fragments onViewCreated() method. And from there... you should create a callback and notify your hosting Activity of the event.