android - 对话框 fragment 问题 : onCreateDialog not called; can't get back key press

标签 android android-fragments android-dialogfragment

我所拥有的是一个将我的游戏 fragment 插入 fragment 容器的 MainActivity:

import android.app.FragmentManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.DialogFragment;
import android.support.v4.view.ViewGroupCompat;
import android.support.v7.app.ActionBar;
import android.text.Layout;
import android.util.Log;
import android.view.View;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener, Game.OnFragmentInteractionListener,
        Roster.OnFragmentInteractionListener, Stats.OnFragmentInteractionListener,
        Settings.OnFragmentInteractionListener, CurrentGame.OnFragmentInteractionListener, NewGame.OnFragmentInteractionListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = (TextView) findViewById(R.id.toolbar_title);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);


        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        if (savedInstanceState == null) {

            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.fragment_container, new Game(),"fragment_game")
                    .commit();

        }

    }

    @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();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.

        android.support.v4.app.FragmentTransaction transact = getSupportFragmentManager().beginTransaction();

        int id = item.getItemId();

        if (id == R.id.nav_games) {
            transact.replace(R.id.fragment_container, new Game()).commit();
        } else if (id == R.id.nav_roster) {
            transact.replace(R.id.fragment_container, new Roster(), "fragment_roster").commit();
        } else if (id == R.id.nav_stats) {
            transact.replace(R.id.fragment_container, new Stats(), "fragment_stats").commit();
        } else if (id == R.id.nav_settings) {
            transact.replace(R.id.fragment_container, new Settings(), "fragment_settings").commit();
        } 

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
    public boolean isEdited(int Id){
        ViewGroup view = (ViewGroup) findViewById(Id);
        for (int i = 0; i <= view.getChildCount(); i++){
            View v = view.getChildAt(i);
            if(v instanceof EditText){
                EditText ET = (EditText) findViewById(view.getChildAt(i).getId()) ;
                if (ET.getText().length() != 0){
                    return true;
                }
            }
        }
        return false;

    }


    @Override
    public void onFragmentInteraction(Uri uri) {

    }
}

游戏 fragment 创建一个对话 fragment :
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;

import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;


public class Game extends Fragment  {

    static final int NUM_ITEMS = 2;

    private OnFragmentInteractionListener mListener;

    public Game() {
        // Required empty public constructor
    }


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

    }


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

        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_game, container, false);
    }

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

        TextView tv = (TextView) getActivity().findViewById(R.id.toolbar_title);
        tv.setText("Games");

        Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar_game);
        ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);

        final ViewPager viewPager = (ViewPager) getActivity().findViewById(R.id.viewpager_game);
        setupViewPager(viewPager);

        TabLayout tabLayout = (TabLayout) getActivity().findViewById(R.id.tablayout_game);
        tabLayout.setupWithViewPager(viewPager);

        FloatingActionButton fab = (FloatingActionButton) getActivity().findViewById(R.id.fab_game);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showDialog();
            }
        });

    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
        adapter.addFrag(new gameTab(), "My Team");
        adapter.addFrag(new scoutTab(), "Scout");
        viewPager.setAdapter(adapter);
    }


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }
        public void showDialog() {
        android.support.v4.app.FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        //android.support.v4.app.CustomDialogFragment newFragment = new getActivity().CustomDialogFragment();
        // The device is smaller, so show the fragment fullscreen
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        // For a little polish, specify a transition animation
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity
        transaction.add(android.R.id.content, new NewGame())
                .addToBackStack(null).commit();
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }

    class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
        @Override
        public int getCount() {
            return mFragmentList.size();
        }
        public void addFrag(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }
        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }

    public static class gameTab extends Fragment {
        int color;
        //SimpleRecyclerAdapter adapter;
        public gameTab() {
        }
        @SuppressLint("ValidFragment")
        public gameTab (int color) {
            this.color = color;
        }
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_game_tab, container, false);
            final FrameLayout frameLayout = (FrameLayout) view.findViewById(R.id.frame_game_tab);
            frameLayout.setBackgroundColor(color);
            /*RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.game_tab_scrollableview);
            LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity().getBaseContext());
            recyclerView.setLayoutManager(linearLayoutManager);
            recyclerView.setHasFixedSize(true);
            List<String> list = new ArrayList<String>();
            for (int i = 0; i < VersionModel.data.length; i++) {
                list.add(VersionModel.data[i]);
            }
            adapter = new SimpleRecyclerAdapter(list);
            recyclerView.setAdapter(adapter);*/
            return view;
        }
    }


/*    public static class gameTab extends Fragment {

        private OnFragmentInteractionListener mListener;

        public gameTab() {
            // Required empty public constructor
        }


        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_game_tab, container, false);
        }

        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            if (context instanceof OnFragmentInteractionListener) {
                mListener = (OnFragmentInteractionListener) context;
            } else {
                throw new RuntimeException(context.toString()
                        + " must implement OnFragmentInteractionListener");
            }
        }

        @Override
        public void onDetach() {
            super.onDetach();
            mListener = null;
        }

        public interface OnFragmentInteractionListener {
            // TODO: Update argument type and name
            void onFragmentInteraction(Uri uri);
        }
    }*/
    public static class scoutTab extends Fragment {

        private OnFragmentInteractionListener mListener;

        public scoutTab() {
            // Required empty public constructor
        }


        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_scout_tab, container, false);
        }

        /*@Override
        public void onAttach(Context context) {
            super.onAttach(context);
            if (context instanceof OnFragmentInteractionListener) {
                mListener = (OnFragmentInteractionListener) context;
            } else {
                throw new RuntimeException(context.toString()
                        + " must implement OnFragmentInteractionListener");
            }
        }*/



    @Override
        public void onDetach() {
            super.onDetach();
            mListener = null;
        }


        public interface OnFragmentInteractionListener {
            // TODO: Update argument type and name
            void onFragmentInteraction(Uri uri);
        }
    }

}

在这个对话 fragment 中,我想拦截 onBackPressed() 以在按下后退键时显示一个弹出窗口。我花了将近 2 天的时间,在堆栈溢出问题上尝试了这里的好人提出的许多不同建议,但无济于事。提出的看似最佳的解决方案之一here对我不起作用,因为我的 onCreatDialog 方法从未被调用过。

这是对话 fragment 代码(如您所见,我正在测试以查看实际调用了哪些方法):
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;

public class NewGame extends DialogFragment {

    EditText entryAway, entryHome;
    private OnFragmentInteractionListener mListener;
    private OnFragmentInteractionListener mListener2;

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

        FloatingActionButton fab = (FloatingActionButton) getActivity().findViewById(R.id.fab_game);
        fab.setVisibility(View.GONE);

        entryAway = (EditText) getActivity().findViewById(R.id.entry_away);

        setHasOptionsMenu(true);

        View rootView = inflater.inflate(R.layout.fragment_new_game, container, false);

        Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar_newg);
        toolbar.setTitle("");


        ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);

        ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeButtonEnabled(true);
            actionBar.setHomeAsUpIndicator(R.drawable.ic_close);
        }



        return rootView;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Log.d("Diag Frag", "This is the diag frag");
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        return dialog;

    }

    @Override
    public void onCancel (DialogInterface dialogInterface){
        super.onCancel(dialogInterface);
        Log.d("Diag Frag", "This is called");
    }
    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        Log.d("Diag Frag", "This is called");
        dialog.cancel();
    }







    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        getActivity().getMenuInflater().inflate(R.menu.menu_ak, menu);
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        //TODO: Add 2 different dialgoues. One if the it is has been edited and one if it hasn't.

        int id = item.getItemId();

        if (id == R.id.action_save) {
            // handle confirmation button click here
            LinearLayout nGF = (LinearLayout) getActivity().findViewById(R.id.newGameFields);

            return true;
        } else if (id == android.R.id.home) {
            // handle close button click here
                if(mListener.isEdited(R.id.newGameFields)){
                    //confirmPopup();
                }else{
                    dismiss();
                }
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

   public void confirmPopup() {
        final DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which) {
                    case DialogInterface.BUTTON_POSITIVE:
                        //Erase button clicked
                        dismiss();
                        break;

                    case DialogInterface.BUTTON_NEGATIVE:
                        //Cancel button clicked
                        break;
                }
            }
        };
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage("Discard new game?")
                .setPositiveButton("ERASE", dialogClickListener)
                .setNegativeButton("CANCEL", dialogClickListener).show();

    }


/*
    public boolean isEdited(){
        LinearLayout nGF = (LinearLayout) getActivity().findViewById(R.id.newGameFields);
        for (int i = 0; i <= nGF.getChildCount(); i++){
            View v = nGF.getChildAt(i);
            if(v instanceof EditText){
                EditText ET = (EditText) getActivity().findViewById(nGF.getChildAt(i).getId()) ;
                if (ET.getText().length() != 0){
                    Toast.makeText(getActivity(), "Empty!" + ET.getText().toString(),
                            Toast.LENGTH_SHORT).show();
                    return true;
                }
            }
        }
        return false;
    }
*/

    /*@Override
    public boolean onBackPressed() {

        return true;
    }
*/

    /*   @Override
       public void onBackPressedCallback() {
           //this method is called by the DetailActivity,
           //when its onBackPressed() method is triggered
           Log.d("DetailActivity", "user pressed the back button");
       }*/
    @Override
    public void onAttach(Context context) {

        super.onAttach(context);

        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }


    @Override
    public void onDestroyView() {
        super.onDestroyView();
        FloatingActionButton fab = (FloatingActionButton) getActivity().findViewById(R.id.fab_game);
        fab.setVisibility(View.VISIBLE);

    }

    public interface OnFragmentInteractionListener {
        boolean isEdited(int Id);
        //void onBackPressed();
        void onFragmentInteraction(Uri uri);

    }
}

任何帮助深表感谢!如果您需要更多信息,请与我们联系。

编辑

好的,所以我终于整理了所有这些。在查看有关 Dialogs 和 Showing a Dialog Fullscreen 或作为 Embedded Fragment 的 android 文档时,据说使用此代码:
public void showDialog() {
FragmentManager fragmentManager = getSupportFragmentManager();
CustomDialogFragment newFragment = new CustomDialogFragment();

if (mIsLargeLayout) {
    // The device is using a large layout, so show the fragment as a dialog
    newFragment.show(fragmentManager, "dialog");
} else {
    // The device is smaller, so show the fragment fullscreen
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    // For a little polish, specify a transition animation
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    // To make it fullscreen, use the 'content' root view as the container
    // for the fragment, which is always the root view for the activity
    transaction.add(android.R.id.content, newFragment)
               .addToBackStack(null).commit();
}
 }

我误解了这里发生了什么。这个:
newFragment.show(fragmentManager, "dialog");

将 DialogFragment 显示为 Dialog。它调用了所有的 Dialog 方法,例如 onCreateDialog。但是这个:
// The device is smaller, so show the fragment fullscreen
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    // For a little polish, specify a transition animation
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    // To make it fullscreen, use the 'content' root view as the container
    // for the fragment, which is always the root view for the activity
    transaction.add(android.R.id.content, newFragment)
               .addToBackStack(null).commit();

将 DialogFragment 显示为 fragment 。因此,它不会调用 Dialog 方法,而是调用 Fragment 方法。

我最终只是把我的 DialogFragment 变成了一个 fragment 。

最佳答案

如果您想调用对话 fragment 在您的 fragment 中,不必替换和添加您的对话 fragment ,请调用您的对话 fragment 像这样,它的工作...

public void showDialog() {
     NewGame newGame = new NewGame();
     newGame.show(getChildFragmentManager(), "");
}

关于android - 对话框 fragment 问题 : onCreateDialog not called; can't get back key press,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38966423/

相关文章:

android - 如何构建 _just_ libwebcore.so 而不是整个 froyo 源

java - 无法从 fragment 类在 Textview 上设置文本

java - ProgressDialog 不适用于 fragment 的参数

android - 如何在 AsyncTask 的 DialogFragment 中显示 ProgressDialog

android - DialogFragment 给出 NullPointerException

android - DialogFragment - 在 onSaveInstanceState 之后无法执行此操作

安卓工作室 3.0 : Studio Profilers encountered an unexpected error

Android检测触摸内部 fragment

java - 带有注释参数的私有(private)方法的 Android java.lang.VerifyError

android - 打开推送通知时开始 fragment ?