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.
Related
I have an EditText where I need to hold its value in a MutableLiveData in a viewmodel.
Is it okay to be calling the method setValue("the changed edittext string") every time the user edits something in the EditText?
The reason why I'm doing this is to keep the data alive even if the user for example rotated the screen.
Is there any other way to achieve the same result? Cause I feel like it can be expensive and it's a bad practice calling the method over and over. here's an example in an activity:
public class NoteActivity extends AppCompatActivity {
private ActivityNoteBinding binding;
private NoteViewModel viewmodel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_note);
viewmodel = new ViewModelProvider(this).get(NoteViewModel.class);
addObservers();
addListeners();
}
private void addObservers() {
viewmodel.noteBodyLiveData.observe(this, s -> binding.noteBody.setText(s));
}
private void addListeners() {
binding.noteBody.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) {
viewmodel.noteBodyLiveData.setValue(String.valueOf(s));
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
The LiveData Objects are initialized with the data corresponding to what's in the database.
Thanks in advance!
I want the listView to be displayed only when a search string is inserted in the EditText. Below is my code...Please help me I would be highly obliged...
public class MainActivity extends AppCompatActivity {
private ListView mSearchNFilterLv;
private EditText mSearchEdt;
private ArrayList<String> mStringList;
private ValueAdapter valueAdapter;
private TextWatcher mSearchTw;
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUI();
initData();
valueAdapter = new ValueAdapter(mStringList, this);
mSearchNFilterLv.setAdapter(valueAdapter);
mSearchEdt.addTextChangedListener(mSearchTw);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
private void initData() {
mStringList = new ArrayList<String>();
mStringList.add("one");
mStringList.add("two");
mStringList.add("three");
mStringList.add("four");
mStringList.add("five");
mStringList.add("six");
mStringList.add("seven");
mStringList.add("eight");
mStringList.add("nine");
mStringList.add("ten");
mStringList.add("eleven");
mStringList.add("twelve");
mStringList.add("thirteen");
mStringList.add("fourteen");
mSearchTw = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
valueAdapter.getFilter().filter(s);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
if(mSearchEdt.getVisibility() != View.VISIBLE)
mSearchEdt.setVisibility(View.VISIBLE);
}
};
}
private void initUI() {
mSearchNFilterLv = (ListView) findViewById(R.id.list_view);
mSearchEdt = (EditText) findViewById(R.id.txt_search);
}
}
You can use the code below:
mSearchTw = 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) {
if (s != null && s.toString().trim().length() > 0) {
mSearchNFilterLv.setVisibility(View.VISIBLE);
} else {
mSearchNFilterLv.setVisibility(View.GONE);
}
}
#Override public void afterTextChanged(Editable s) {
}
};
This will show the ListView when there is an entered text (while entering text to EditText) and if text has 1 or more characters.
If you want ListView to be changed only when the insertion is over move the given code inside onTextChanged to afterTextChanged
PS: You can use the same structure with SearchView instead of EditText with query listeners.
Updated
You can use below code to hide ListView initially:
private void initUI() {
mSearchNFilterLv = (ListView) findViewById(R.id.list_view);
mSearchEdt = (EditText) findViewById(R.id.txt_search);
mSearchNFilterLv.setVisibility(View.GONE);
}
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;
}
}
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
Is it possible to create variables before the onCreate() method in Android? I have tried doing so in the past but to no avail so I'm assuming you cant, but I just want to double check. The reason why is because I am trying to access a variable in my TextWatcher that serves as a counter, but its out of scope and asking for me to make it final, which obviously doesnt work since its serving as a counter and is needed to increment. I have attached my code below:
int counter = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText answerText = (EditText) findViewById(R.id.answer);
final TextView text = (TextView) findViewById(R.id.wordtoanswer);
final ArrayList updatedList = helperMethod();
text.setText(updatedList.get(0).toString());
final String wordFinal = updatedList.get(0).toString();
while(true)
{
answerText.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub
}
public void afterTextChanged(Editable s) {
System.out.println(counter);
String answer = s.toString();
if(answer.equals(wordFinal))
{
text.setText(updatedList.get(counter).toString());
answerText.setText("");
}
}
});
counter++;
}
}
Hopefully you guys understand why I'm trying to declare it before the onCreate(), because only then can the methods inside the TextWatcher actually access it without them being out of scope. Is there anyway I can get around this problem? Please let me know if you need more information/code!
Declare the reference as a member variable:
private TextView text;
Instantiate it in OnCreate method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.wordtoanswer);
//...
}