Get value from DialogFragment [duplicate] - android

This question already has answers here:
Receive result from DialogFragment
(15 answers)
Closed 9 years ago.
I want the DialogFragment to return a value to me that was entered in editQuantity when dismissed.
But i am not getting any way to make it work. I can do this by passing the value through the intent but that destroys the progress of the current activity.
Is there any way other than passing through intent that will return me value?
package com.example.myprojectname;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.text.InputType;
import android.util.Log;
import android.widget.EditText;
public class QuantityDialogFragment extends DialogFragment implements OnClickListener {
private EditText editQuantity;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
editQuantity = new EditText(getActivity());
editQuantity.setInputType(InputType.TYPE_CLASS_NUMBER);
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.app_name)
.setMessage("Please Enter Quantity")
.setPositiveButton("OK", this)
.setNegativeButton("CANCEL", null)
.setView(editQuantity)
.create();
}
#Override
public void onClick(DialogInterface dialog, int position) {
String value = editQuantity.getText().toString();
Log.d("Quantity: ", value);
dialog.dismiss();
}
}

Assuming that you want to foward result to the calling Activity:) try this code snippet:
public class QuantityDialogFragment extends DialogFragment implements OnClickListener {
private EditText editQuantity;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
editQuantity = new EditText(getActivity());
editQuantity.setInputType(InputType.TYPE_CLASS_NUMBER);
return new AlertDialog.Builder(getActivity()).setTitle(R.string.app_name).setMessage("Please Enter Quantity")
.setPositiveButton("OK", this).setNegativeButton("CANCEL", null).setView(editQuantity).create();
}
#Override
public void onClick(DialogInterface dialog, int position) {
String value = editQuantity.getText().toString();
Log.d("Quantity: ", value);
MainActivity callingActivity = (MainActivity) getActivity();
callingActivity.onUserSelectValue(value);
dialog.dismiss();
}
}
and on Your activity add :
public class MainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
QuantityDialogFragment dialog = new QuantityDialogFragment();
dialog.show(getSupportFragmentManager(), "Dialog");
}
/**
* callback method from QuantityDialogFragment, returning the value of user
* input.
*
* #param selectedValue
*/
public void onUserSelectValue(String selectedValue) {
// TODO add your implementation.
}
}

Taking this idea a little further, I created a listener interface inside the dialog and implemented it in the main activity.
public interface OnDialogResultListener {
public abstract void onPositiveResult(String value);
public abstract void onNegativeResult();
}
public void setOnDialogResultListener(OnDialogResultListener listener) {
this.onDialogResultListener = listener;
}
Call onNegativeResult() inside an overriden onCancel(DialogInterface) and onPositiveResult(String) where you want your dialog to return the value.
Note: don't forget to dismiss() your dialog after calling onPositiveResult() or the dialog window will stay opened.
Then inside your main activity you can create a listener for the dialog, like so:
QuantityDialogFragment dialog = new QuantityDialogFragment();
dialog.setOnDialogResultListener(new QuantityDialogFragment.OnDialogResultListener() {
#Override
public void onPositiveResult(String value) {
//Do something...
}
#Override
public void onNegativeResult() {
//Do something...
}
});
This will make your dialog easier to reuse later.

Related

Targeting the wrong class when showing DialogFragment in Fragment

I have an AndroidStudio Java project using Fragments.
i want to show a dialogbox that asks to aquire permissions when needed.
So i did
Top of fragment
public class DinersFragment extends Fragment implements PermissionDialogFragment.PermissionDialogListener{
in class of fragment
public void showPermissionDialog() {
// Create an instance of the dialog fragment and show it
DialogFragment dialog = new PermissionDialogFragment();
dialog.show(((FragmentActivity) getActivity()).getSupportFragmentManager(), "PermissionDialogFragment");
}
#Override
public void onDialogPositiveClick(DialogFragment dialog) {
}
#Override
public void onDialogNegativeClick(DialogFragment dialog) {
}
but debug i got a cast error and had to add the same to mainActivity
Now things work, but when i click on the yes or no button, the onClicklistener in mainActivity is triggered, but instead i want the onClicklistener in the fragment to trigger.
How do i achieve this to not target mainActivity but the actual fragment?
the permission dialog:
package com.example.thermomaxtb;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
* Use the actory method to
* create an instance of this fragment.
*/
public class PermissionDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.req_perm)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// START THE GAME!
listener.onDialogPositiveClick(PermissionDialogFragment.this);
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
listener.onDialogNegativeClick(PermissionDialogFragment.this);
}
});
// Create the AlertDialog object and return it
return builder.create();
}
public interface PermissionDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
PermissionDialogListener listener;
#Override
public void onAttach(Context context) {
super.onAttach(context);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
listener = (PermissionDialogListener) context;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(e.toString()
+ " must implement NoticeDialogListener");
}
}
}

Android listener always null when attach in a DialogFragment

high school teachers here trying to teach how to implement a DialogFragment with listener attach with an interface to the fragment that show it. for some reason the listener is always null and while the dialog show, when I press the ok or Cancel button of the Dialog, the transfert to the implement method dont work, it stop a the line where I call the listener class (always null) in the alertDialog.Builder Here my code, thank
here my Fragment that call the dialogfragment
package net.ccl.monapp.ui;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import net.ccl.monapp.R;
public class AnimationFragment extends Fragment implements MonDialogFragment.MonDialogListener {
public AnimationFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_animation,container,false);
Button myButton = root.findViewById(R.id.bt_dialog);
final TextView tvTitre = root.findViewById(R.id.tv_titre);
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogFragment myDialog = new MonDialogFragment();
// Show Alert DialogFragment
myDialog.show(getFragmentManager(), "Dialog");
}
});
return root;
}
#Override
public void onDialogPositiveClick(DialogFragment dialog) {
TextView myTitre = getView().findViewById(R.id.tv_titre);
myTitre.setText("Mon nouveau titre");
dialog.dismiss();
}
#Override
public void onDialogNegativeClick(DialogFragment dialog) {
Toast.makeText(getActivity(),"Vous avez canceler l'action du dialog",Toast.LENGTH_SHORT);
}
}
here my DialogFragment
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
public class MonDialogFragment extends DialogFragment {
public MonDialogFragment() {
}
public interface MonDialogListener {
void onDialogPositiveClick(DialogFragment dialog);
void onDialogNegativeClick(DialogFragment dialog);
}
// Use this instance of the interface to deliver action events
public MonDialogListener listener;
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
// Instantiate the NoticeDialogListener so we can send events to the host
listener = (MonDialogListener) context;
} catch (ClassCastException e) {
}
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Mon interface dialog");
builder.setMessage("Ceci est un message qui explique que tu peux changer le titre du fragment animation en cliquant sur ok");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
listener.onDialogPositiveClick(MonDialogFragment.this);
}
});
builder .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
listener.onDialogNegativeClick(MonDialogFragment.this);
}
});
return builder.create();
}
}
and here my logcat
Process: net.ccl.monapp, PID: 13691
java.lang.NullPointerException: Attempt to invoke interface method 'void net.ccl.monapp.ui.MonDialogFragment$MonDialogListener.onDialogPositiveClick(androidx.fragment.app.DialogFragment)' on a null object reference
at net.ccl.monapp.ui.MonDialogFragment$1.onClick(MonDialogFragment.java:56)
at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Your onAttach() isn't actually doing anything since the Context you're attempting to cast is your Activity, not your AnimationFragment.
Instead of reaching up to get your listener, your AnimationFragment should set the listener on the Dialog by overriding onAttachFragment().
First, you need to make sure that your MonDialogFragment is a child fragment of your AnimationFragment by changing your show() to use getChildFragmentManager():
myDialog.show(getChildFragmentManager(), "Dialog");
Then, override onAttachFragment() in your AnimationFragment:
#Override
public void onAttachFragment(Fragment fragment) {
super.onAttachFragment(fragment);
if (fragment instanceof MonDialogFragment) {
((MonDialogFragment) fragment).listener = this;
}
}
You can then remove onAttach() from MonDialogFragment entirely.

How to add Back Button from an Activity to a Fragment

I'm using a fragment because I used a nav drawer menu. After I click "Category" menu it will take me to "Category" fragment and in that fragment, I have added a floating action bar that will take you to "Add category" activity.
Since fragments can't be viewed in AndroidManifest.xml file, I can't make a fragment as a parent. What I want is to add a "Back Button" from "Add category" activity, display a toast message (If sure to leave without saving changes..etc) and will go back to "Category" fragment.
I have tried using "onBackPressed()" and "getSuppoerActionBar()" that will show a toast but when running the app, the toast message will just show up in a few seconds and will go back to "Category" fragment.
Please help. Thanks!
Here is my code.
CategoriesFragment.java
package com.example.devcash;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
*/
public class CategoriesFragment extends Fragment {
public CategoriesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_categories, container, false);
//add floating action button
FloatingActionButton categories_fab = view.findViewById(R.id.addcategories_fab);
categories_fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// when add fab is pressed, go to add product activity
Intent addprod = new Intent(getActivity(), AddCategoryActivity.class);
startActivity(addprod);
}
});
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("Categories");
}
}
AddCategoryActivity.java
package com.example.devcash;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
public class AddCategoryActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_category);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Unsaved changes");
builder.setMessage("Are you sure you want to leave without saving changes?");
builder.setPositiveButton("LEAVE", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
AddCategoryActivity.super.onBackPressed();
}
});
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.show();
super.onBackPressed();
}
}
You need to remove below code from onBackPressed() as it is calling super class method and eventually destroying activity.
super.onBackPressed();
To handle toolbar back add following code
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// todo: goto back activity from here
onBackPressed();
default:
return super.onOptionsItemSelected(item);
}
}
Your AddCategoryActivity should be like this
public class AddCategoryActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_category);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public void onBackPressed() {
quitActivity();
}
private void quitActivity() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Unsaved changes");
builder.setMessage("Are you sure you want to leave without saving changes?");
builder.setPositiveButton("LEAVE", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.show();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
quitActivity();
return true;
} else
return super.onOptionsItemSelected(item);
}
}
you can use EventBus.
class Activity{
fun backToFragment(){
EventBus.postEvent(BackToFragmentEvent())
}
}
class HomeActivity{
EventBus.register{
fragmentmanager.replace(CategoriesFragment)
}
}

Showing a DialogFragment object from an on click inside a button listener

I was just trying showing a DialogFragment object from an on click inside a button listener.
Here is the code of the activity that should start the Dialog:
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
Button button1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addListenerToButton1();
}
private void addListenerToButton1(){
final Context context = this;
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
DP ciao = new DP();
ciao.show(this,"MyDP");
}
});
}
}
And here's the code of the Dialog:
public class DP extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Prova")
.setPositiveButton("POS", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
})
.setNegativeButton("NEG", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
return builder.create();
}
}
Errors are:
The method show(FragmentManager, String) in the type DialogFragment is not applicable for the arguments (MainActivity, String)
The method show(FragmentManager, String) in the type DialogFragment is not applicable for the arguments (new View.OnClickListener(){}, String)
Any advice?
Show DialogFragment from Activity by passing FragmentManager instance for interacting with fragments associated with current activity as instead of by passing Activity or Button Context:
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
DialogFragment ciao = DP.newInstance();
ciao.show(MainActivity.this.getFragmentManager(),"MyDP");
}
});
and you will also need to add following newInstance() method in DP DialogFragment which return you DialogFragment instance :
public static DP newInstance() {
DP frag = new DP();
return frag;
}
Try this method of passing the correct context into your DialogFragment
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
DP ciao = new DP();
ciao.show(view.getContext(),"MyDP");
}
});
In your original code, when calling
'ciao.show(this,"MyDP");'
the this refers to its parent class which is OnClickListener.
When assigning a click listener and overriding the onClick, you get passed the view and an argument which you can use to access information from, including the context.
Extend your fragment (DP) from the android.app.DialogFragment
you can access FragmentManager from within Activity by getFragmentManager()
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
DP ciao = new DP();
ciao.show(getFragmentManager(),"MyDP");
}
});
Hopefully this works :)

ListFragment as DialogFragment

Is it possible to show ListFragment as Dialog? Or there's no way and I should implement my own ListView, empty TextView and indeterminate ProgressBar inside DialogFragment myself?
Another Option:
Build Dialog Fragment:
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
public class ListDialogFragment extends DialogFragment {
private OnListDialogItemSelect listener;
private String title;
private String[] list;
public ListDialogFragment(OnListDialogItemSelect listener, String[] list, String title) {
this.listener=listener;
this.list=list;
this.title=title;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(title)
.setCancelable(false)
.setItems(list, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
listener.onListItemSelected(list[item]);
getDialog().dismiss();
ListDialogFragment.this.dismiss();
}
}).create();
}
public interface OnListDialogItemSelect{
public void onListItemSelected(String selection);
}
}
On Your Fragment Activity like this:
public class YourActivity extends FragmentActivity implements OnListDialogItemSelect{
private void showCountryFragment(){
FragmentManager fm = getSupportFragmentManager();
ListDialogFragment newFragment = new ListDialogFragment(this,getCountries(),"Country:");
newFragment.show(fm, "country_picker");
}
#Override
public void onListItemSelected(String selection) {
_bt_country.setText(selection);
}
}
I am not very sure whether it works with ListFragment or not but we can show an activity as Dialog by applying a theme to activity in manifest file as:
<activity android:theme="#android:style/Theme.Dialog" />
Please try with your ListFragment, and let me know if it works.
Thank you.

Categories

Resources