0

I have a simple application (really!) that displays a list and then displays the details of an item on the list based on the user's choice. I do this using Fragments. The details portion is a Fragment which has an EditText in it. Currently, if the user types in the EditText and clicks on the Save button, an AlertDialog.Builder pops up asking her if she wants to save. If she chooses yes, the text is saved to a database. I want the same thing to happen if the user hits the back button. In my class that extends FragmentActivity, I have:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{

    super.onKeyDown(keyCode, event);

    DetailFrag frag = (DetailFrag) getSupportFragmentManager().findFragmentById(R.id.frag_stitchdetail);
    frag.onKeyDown(keyCode, event);
    return false;
}

In my class that extends Fragment (the details portion), I have:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_ENTER && event.getRepeatCount() == 0
            && Edited) {
        return true;
    }
    else
        return false;
}

I'm not sure where to put the code that will call the AlertDialog.Builder. I want to put it in the Fragment class because the code needs to get the rowID of the detail from the list (a class that extends ListFragment). That information isn't available to the FragmentActivity class. For clarification, here's the code I use to operate the Save button. It's called from the onCreateView method of the Fragment class and I want to re-use this code (put it in its own method, probably) when the back button is hit.

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

    View view = inflater.inflate(R.layout.detailfragment, container, false);
    Typeface danielFont = Typeface.createFromAsset(getActivity().getAssets(),
            "danielbk.ttf");

    final EditText notes = (EditText)view.findViewById(R.id.stitchnotes);
    notes.setTypeface(danielFont);
    notes.setTextSize(12);

    builder = new AlertDialog.Builder(getActivity());
    builder.setMessage("Do you want to save your Notes?");
    builder.setCancelable(false);

    builder.setPositiveButton("Yes",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {

                    String Notes = notes.getText().toString();
                    Uri updateUri = ContentUris.withAppendedId(STITCHES_URI, rowID);
                    ContentValues values = new ContentValues();
                    values.put("stitchnotes", Notes);
                    getActivity().getContentResolver().update(updateUri,values,null,null);
                }
            });

    builder.setNegativeButton("No",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                    //getActivity().finish();
                }
            });

    alert = builder.create();

    ImageButton savebutton = (ImageButton)view.findViewById(R.id.savebutton);
    savebutton.setOnClickListener(new ImageButton.OnClickListener() {

        public void onClick(View v) {
            alert.show();
        }
    });
    notes.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) {
            Edited = true;

        }
    });

    return view;
}

The rowID that's used when I declare updateURI comes from the ListFragment class like so:

DetailFrag frag = (DetailFrag) getFragmentManager().findFragmentById(R.id.frag_stitchdetail);
if (frag != null && frag.isInLayout()) {
     //more code
     frag.setRowID(stitchid);
}

setRowID is defined in the Fragment class:

public void setRowID(int row_id)
{
    rowID = row_id;
}

and rowID is a private static int in the Fragment class.

Can someone please point me in the right direction?

Melanie
  • 3,021
  • 6
  • 38
  • 56

1 Answers1

2

Two options I can see.

One:

public boolean onKeyDown(int keyCode, KeyEvent event)
{
    if(keyCode == KeyEvent.KEYCODE_BACK) {
        backPressed = true;
        alert.show();
        return true; // shows you consumed the event with your implementation
    }
    // blah, blah, other code
}

Add the following lines to your dialog yes and no OnClickListeners:

if (backPressed){
    finish();// - to exit the Activity
}

Alternately, create two separate builders as follows:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // other code

    builder = new AlertDialog.Builder(getActivity());
    builder.setMessage("Do you want to save your Notes?");
    builder.setCancelable(false);

    builder.setPositiveButton("Yes",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    saveNotes();
                }
            });

    builder.setNegativeButton("No",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            });

    alertSave = builder.create();


    builder.setPositiveButton("Yes",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    saveNotes();
                    finish();
                }
            });

    builder.setNegativeButton("No",
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                    finish();
                }
            });

    alertBack = builder.create();

    ImageButton savebutton = (ImageButton)view.findViewById(R.id.savebutton);
    savebutton.setOnClickListener(new ImageButton.OnClickListener() {

        public void onClick(View v) {
            alertSave.show();
        }
    });
    // other code
}

public boolean onKeyDown(int keyCode, KeyEvent event)
{
    if(keyCode == KeyEvent.KEYCODE_BACK) {
        alertBack.show();
        return true; // shows you consumed the event with your implementation
    }
    // blah, blah, other code
}        


private void saveNotes() {
    String Notes = notes.getText().toString();
    Uri updateUri = ContentUris.withAppendedId(STITCHES_URI, rowID);
    ContentValues values = new ContentValues();
    values.put("stitchnotes", Notes);
    getActivity().getContentResolver().update(updateUri,values,null,null);
}
Catherine
  • 13,588
  • 9
  • 39
  • 60
  • Catherine, thanks for your detailed answer. I've tried both options and neither works. I've walked through the code in the debugger and when I hit the Back button, I get to either the alertBack.show() line or the backPressed = true line in the onKeyDown method. Then the debugger moves past that line to the return false I have in my else statement. Never goes to the return true in the if statement. The dialog continues to display when I hit the Save button, but I never see it when I hit the Back button. I'm missing something here, but I don't have a clue what it is. Any ideas? – Melanie Feb 07 '14 at 16:40
  • Also - I assumed that the if (backPressed) section you specified should come at the end of the yes and no OnClickListeners and that if I'm using that strategy, I don't need two separate builders for alertSave and alertBack. Am I right? – Melanie Feb 07 '14 at 16:43
  • This now works, although I admit I'm befuddled by how. 1) I deleted the if(keyCode == KeyEvent.KEYCODE_BACK) section of the onKeyDown method in the FragmentActivity class. Clearly that wasn't needed; don't know what I was thinking. See my edited code above. 2) putting the code to save the contents of the EditText in a separate method wasn't working, so I just duplicated it in each onClickListener method. Finally, and this is what troubles me, I changed the final return false to return true in the Fragment's onKeyDown method. I'm pretty sure this is wrong, but don't know how to get around it. – Melanie Feb 07 '14 at 19:30
  • Hmm, there is some interesting stuff going on there. I've had cases when the debugger would behave in weird ways like that. It can be helpful to put logging statements in those cases--logging statements don't (usually) lie. If you're using the if(backPressed) strategy then yes, one builder will do (or more accurately, one alert). – Catherine Feb 07 '14 at 22:53
  • I'm a little confused by your new onKeyDown method--I do think you need that KeyEvent.KEYCODE_BACK, at least if I remember correctly. Why wasn't putting the code to save the contents of the EditText in a separate method working? the code duplication is probably not ideal... – Catherine Feb 07 '14 at 22:55
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/47059/discussion-between-catherine-and-melanie) – Catherine Feb 07 '14 at 22:56
  • My company blocks chat. Let me put some logging statements in my code and poke around a bit. If I need to use chat, could you let me know what times you're available for chat? I could do this from home if need be; I'm on EST. – Melanie Feb 10 '14 at 15:45
  • Pretty much anytime, really, other than what can loosely be considered "dinnertime" on PST. – Catherine Feb 10 '14 at 21:51
  • Catherine, I think I've got it figured out, so I won't need to chat, but I REALLY appreciate your willingness to help. Your answer got me 95% there. The rest was 1) uncommenting the onKeyDown in the Fragment Activity and moving the code that dealt with the Detail Fragment onKeyDown to within that block and 2) overriding the onKeyDown method in the List Fragment also. I'm going to work on getting the code that saves the Edit Text contents to a separate method, but that's a different issue. Anyway, THANK YOU!!! – Melanie Feb 11 '14 at 16:27