Question

New programmer here. I want the Add button on my screen to enable only when all fields are non-empty. However, adding a TextWatcher is making the screen crash. Asking elsewhere, it seems I shouldn't try to access my EditText with my ContentView set to activity_add_grade. But I need help understanding the right way to do things.

The template/tutorial I followed had me create 2 xml files per activity. As seen below, my AddClass sets the contentView to activity_add_grade and then inflates fragment_add_grade, which is where my screen design and views are. So the problem with accessing my EditText views from onCreate is that my ContentView is not set to the xml that contains the views. So where should I set my listeners instead? And why are there two xmls anyway? I'd like to understand more and follow the best practice. Thanks!

AddClass -- the java for the activity in question

public class AddClass extends ActionBarActivity {

DBAdapter db = new DBAdapter(this);

private EditText editText1;
private EditText editText2;

public TextWatcher watcher = new TextWatcher(){
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    }
    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        checkFieldsForEmptyValues();
    }
    @Override
    public void afterTextChanged(Editable editable) {
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_add_grade);

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment()).commit();
    }
    // setContentView(R.layout.fragment_add_grade); //Tried this. Doesn't work

    editText1 = (EditText)findViewById(R.id.editTitle);
    editText2 = (EditText)findViewById(R.id.editCredit);

    editText1.addTextChangedListener(watcher);
    editText2.addTextChangedListener(watcher);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.add_grade, menu);

    //Code here for spinners on screen. Removed for space
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

private void checkFieldsForEmptyValues() {

    Button b = (Button)findViewById(R.id.addClassButton);
    System.out.println("in the check fields thing");
    String s1 = editText1.getText().toString();
    String s2 = editText2.getText().toString();

    if(s1.isEmpty() || s2.isEmpty()) {
        b.setEnabled(false);
    } else {
        b.setEnabled(true);
    }

}

// THIS WORKS -- the method is bigger, but I shortened it for space.
public void createNewClass(View v) {
    EditText titleTxt = (EditText)findViewById(R.id.editTitle);
    //ToStrings
    String titleStr = titleTxt.getText().toString();
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    public PlaceholderFragment() {
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_add_grade,
                container, false);
        return rootView;
    }
}
Was it helpful?

Solution

Well the view you are looking for is in your fragment's layout, so you should handle that view inside your fragment.

Option A:

remove all EditText-related code from your Activity onCreate method. Create fields watcher and editText1, editText2 inside the Fragment. So your PlaceholderFragment code should look more or less like this:

public static class PlaceholderFragment extends Fragment {

    EditText editText1, editText2;

    public TextWatcher watcher = new TextWatcher(){
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }
        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            checkFieldsForEmptyValues();
        }
        @Override
        public void afterTextChanged(Editable editable) {
        }
    };

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container,
                false);

        editText1 = (EditText) rootView.findViewById(R.id.editTitle);
        editText1.addTextChangedListener(watcher);
        editText2 = (EditText) rootView.findViewById(R.id.editCredit);
        editText2.addTextChangedListener(watcher);
        return rootView;
    }
}

Option B:

Since it looks like your fragment is the autogenerated one from eclipse and you may not want to use fragments in your code you can do this: Drop your fragment code & layout and move the edittexts from your fragment layout in to your activitiy layout. Then your onCreate code of the Activity should work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top