Taylor Dawson Taylor Dawson - 3 months ago 79
Android Question

Dialog Fragment Issues: onCreateDialog not called; can't get back key press

What I have is a MainActivity that inserts my Game fragment into the fragment container:

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) {

}
}


The Game fragment creates a dialogue 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);
}
}

}


Within this dialogue fragment I want to intercept onBackPressed() to show a pop up when the back key is pressed. I have spent almost 2 days and I have tried many different suggestions from the good folks here on stack overflow, but to no avail. One of the seemingly best solutions presented here did not work for me because my onCreatDialog method is never called.

Here is the dialogue fragment code(as you can see I was testing to see which methods were actually being called):

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

}
}


Any help is much appreciated! Let me know if you need more information.

EDIT

Okay so I finally sorted through all of this. When was looking at the android documentation on Dialogs and under Showing a Dialog Fullscreen or as an Embedded Fragment is said to use this code:

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


I misunderstood what is going on here. This:

newFragment.show(fragmentManager, "dialog");


Shows the DialogFragment as a Dialog. Which calls all of the Dialog methods, such as, onCreateDialog. But this:

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


Shows the DialogFragment as a Fragment. Thus, it will not call the Dialog methods, but rather, the Fragment methods.

I ended up just turning my DialogFragment into a fragment.

Answer

If you want to call Dialog Fragment inside your fragment than dont have to replace and add your dialog fragment, call your Dialog fragment like this, its working...

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