Hot questions for Using Android EditText in android fragments

Top Java Programmings / Android EditText / android fragments

Question:

Intro

Hi guys. Currently I am working on a question-form app. Adding an item in the MainActivity opens a QuestionListActivity. Clicking on the first item opens the Main2Activity which contains 3 fragments (tabbed with Viewpager). Each fragment contains an EditText field to answer the question in. And a Toolbar with a save button. The first question is to give the form a name which is viewable in the MainActivity. Clicking on one of the saved items in the MainActivity opens the QuestionList and then clicking on the first item shows the fragments with their saved data already in the EditText form to view or change. After working in these fragments the save button should save all the fragments at once instead of one at a time.

Problem

First I was able to only save the items. But it wasn't possible to view them. Then I fixed my java classes for each fragment and now it is possible to view all the saved data inside the fragments for each saved item in the MainActivity. But now the problem is that I can't save new data, or change my already saved data, because then I get a null object reference in my private void saveNote part of my code (LogCat).

Question

I obviously shouldn't call title, question2 and question3 in my oncreate method in my Main2Activity, hence this causes the null object reference. But I really don't know how to do this the right way. Hopefully someone knows how to save the data from each fragment inside one item the right way and maybe how to change title, question2 and question3 inside the private void saveNote.

(I searched on StackOverFlow for the right answer, but unfortunately I this wasn't able to help me in this particular way)

Codes

Right here I post the codes of my Main2Activity and one fragment (Frag1). The other fragments are setup in the same way.

 public class Main2Activity extends AppCompatActivity {

    private void saveNote() {

    String title1,title2,title3;
    for(int position = 0; position<mSectionsPagerAdapter.getCount();position++){
        Fragment fragment = mSectionsPagerAdapter.getItem(position);
        if(fragment instanceof Frag1){
            title1 = ((Frag1)fragment).getTitle();
        } else  if(fragment instanceof Frag2){
            title2 = ((Frag2)fragment).getQuestion2();
        } else  if(fragment instanceof Frag3){
            title3 = ((Frag3)fragment).getQuestion3();
        }
    }

    boolean valid = !TextUtils.isEmpty(title1);
    valid = valid && !TextUtils.isEmpty(title2);
    valid = valid && !TextUtils.isEmpty(title3);

    Note note;

    if(!valid()){
        Toast.makeText(this, "Please provide inputs", Toast.LENGTH_SHORT).show();
        return;
    }
    note = new Note((mLoadedNote != null)?mLoadedNote.getDateTime():System.currentTimeMillis(), title.getText().toString(), question2.getText().toString(), question3.getText().toString());

    if (Utilities.saveNote(this, note)){
        Toast.makeText(this, "saved", Toast.LENGTH_SHORT).show();
    } else{
        Toast.makeText(this, "not enough space", Toast.LENGTH_SHORT).show();
    }

    finish();
}

08-23 13:53:52.045 7779-7779/com.example.beginnoteinidee E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.beginnoteinidee, PID: 7779
java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference
    at com.example.beginnoteinidee.Main2Activity.saveNote(Main2Activity.java:109)
    at com.example.beginnoteinidee.Main2Activity.onOptionsItemSelected(Main2Activity.java:139)
    at android.app.Activity.onMenuItemSelected(Activity.java:2885)
    at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:436)
    at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:196)
    at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
    at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
    at android.support.v7.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:64)
    at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:204)
    at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:781)
    at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:840)
    at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:158)
    at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:991)
    at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:981)
    at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:625)
    at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:151)
    at android.view.View.performClick(View.java:4780)
    at android.view.View$PerformClick.run(View.java:19866)
    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:5254)
    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:903)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Answer:

Change your saveNote method like below,

private void saveNote() {

    String title1="",title2="",title3="";
    for(int position = 0; position<mSectionsPagerAdapter.getCount();position++){
        Fragment fragment = mSectionsPagerAdapter.getItem(position);
        if(fragment instanceof Frag1){
            title1 = ((Frag1)fragment).getTitle();
        } else  if(fragment instanceof Frag2){
            title2 = ((Frag2)fragment).getTitle();
        } else  if(fragment instanceof Frag2){
            title3 = ((Frag2)fragment).getTitle();
        }
    }

    boolean valid = !TextUtils.isEmpty(title1);
    valid = valid && !TextUtils.isEmpty(title2);
    valid = valid && !TextUtils.isEmpty(title3);

    Note note;

    if(!valid){
        Toast.makeText(this, "Please provide inputs", Toast.LENGTH_SHORT).show();
        return;
    }
    note = new Note((mLoadedNote != null)?mLoadedNote.getDateTime():System.currentTimeMillis(), title1, title2, title3);

    if (Utilities.saveNote(this, note)){
        Toast.makeText(this, "saved", Toast.LENGTH_SHORT).show();
    } else{
        Toast.makeText(this, "not enough space", Toast.LENGTH_SHORT).show();
    }

    finish();
}

You also need to create method getTitle on each fragment Frag1, Frag2 and Frag3.

For example,

Frag1

public String getTitle(){
 return mEtTitle.getText().toString();
}

Question:

I have a MainActivity (MA) running several fragments, which do not talk to each other but communicate to the MA via the 'onClick' android mechanism. Driven by a spinner choice and an 'onClick' button press, we arrive in the RetrievePatientRecord method of the MA.

I carry out a database call to get the chosen db record (as per the commented line) and then test to see if there is an existingPatient fragment present into which I intend to put the database record's various fields as its essentially a form. With a not found, 'null' condition, I instantiate a new instance of a ExistingPatientFg fragment. However when I attempt to use the existingPatient reference via a setter in the ExistPatientFg fragment to set the 'Title' field value the program falls over with a NPE !

I have tried to 'get the fragment address' using commented out line … getFragmentManager().findFragmentById(R.id….) but interestingly using android studio's code completion facility the only R.id. object it will offer is the 'fragment_container' which though it compiles, it falls over on this line of code if I leave it in.

So I'm a bit stumped. I've read through most of the other S/O answers in this fragment/MainActivity/edit text field, subject area but haven't been able to get a solution which can help me, so I'm after some assistance here. (also it may be relevant that my activity_main.xml layout file is using a FrameLayout layout with its id as 'fragment_container')

   public void RetrievePatientRecord(View view) {
//   do database query to get record before displaying in patient record fragment
             this.patientID = findPatientRecordFg.patientID;
        Log.d(DEBUGTAG, " ---->>>>> retrieve this record L 404 with ID =  " + findPatientRecordFg.patientID);

// db query for existing patient's records
          findPatientRecordFg.db.getPatientRecords(patientID);

// populate patientdetails fragment fields and re display patientdetails fragment.

        if (existingPatient != null) {

            populatePatientDetails_fgWithCurrentValues();
            trans = getFragmentManager().beginTransaction();
            trans.replace(R.id.fragment_container, existingPatient);
            trans.addToBackStack(null);
            trans.commit();
        }else
        if (existingPatient == null){

            existingPatient = new ExistingPatientFg();
          // ExistingPatientFg existingPatient = (ExistingPatientFg)getFragmentManager().findFragmentById(R.id.fragment_container);
            cTitle      = findPatientRecordFg.db.geteTitle();

            Log.d(DEBUGTAG, " ######## -->>>>> reached just before setTitleField L 424 with value Title  =  "+ cTitle);
            existingPatient.setTitleField(cTitle);

            //populatePatientDetails_fgWithCurrentValues();
            trans = getFragmentManager().beginTransaction();
            trans.replace(R.id.fragment_container, existingPatient);
            trans.addToBackStack(null);
            trans.commit();
        }
    }

the fragment's java code is :-

public class ExistingPatientFg extends Fragment {
public ButtonPlus btn;
public ButtonPlus analysisBtn;


@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.patientdetails_fg, container, false);
    return view;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    EditText editText = (EditText)getView().findViewById(R.id.bannerText);
    editText.setText("Existing Patient");

    btn = (ButtonPlus)getActivity().findViewById(R.id.Goto_Scanning_Page);

    analysisBtn = (ButtonPlus)getView().findViewById(R.id.Analysis);
    btn.setEnabled(true);

}


public void setTitleField(String string){
    EditText et = (EditText)getView().findViewById(R.id.Title);
    et.setText(string);
}

Answer:

I suspect that the null pointer exception is not that you don't have a reference to the fragment, but that you are calling setTitleField before the fragment view has been inflated so the edit text field doesn't exist yet.

Try moving setTitleField to after the trans.commit or better yet pass the title to the fragment as an extra argument.

existingPatient = new ExistingPatientFg();
Bundle bundle = new Bundle();
bundle.putString("title",cTitle);
existingPatient.setArguments(bundle);                 
trans = getFragmentManager().beginTransaction();
trans.replace(R.id.fragment_container, existingPatient);
trans.addToBackStack(null);
trans.commit();

And use the following inthe Fragment's onCreateView to get the title

String cTitle = getArguments().getString("title");

See How to pass a variable from Activity to Fragment, and pass it back?

Question:

i have a fragment with 3 edit texts and 1 text view. i want to get inputs from those edit texts. but it force closes. what is the problem? my code:

View view = inflater.inflate(R.layout.bmi_fragment,
            container, false);
    EditText age = (EditText) view.findViewById(R.id.editText_age);
    EditText weight = (EditText) view.findViewById(R.id.editText_weight);
    EditText height = (EditText) view.findViewById(R.id.editText_height);
    int age_value = Integer.parseInt(age.getText().toString());
    int weight_value = Integer.parseInt(weight.getText().toString());
    int height_value = Integer.parseInt(height.getText().toString());
    int calc = (weight_value / ((height_value / 100) * (height_value / 100)));
    TextView dd = (TextView) view.findViewById(R.id.result_bmi_textView);
    dd.setText(calc);

Answer:

Add a control for empty EditText

View view = inflater.inflate(R.layout.bmi_fragment,
        container, false);
EditText age = (EditText) view.findViewById(R.id.editText_age);
EditText weight = (EditText) view.findViewById(R.id.editText_weight);
EditText height = (EditText) view.findViewById(R.id.editText_height);
try {
        int age_value = Integer.parseInt(age.getText().toString());
        int weight_value = Integer.parseInt(weight.getText().toString());
        int height_value = Integer.parseInt(height.getText().toString());
        int calc = (weight_value / ((height_value / 100) * (height_value / 100)));
        TextView dd = (TextView) findViewById(R.id.textView);
        dd.setText(calc+"");
} catch (Exception e){
    //Textfield empty
}

Question:

In myfragment class witch extends Fragment I'm finding object reference in onCreateView method

private static final String TAG = "CloadLab";


private Cloud dCloud;
private EditText dNameText;
public String dNameHolder = "";




@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

    UUID dreamId = (UUID)getArguments().getSerializable(EXTRA_DREAM_ID);




}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    getActivity().setTitle("Add new");

}

@Override
public View onCreateView(LayoutInflater inflater,
                         ViewGroup parent, Bundle savedInstanceState){

    View v = inflater.inflate(R.layout.fragment_add,parent,false);

    dNameText = (EditText) v.findViewById(R.id.dream_name);


    return v;
}

public void SaveDream (){


    dNameHolder = dNameText.getText().toString();

    if (dNameText != null) {
        Log.e(TAG,"not null");
    }else if (dNameText == null){
        Log.e(TAG,"null");
    }


}

}

which works fine if I use it within onCreateView method, but for example I want to use dNameText in this method which is in same class

public void SaveDream (){
   dNameHolder = dNameText.getText().toString();
}

and now it has null object reference how can I fix that and how can I set references through whole class?

I'm calling this SaveDream() method from Activity which holds this Fragment

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {

        case R.id.action_favorite:

            AddFragment mActivity= new AddFragment();
            mActivity.SaveDream();
            finish();
            return true;
    }

    return super.onOptionsItemSelected(item);


}

Every Activity extends SingleFragmentActivity and has these methods in it

        private AddFragment mFragment;

@Override
    protected Fragment createFragment() {

    UUID dreamId = (UUID)getIntent()
            .getSerializableExtra(AddFragment.EXTRA_DREAM_ID);
    return AddFragment.newInstance(dreamId);
}

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        //setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);


    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.action_bar_menu,menu);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

            case R.id.action_favorite:

               // AddFragment mActivity= new AddFragment();
               // mActivity.SaveDream();
                //finish();
                mFragment = new AddFragment();
                FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
                fragmentTransaction.replace(android.R.id.content, mFragment);
                fragmentTransaction.commit();
                mFragment.SaveDream();
                finish();
                return true;
        }

        return super.onOptionsItemSelected(item);


    }

SingleFragmentActivity

    protected abstract Fragment createFragment();

@Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_fragment);
    FragmentManager fm = getSupportFragmentManager();
    Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);

   // getSupportActionBar().setDisplayHomeAsUpEnabled(false);


    if (fragment == null){
        fragment = createFragment();
        fm.beginTransaction()
                .add(R.id.fragmentContainer, fragment)
                .commit();
    }

}

Answer:

You are calling SaveDream method on a new instance of the fragment, not the one which is loaded right now at

AddFragment mActivity= new AddFragment();
mActivity.SaveDream();

Because the view is not created on the new instance (view is created while loading) and you are getting null for EditText. You should keep the loaded instance globally and call the method on that instance.

Follow these steps.

Step 1: Create a class level variable

private AddFragment mFragment;

Step 2: Load Fragment like this

mFragment = new AddFragment();

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(android.R.id.content, mFragment);
fragmentTransaction.commit();

Step 3: Call method like this

mFragment.SaveDream();

Update

Update method like this

@Override
protected Fragment createFragment() {
    UUID dreamId = (UUID)getIntent()
        .getSerializableExtra(AddFragment.EXTRA_DREAM_ID);
    mFragment = AddFragment.newInstance(dreamId);
    return mFragment;
}

and

case R.id.action_favorite:
    mFragment.SaveDream();
    return true;    

Question:

I opening Fragment B from Fragment A with startActivityForResult when Fragment B closes I get String value from EditText to Fragment A and everything works fine but now I opening same Fragment B from Fragment A and I want it to have that earlier returned value but it disappears

here I'm storing purposeText value from editText but not saving to json yet I want it to be saved on exiting Fragment A

    public class Cloud {


    private static final String JSON_ID = "id";
    private static final String JSON_PURPOSE = "purpose";

    private UUID mId;
    private String purposeText = "";



    public Cloud() {

        mId = UUID.randomUUID();
    }



    public Cloud(JSONObject json) throws JSONException {
        mId = UUID.fromString(json.getString(JSON_ID));
        if (json.has(JSON_PURPOSE)){
            purposeText = json.getString(JSON_PURPOSE);
        }

    }

    public JSONObject toJSON() throws JSONException{

        JSONObject json = new JSONObject();
        json.put(JSON_ID, mId.toString());
        json.put(JSON_PURPOSE, purposeText);

        return json;
    }


    @Override
    //Using get and set methods to get it in private String
    public String getPurposeText(){return purposeText;}
    public void setPurposeText(String purpose){purposeText = purpose;}



    public UUID getId() {return mId;};

}

In Fragment A I'm getting text and setting it to textview and it works, then setting it back to setter in Cloud class

    public class AddFragment extends Fragment {

    private static final String TAG = "Cload";
    public static final String EXTRA_DREAM_ID = "com.example.tadas.dreamcload1.dream_id";
    private static final  int REQUEST_DATE = 0;
    private static final int REQUEST_TEXT =1;

    private Cloud dCloud;
    private TextView purposeView;
    private String comeBackPurpose;



    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        dCloud = new Cloud();
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        getActivity().setTitle("Add new dream");

    }

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup parent, Bundle savedInstanceState){

        View v = inflater.inflate(R.layout.fragment_add,parent,false);

        purposeView = (TextView)v.findViewById(R.id.dream_purpose);
        purposeView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(getActivity(),DreamPurposeActivity.class);
                startActivityForResult(i,REQUEST_TEXT);
            }
        });

        return v;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_TEXT){

            comeBackPurpose = data.getStringExtra("comeBackPurpose");
           // Log.e(TAG,"SHITFACE " + comeBackPurpose);
            purposeView.setText(comeBackPurpose);
            dCloud.setPurposeText(comeBackPurpose);
            Log.e(TAG,"SHITFACE " + dCloud.getPurposeText());
        }
    }


    public static AddFragment newInstance(UUID dreamId) {
        Bundle args = new Bundle();
        args.putSerializable(EXTRA_DREAM_ID, dreamId);

        AddFragment fragment = new AddFragment();
        fragment.setArguments(args);

        return  fragment;
    }
}

Now In Fragment B I'm trying to set that text back to EditText in onCreateView method but it gets default value, what should I do to fix that?

    public class PurposeFragment extends Fragment {

    public static final String EXTRA_D = "com.dropstudio.drea.dr_ids";
    private static final String TAG = "Cload";

    private EditText purposeEText;
    private String purposeEditText;
    private Cloud mCloud;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mCloud = new Cloud();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.dream_purpose_edit,container,false);
        purposeEText = (EditText)v.findViewById(R.id.purpose_edit);


        purposeEText.setText(mCloud.getPurposeText());

        return v;
    }


    public void savePurpose(){

        purposeEditText = purposeEText.getText().toString();
        mCloud.setPurposeText(purposeEditText);
        Intent returnIntent = new Intent();
        returnIntent.putExtra("comeBackPurpose",purposeEditText);
        getActivity().setResult(Activity.RESULT_OK,returnIntent);
        getActivity().finish();


    }

    public static PurposeFragment newInstance(UUID dreaIds) {
        Bundle args = new Bundle();
        args.putSerializable(EXTRA_D, dreaIds);

        PurposeFragment fragment = new PurposeFragment();
        fragment.setArguments(args);

        return fragment;
    }
}

Answer:

In Fragment B , you are creating a new Cloud object in onCreate() and trying to get the value from that object in onCreateView() which will always be null.

 @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mCloud = new Cloud(); //New instance will be created
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.dream_purpose_edit,container,false);
        purposeEText = (EditText)v.findViewById(R.id.purpose_edit);


        purposeEText.setText(mCloud.getPurposeText()); // 'mCloud' is a new object everytime and hence will not have your saved value

        return v;
    }

For your task, either use SharedPreferences or pass the saved value while instantiating Fragment B.