Search code examples
androidandroid-activityandroid-edittextactivity-lifecycleviewswitcher

Non responding app in "Recent Apps" when PopUpMenu and Edit Text Present


Context

I'm working with popupwindows to allow a user to quickly rename a cardview in an activity.

I do this by using a ViewSwitcher to swap the TextView (original name) for an EditText(new name).

Problem

When the EditText and PopUpWindow to confirm are present an the user presses "RECENT APPS", you cannot for some reason get back into the app. ie. when you click it, it won't respond.

Diagnosis

I think it's an issue with Window Focus. I've tried EditText.clearFocus() from ET and dismissing all PopUps onPause, no luck.

Is there a way to use onFocusChangeListener to remove this issue?

Code (I've tried to remove as much superfluous items as possible)

TheHubActivity.java

public class TheHubActivity extends AppCompatActivity implements RecyclerViewAdapter.onCardClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        // KEYBOARD
        imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        //... Set up recycle view

        rvContent = new ArrayList<>();
    }

    @Override
    public void onCardLongClick(Flow longClickedFlow, int cardPosition, View cardViewClicked) {
        showLongClickPopUpMenu(longClickedFlow,cardPosition, cardViewClicked);
    }

    private void showLongClickPopUpMenu(final Flow longClickedFlow, final int cardPosition, final View cardViewClicked) {

        LayoutInflater layoutInflater = (LayoutInflater) this
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = layoutInflater.inflate(R.layout.popup_window_longclick, null);

        LinearLayout viewGroup = (LinearLayout)  layout.findViewById(R.id.popup_longclick);

        // Creating the PopupWindow
        final PopupWindow popup = new PopupWindow(layout, RecyclerView.LayoutParams.WRAP_CONTENT,
                RecyclerView.LayoutParams.WRAP_CONTENT);


        popup.setFocusable(true);

        // Getting a reference to Close button, and close the popup when clicked.
        ImageView delete = (ImageView) layout.findViewById(R.id.popup_delete_item);

        delete.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                /*.... Delete current Flow from internal file and UI */
                popup.dismiss();
            }
        });

        ImageView edit = (ImageView) layout.findViewById(R.id.popup_edit_item);

        edit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popup.dismiss();
                renameFlow(cardPosition, cardViewClicked);
            }
        });

        // Displaying the popup at the specified location, + offsets.
        popup.showAsDropDown(cardViewClicked, cardViewClicked.getMeasuredWidth(),popupDisplayHeight, Gravity.TOP);

        longClickPopup = popup;
    }

    private void renameFlow(final int cardPosition, final View cardViewClicked) {
        final ViewSwitcher switcher = (ViewSwitcher) cardViewClicked.findViewById(R.id.rename_switcher);
        final EditText rename = (EditText) switcher.findViewById(R.id.item_flow_rename);

        rename.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (rename.hasFocus()) {
                    showEditPopupWindow(rename, cardViewClicked, switcher, cardPosition);
                } else {
                    imm.hideSoftInputFromWindow(rename.getWindowToken(), 0);
                }

            }
        });

        switcher.showNext();

        rename.requestFocus();
        imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
        /* Forces keyboard */


    }

    private void showEditPopupWindow(final EditText newName, View cardViewClicked, final ViewSwitcher switcher, final int cardPosition) {
        LayoutInflater layoutInflater = (LayoutInflater) this
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout = layoutInflater.inflate(R.layout.popup_window_editing, null);

        LinearLayout viewGroup = (LinearLayout)  layout.findViewById(R.id.popup_editing);

        // Creating the PopupWindow
        final PopupWindow popup = new PopupWindow(layout, RecyclerView.LayoutParams.WRAP_CONTENT,
                RecyclerView.LayoutParams.WRAP_CONTENT);

        popup.setFocusable(false); // So that user can edit text

        // Getting a reference to Close button, and close the popup when clicked.
        ImageView confirmEdit = (ImageView) layout.findViewById(R.id.popup_confirm_item_changes);

        confirmEdit.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                /* .. Changes name of cardview through edit text */
                    switcher.showNext();
                    popup.dismiss();
                    newName.clearFocus();
                }

            }
        });

        ImageView cancelEdit = (ImageView) layout.findViewById(R.id.popup_cancel_item_changes);

        cancelEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switcher.showNext();
                popup.dismiss();
            }
        });

        popup.showAsDropDown(cardViewClicked, cardViewClicked.getMeasuredWidth(),popupDisplayHeight, Gravity.TOP);
        editingPopup = popup;
    }


    @Override
    protected void onPause() {
        dismissPopups();
        super.onPause();
    }

    private void dismissPopups() {
        if (longClickPopup!=null && longClickPopup.isShowing()) {
            longClickPopup.dismiss();
        }

        if (editingPopup!=null && editingPopup.isShowing()) {
            editingPopup.dismiss();
        }
    }
}

For Visual People

enter image description here

enter image description here

enter image description here


Solution

  • I solved the issue... and it was surprisingly larger and completely unrelated to the Focus/PopUps (tunnel vision does that I guess).

    In my Manifest I was using android:launchMode="singleTop" which was creating weird behaviour when TheHubActivity was sent to recent apps because this was my entrance activity. From the Developer Docs singleTop functions like so:

    Similarly, a new instance of a "singleTop" activity may also be created to handle a new intent. However, if the target task already has an existing instance of the activity at the top of its stack, that instance will receive the new intent (in an onNewIntent() call); a new instance is not created. In other circumstances — for example, if an existing instance of the "singleTop" activity is in the target task, but not at the top of the stack, or if it's at the top of a stack, but not in the target task — a new instance would be created and pushed on the stack.

    <activity
                android:name=".TheHubActivity"
                android:label="@string/app_name"
                ~~~~~~android:launchMode="singleTop"~~~~~~~~
                android:screenOrientation="portrait">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>