Having problems getting Fragment to Activity communication working properly..
I have an edit box in a Fragment and I need it to send its value back to the main activity after each edit.
Fragment Class:
public class FragA extends Fragment {
FragAInt mCallback;
public interface FragAInt{
public void onEditBoxEdited(String boxContent);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_a, container, false);
final View et = view.findViewById(R.id.eboxa) ;
((EditText) et).addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
mCallback.onEditBoxEdited(((EditText) et).getText().toString());
}
});
return view;
}
}
MainActivity
public class MainActivity extends FragmentActivity implements FragA.FragAInt{
private String editBoxVal;
public void onEditBoxEdited(String editBoxContent){
this.editBoxVal= editBoxContent;
}
}
The app will run but it will crash as soon as you type in the exit box with a null pointer exception.
Where have I gone wrong?
Full error:
java.lang.NullPointerException:
Attempt to invoke interface method 'void nemo.myapplication.FragA$FragAInt.onEditBoxEdited(java.lang.String)' on a null object reference
at nemo.myapplication.FragA$1.afterTextChanged(FragA.java:49)
at android.widget.TextView.sendAfterTextChanged(TextView.java:8017)
at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:10182)
at android.text.SpannableStringBuilder.sendAfterTextChanged(SpannableStringBuilder.java:1043)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:560)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:492)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:34)
at android.view.inputmethod.BaseInputConnection.replaceText(BaseInputConnection.java:685)
at android.view.inputmethod.BaseInputConnection.setComposingText(BaseInputConnection.java:445)
at com.android.internal.view.IInputConnectionWrapper.executeMessage(IInputConnectionWrapper.java:340)
at com.android.internal.view.IInputConnectionWrapper$MyHandler.handleMessage(IInputConnectionWrapper.java:78)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
You need to assign the mCallback variable. I think you missed that part, you can use onAttach event.
public class FragA extends Fragment {
FragAInt mCallback;
public interface FragAInt{
public void onEditBoxEdited(String boxContent);
}
public FragA(FragAInt mCallback) {
this.mCallback = mCallback;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (FragAInt) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_a, container, false);
final View et = view.findViewById(R.id.eboxa) ;
((EditText) et).addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
mCallback.onEditBoxEdited(((EditText) et).getText().toString());
}
});
return view;
}
}
Related
Hi in the below code I was implemented callevents for sockets but it is not working.when I am try to press end call button, it is giving me an null pointer exception.
Can any one help how to resolve my issue.
OnCallEvents.java:
public interface OnCallEvents {
void onCallHangUp();
void onCameraSwitch();
void onCaptureFormatChange(int width, int height, int framerate);
boolean onToggleMic();
}
VideocallFragment.java:
public class VideocallFragment extends Fragment implements OnCallEvents {
public VideocallFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.video_main, container, false);
surfaceView=rootView.findViewById(R.id.surfaceView);
surfaceView2=rootView.findViewById(R.id.surfaceView2);
button_call_disconnect=rootView.findViewById(R.id.button_call_disconnect);
button_call_disconnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onCallHangUp();
Toast.makeText(getContext(),"Call Disconnected",Toast.LENGTH_LONG).show();
}
});
#Override
public void onCallHangUp() {
socket.disconnect();
}
I am trying to build a sample app which has two fragments in same activity. One fragment has EditText, SeekBar & a Button. Second Fragment has a TextView. On entering text in the EditText of first fragment and setting seekbar to appropriate value and clicking the button will change the text in the second fragment with the text entered in first fragment and size described by seekbar. I wrote a good code but the app keeps crashing on clicking the button. Please help!
Fragment one:
import ....
public class Toolbarfragment extends Fragment implements OnSeekBarChangeListener {
private static int seekvalue = 10;
private static EditText edittext;
public interface ToolbarListener {
void onButtonClick(int pos, String tex);
}
ToolbarListener activityCallback;
#Override
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.toolbarfragment, container, false);
edittext= (EditText)view.findViewById(R.id.editTextTextPersonName);
final Button button = (Button) view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonclicked(v);
}
});
final SeekBar seekBar = (SeekBar) view.findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(this);
return view;
}
public void buttonclicked(View view) {
activityCallback.onButtonClick(seekvalue, edittext.getText().toString());
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
seekvalue = progress;
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
}
#Override
public void onStopTrackingTouch(SeekBar arg0) {
}
}
Fragment two:
import ...
public class TextFragment extends Fragment {
private static TextView textview;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view= inflater.inflate(R.layout.textfragment,container,false);
textview = view.findViewById(R.id.textView);
return view;
}
public void changetextproperties(int size, String text) {
textview.setText(text);
textview.setTextSize(size);
}
}
Main Activity:
import ...
public class MainActivity extends FragmentActivity implements Toolbarfragment.ToolbarListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onButtonClick(int size, String text) {
TextFragment textfragment= (TextFragment)getSupportFragmentManager().findFragmentById(R.id.fragment2);
textfragment.changetextproperties(size, text);
}
}
Logcat :
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.badatext, PID: 13829
java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.badatext.Toolbarfragment$ToolbarListener.onButtonClick(int, java.lang.String)' on a null object reference
at com.example.badatext.Toolbarfragment.buttonclicked(Toolbarfragment.java:52)
at com.example.badatext.Toolbarfragment$1.onClick(Toolbarfragment.java:37)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Figured it out!
By overriding OnAttach() method in Toolbarfragment class
#Override
public void onAttach(Context context) {
super.onAttach(context);
activityCallback = (ToolbarListener) context;}
You may use localbrodcastreceiver or you can use extra values from intent when launching a fragment
I am used in fragment.
error java.lang.IllegalArgumentException: MainActivity#a3d41ec must
implement interface OnEmojiconBackspaceClickedListener
public class Chat extends Fragment implements EmojiconGridFragment.OnEmojiconClickedListener,
EmojiconsFragment.OnEmojiconBackspaceClickedListener {
EmojiconEditText mEditEmojicon;
EmojiconTextView mTxtEmojicon;
public Chat() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_chat, container, false);
mEditEmojicon = (EmojiconEditText) view.findViewById(R.id.editEmojicon);
mTxtEmojicon = (EmojiconTextView) view.findViewById(R.id.txtEmojicon);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mEditEmojicon.addTextChangedListener(new TextWatcher() {
/**
* This notify that, within s,
* the count characters beginning at start are about to be replaced by new text with length
* #param s
* #param start
* #param count
* #param after
*/
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
/**
* This notify that, somewhere within s, the text has been changed.
* #param s
*/
#Override
public void afterTextChanged(Editable s) {}
/**
* This notify that, within s, the count characters beginning at start have just
* replaced old text that had length
* #param s
* #param start
* #param before
* #param count
*/
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Set text on TextView
mTxtEmojicon.setText(s);
}
});
setEmojiconFragment(false);
}
private void setEmojiconFragment(boolean useSystemDefault) {
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.emojicons, EmojiconsFragment.newInstance(useSystemDefault))
.commit();
}
#Override
public void onEmojiconClicked(Emojicon emojicon) {
EmojiconsFragment.input(mEditEmojicon, emojicon);
}
#Override
public void onEmojiconBackspaceClicked(View v) {
EmojiconsFragment.backspace(mEditEmojicon);
}
}
The host Activity must implement the interface for handling back button
click not in the Fragment where you have done
https://github.com/rockerhieu/emojicon/issues/21
Sample Activity
package com.rockerhieu.emojicon.example;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import io.github.rockerhieu.emojicon.EmojiconEditText;
import io.github.rockerhieu.emojicon.EmojiconGridFragment;
import io.github.rockerhieu.emojicon.EmojiconTextView;
import io.github.rockerhieu.emojicon.EmojiconsFragment;
import io.github.rockerhieu.emojicon.emoji.Emojicon;
public class MainActivity extends AppCompatActivity implements EmojiconGridFragment.OnEmojiconClickedListener, EmojiconsFragment.OnEmojiconBackspaceClickedListener {
EmojiconEditText mEditEmojicon;
EmojiconTextView mTxtEmojicon;
CheckBox mCheckBox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEditEmojicon = (EmojiconEditText) findViewById(R.id.editEmojicon);
mTxtEmojicon = (EmojiconTextView) findViewById(R.id.txtEmojicon);
mEditEmojicon.addTextChangedListener(new TextWatcherAdapter() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mTxtEmojicon.setText(s);
}
});
mCheckBox = (CheckBox) findViewById(R.id.use_system_default);
mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
mEditEmojicon.setUseSystemDefault(b);
mTxtEmojicon.setUseSystemDefault(b);
setEmojiconFragment(b);
}
});
setEmojiconFragment(false);
}
private void setEmojiconFragment(boolean useSystemDefault) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.emojicons, EmojiconsFragment.newInstance(useSystemDefault))
.commit();
}
#Override
public void onEmojiconClicked(Emojicon emojicon) {
EmojiconsFragment.input(mEditEmojicon, emojicon);
}
#Override
public void onEmojiconBackspaceClicked(View v) {
EmojiconsFragment.backspace(mEditEmojicon);
}
public void openEmojiconsActivity(View view) {
startActivity(new Intent(this, EmojiconsActivity.class));
}
}
If you have doubts always go back and have a look on original example and compare
https://github.com/rockerhieu/emojicon/tree/master/example/src/main/java/com/rockerhieu/emojicon/example
You need to implement the same listeners for Activity
public class MainActivity extends AppCompatActivity implements EmojiconsFragment.OnEmojiconBackspaceClickedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Why is it not possible to call the checkButtonAddmethod in my Fragment?
public class AddDataFragment extends Fragment {
DbHelper mydb;
Button buttonadd;
Button buttondelete;
private EditText inputLabel;
//Validator boolean
public boolean labelOk;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_add_data, container, false);
final Context context = getContext();
mydb = new DbHelper(context);
[...]
//Label
inputLabel = (EditText) view.findViewById(R.id.editText_label);
inputLabel.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
#Override
public void afterTextChanged(Editable s) {
Pattern p = Pattern.compile("^[A-Z]{3}-[0-9]{4}$");
Matcher m = p.matcher(s);
labelOk = m.find();
Log.d("ButtonAdd?", String.valueOf(labelOk));
}
checkButtonAdd(); // <---------------
});
[...]
return view;
}
public void checkButtonAdd(){
if (labelOk){
buttonadd.setEnabled(true);
}else{
buttonadd.setEnabled(false);
}
};
}
I thought this should work because I used it in another Application. But in the MainActivitiy could this be the mistake and if yes, how can I solve it?
You have to call that method from one of the callback methods using this keyword, to get the instance of enclosing Fragment. For instance..
#Override
public void afterTextChanged(Editable s) {
// Your Statements
AddDataFragment.this.checkButtonAdd();
}
No need to declare the method as static. In fact, declaring it static will be a piece of poor code
You are not in the right scope.
Try
AddDataFragment.checkButtonAdd();
instead.
My Fragment always throws
java.lang.NullPointerException: Attempt to invoke interface method 'void FragmentClass$InputCallbacks.OnTextChanged(java.lang.CharSequence)' on a null object reference
because of the line:
UserInput.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mListener.OnTextChanged(s);
}
});
My other uses of mListener aren't throwing something.
I guess it's because of the use of new Textwatcher(){....} but I'm not experienced enough to solve that by myself :-/
The whole class throwing the error:
public class ToolbarInputOneAddress extends Fragment {
private InputCallbacks mListener;
public ToolbarInputOneAddress() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.toolbar_input_one_address, container, false);
Address address = mListener.getAddress();
EditText UserInput = (EditText) v.findViewById(R.id.InputField);
if (address != null) {
StringBuilder Sb = new StringBuilder();
UserInput.setText(SuggestAddresses.createFormattedAddressFromAddress(address, Sb));
}
UserInput.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mListener.OnTextChanged(s);
}
});
ImageButton ReturnButton = (ImageButton) v.findViewById(R.id.btn_navigation_drawer_back);
ReturnButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.onReturnButtonClicked();
}
});
return v;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (InputCallbacks) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement InputCallbacks");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface InputCallbacks {
void OnTextChanged(CharSequence s);
void onReturnButtonClicked();
Address getAddress();
}
}
I think I solved it.
I declare my callbacks in fragments in groups like this like this
public interface $Callbacks {
void $Callback1(String s);
void $Callback2();
Address $Callback2();
}
Turns out I had multiple Callback Groups defined with the same name. I thought this is okay, because I state that explicitly with implements in my activity.
Since I changed the callback groups names to different ones I don't get the NPE anymore:
TL,DR:
I changed
implements $fragment1.callbacks $fragment2.callbacks $fragment3.callbacks
to
implements $fragment1.f1callbacks $fragment2.f2callbacks $fragment3.f3callbacks
In my activity implementing said fragment callbacks