First of all sorry if this post may seem a duplicate but I am very new to Android programming and posting this question only when I am still not able to get a satisfactory answer for use of getActivity.
Theoretically I understand the use of getActivity() from the several posts here but I am confused how it is working in my code.
I have a class MainActivity from which I am creating a dialog onclick of a checkbox.
I have another class TaxDialog where the dialog is implemented. On click of Yes/No buttons I am calling methods define in MainActivity class.
Below are the codes:
MainActivty
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity implements View.OnClickListener, View.OnFocusChangeListener {
// onCheck of checkbox showNoticeDialog is called
public void showNoticeDialog() {
// Create an instance of the dialog fragment and show it
Log.i("MyActivity", "Inside showNoticeDialog");
DialogFragment dialog = new TaxDialog();
Bundle args = new Bundle();
args.putString("title", "Test");
args.putString("message", "Test Message");
dialog.setArguments(args);
dialog.show(getSupportFragmentManager(), "dialog");
}
public void doPositiveClick(){
Log.i("MyActivity", "Inside +ve");
}
public void doNegativeClick(){
Log.i("MyActivity", "Inside -ve");
}
}
TaxDialog
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.util.Log;
public class TaxDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle args = getArguments();
String title = args.getString("title");
String message = args.getString("message");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(title);
builder.setMessage(message);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
Log.i("MyActivity", "Expected fault area.");
((MainActivity) getActivity()).doPositiveClick();
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((MainActivity) getActivity()).doNegativeClick();
}
});
builder.create();
return builder.create();
}
}
Here I want to understand how below line works
((MainActivity) getActivity()).doPositiveClick();
and also please make me aware of other ways of doing the same thing (something like MainActivity.this.getActivity() or something else).
Thanks a lot.
EDIT
Thanks everyone. Probably I framed the question incorrectly. My only doubt was how getActivity() returns the Activity reference. Now I understand.
Lets split it up:
getActivity() can be used in a Fragment for getting the parent Activity of the Fragment (basically the Activity that displayed the Fragment).
((MainActivity) getActivity()) additionally casts the result of getActivity() to MainActivity. Usually, you just know that getActivity() returns an object of type Activity, but using this cast, you tell the compiler that you are sure the object is a specific subclass of Activity, namely MainActivity. You need to do that in your case, because doPositiveClick() is only implemented in MainActivity, and not in Activity, so you have to assure the compiler the object is a MainActivity, and it will respond to the method doPositiveClick().
doPositiveClick() simply calls that method on the MainActivity object that is returned by getActivity().
The approach you are using is not the best way to accomplish what you want to do. Android have a good support for listeners, and for communicating with fragments. So, lets see how to communicate fragment->activity direction.
First, you need to make your MainActivity a listener from what happens on a dialog, so the best way to do this is implementing DialogInterface.OnClickListener on your MainActivity and override the onClick(DialogInterface dialog, int which) method, this method will be called from your fragmen. So until now everything is done in your MainActivity.
Now, in your fragment, you have to override the onAttach(Activity activity) method, this is the first method called when the fragment is built and this method comes with our parent Activity, inside this method initialize the listener of your fragment (your MainActivity).
Your fragment should look like this:
private DialogInterface.OnClickListener listener;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle args = getArguments();
String title = args.getString("title");
String message = args.getString("message");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(title);
builder.setMessage(message);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//Calling our MainActivity Listener with a positive answer
listener.onClick(getDialog(), 1);
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//Calling our MainActivity Listener with a negative answer
listener.onClick(getDialog(), 0);
}
});
builder.create();
return builder.create();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof DialogInterface.OnClickListener) {
listener = (DialogInterface.OnClickListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implemenet DialogInterface.OnClickListener");
}
}
And your main activity onClick() method should look like this:
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
//Do your negative thing
break;
case 1:
//Do your positive thing
break;
}
Toast.makeText(this, "You clicked "+ which, Toast.LENGTH_SHORT).show();
}
This is the best approach to do what you want to do, forget about "hard" cast your MainActivity class. Hope it helps you!
I believe you can jsut do
this.doPsitiveClick();
((MainActivity)getActivity()) is just getting the current active activity and casting that to be MainActivity..
When you use fragments it is only way to get context. As above, you are using DialogFragment and in OnClickListener there is need of context.
getActivity() is user-defined.
public final Activity getActivity() - Return the Activity this fragment is currently associated with.
For your code, in TaxDialog which is extending DialogFragment need a context to create AlertDialog with AlertDialog.Builder. So here, getActivity() as a parameter in AlertDialog.Builder is passing as context which tells to AlertDialog Fragment that by which activity it is attached to.
Related
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");
}
}
}
So I'm trying to create a dialog pop up. Here's the Dialog fragment I created in a separate DialogClass.Java file
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Toast;
public class DialogClass extends DialogFragment{
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder newAlertDialog = new AlertDialog.Builder(getActivity());
newAlertDialog.setTitle("Dialog");
newAlertDialog.setMessage("This is a dialog");
newAlertDialog.setPositiveButton(("OK"), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(), ("You clicked Ok"), Toast.LENGTH_SHORT).show();
}
});
newAlertDialog.setNegativeButton(("Cancel"), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getActivity(), ("You clicked Cancel"), Toast.LENGTH_SHORT).show();
}
});
return super.onCreateDialog(savedInstanceState);
}
}
Then when I use this class to create a method it brings us a blank dialog box when I run the app. This is how I use it:
Note: myButtinClick is a method that runs on the click of a button.
public void myButtonClick(View view) {
DialogFragment myFrag = new DialogClass();
myFrag.show(getFragmentManager(), "");
}
Please can anyone figure out what I am doing wrong?
See a screenshot of what the Dialog looks like via this link.
http://i.stack.imgur.com/xsQQj.png
You've only created the Dialog builder, but not the Dialog itself.
You should return newAlertDialog.create() and rename newAlertDialog to dialogBuilder or something like that.
I am new in Android Development. I want to open the Alert Dialog for Number Picker from Main Activity, and then take input from Alert Dialog and show it in the Main view.
I have written code from taking some references and its working correct. But i don't want to use " implements NumberPickerFragment.NoticeDialogListener" in main activity. Please help me, how can i return the value to main activity.
My code for Main Activity is:
package com.pinnacleappdesign.pinnacleappdesign;
import android.os.Bundle;
import android.app.Activity;
import android.app.DialogFragment;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements NumberPickerFragment.NoticeDialogListener{
int memoryIndex = 5;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
Button firstPaneButton = (Button)findViewById(R.id.first_pane_button1);
firstPaneButton.setOnClickListener(new OnClickListener() {
public void onClick(View v){
DialogFragment newFragment = new NumberPickerFragment();
Bundle args = new Bundle();
args.putInt("currentMemoryIndex", memoryIndex);
newFragment.setArguments(args);
newFragment.show(getFragmentManager(), "numberPicker");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void onDialogPositiveClick(int newMemoryIndex) {
this.memoryIndex = newMemoryIndex;
/** Getting the reference of the textview from the main layout */
TextView tv = (TextView) findViewById(R.id.tv_android);
/** Setting the selected android version in the textview */
tv.setText("Your Choice : " + this.memoryIndex);
}
}
My code for NumberPickerFragment.java is:
package com.pinnacleappdesign.pinnacleappdesign;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.NumberPicker;
import android.widget.Toast;
public class NumberPickerFragment extends DialogFragment{
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface NoticeDialogListener {
public void onDialogPositiveClick(int newMemoryIndex);
}
// Use this instance of the interface to deliver action events
NoticeDialogListener mListener;
// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
}
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle bundle = getArguments();
int currentMemoryIndex = bundle.getInt("currentMemoryIndex");
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
View DialogView = inflater.inflate(R.layout.number_picker, null);
final NumberPicker np = (NumberPicker)DialogView.findViewById(R.id.numberPicker1);
np.setMinValue(1);
np.setMaxValue(100);
np.setWrapSelectorWheel(false);
np.setValue(currentMemoryIndex);
builder.setTitle(R.string.dialog_title)
.setView(DialogView)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User confirmed the dialog
int position = np.getValue();
mListener.onDialogPositiveClick(position);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
What is wrong with your current method? That appears to be the method Android encourages developers to use as seen here: Communicating with Fragments
You can also do something like this within your NumberPickerFragment:
((MainActivity) getActivity()).yourMethod();
But IMO it is much cleaner and re-usable to use the defined Interface method.
I have to display many error messages and alert dialogues in my application.
I do not want to use Toast, I prefer to use AlertDialog.
Instead of creating a new alert dialog in every activity, how do I create and maintain one alert dialog and just change the error message string in it?
Whatever activity I am in, I must be able to access the AlertDialog instance to show and dismiss it.
How can I achieve this? Kindly give me some lead on this.
make one class and paste this function...(may be Utils.java)
public static void alertDialogShow(Context context, String message)
{
final AlertDialog alertDialog = new AlertDialog.Builder(context).create();
alertDialog.setMessage(message);
alertDialog.setButton("OK", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
alertDialog.dismiss();
}
});
alertDialog.show();
}
and call this by writing..
Utils.alertDialogShow(YourActivity.this,"Your Error Message")
You could always write a base class of Activity with your alertdialog call as a method and then for any of your activity classes instead of using extends Activity, use extends MyBaseActivity and then call the method whenever you need it by passing the string you want output.
I do something like this in a helper class
public static void AlertBox(final Activity activity, final String title, final String message)
{
AlertDialog.Builder alertbox = new AlertDialog.Builder(activity);
alertbox.setTitle(title);
alertbox.setCancelable(false);
alertbox.setMessage(message);
alertbox.setNeutralButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
activity.finish();
}
});
alertbox.show();
}
Try this:
/**
* Class for showing validation message
*/
package com.prj.utility;
import com.prj.R;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.prj.utility.System;
public class ValidationPopup {
Context mContext = null;
public ValidationPopup(Context mContext) {
// TODO Auto-generated constructor stub
this.mContext = mContext;
}
/**
*
* #param strTitle - title of dialog
* #param strMessage - message to be shown in dialog
* #param value - edit text object
*/
public void showValidationDialog(String strTitle, String strMessage,
final EditText value) {
final AlertDialog dlgValidationPopUp = new AlertDialog.Builder(mContext)
.create();
final LayoutInflater lyInflaterForDlgTitle = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout lLayoutCustTitle = (LinearLayout) lyInflaterForDlgTitle
.inflate(R.layout.custom_title, null);
TextView tvTitle = (TextView) lLayoutCustTitle
.findViewById(R.id.tvTitle);
tvTitle.setText(strTitle);
dlgValidationPopUp.setCustomTitle(lLayoutCustTitle);
if (strMessage == null || strMessage.trim().equalsIgnoreCase("")) {
//If there isn't any message in database for validation of the field, then DEFAULT_MESSAGE will be used
strMessage = Config.DEFAULT_MESSAGE;
}
dlgValidationPopUp.setMessage(strMessage);
dlgValidationPopUp.setCancelable(true);
dlgValidationPopUp.setButton("OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dlgValidationPopUp.dismiss();
//Edittext will be given focus if the field is edit text and it is not null
if (value != null)
value.requestFocus();
}
});
dlgValidationPopUp.show();
}
}
You can make this class's object anywhere in your application as,
ValidationPopup vPopup = new ValidationPopup(mContext);
And call method showValidationDialog according to your need
vPopup.showValidationDialog("Alert Msg","This is message content", objectOfEditText);//You can pass null as third arg if its not for edittext.
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.