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.
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");
}
}
}
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.
I created a ListDialog extending a DialogFragment class and I have a problem with understanding of this code in the DijalogX class
((MainActivity)getActivity()).setTextField(selectedItem);
I understand that with this code above I put selected String variable to the setTextField method as an argument and after that this variable is showed in TextView on MainActivity class.
My questions:
Why I need a cast from getActivity() to the MainActivity and how I get access from DijalogX(fragment) to the method setTextField in MainActivity? Please explain a little about this process.
I also tried instead of ((MainActivity)getActivity()).setTextField(selectedItem)
use an Interface and everything works nice and I got the same resoult but I am wondering what is better solution here Interface or ((MainActivity)getActivity()).setTextField(selectedItem)?
MainActivity
package com.example.dezox.dijaloglist;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity{
private Button btnStartDialog;
private TextView tvSelectedOption;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initWidgets();
setupListener();
}
private void initWidgets() {
btnStartDialog = findViewById(R.id.btnDialog);
tvSelectedOption = findViewById(R.id.tvselectedOption);
}
private void setupListener() {
btnStartDialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DijalogX dijalogX = new DijalogX();
dijalogX.show(getSupportFragmentManager(), "dx");
tvSelectedOption.setText("");
}
});
}
public void setTextField(String odabrano){
tvSelectedOption.setText(odabrano);
}
public String getTextField(){
return tvSelectedOption.getText().toString();
}
}
DijalogX
package com.example.dezox.dijaloglist;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
public class DijalogX extends DialogFragment {
private String[] languageList;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initListResource();
}
private void initListResource() {
languageList = getResources().getStringArray(R.array.language_list);
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),
android.R.style.Theme_Material_Dialog_Alert)
.setTitle("Select Language: ")
.setItems(languageList, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String selectedItem = languageList[which];
//THIS PART OF THE CODE I DONT UNDERSTAND:
((MainActivity)getActivity()).setTextField(selectedItem);
}
});
return builder.create();
}
}
You have declared a method in MainActivity called setTextField. If you called
Activity a = getActivity();
you would not be able to call your custom method (it is on your derived class, not the base Activity class).
a.setTextField(selectedIte); // WON'T WORK - NO SUCH METHOD
If instead you call
MainActivity ma = (MainActivity)getActivity();
it is now cast as your derived class and you can then call
ma.setTextField(selectedItem);
Doing it in two lines like this is the same as calling the one-liner in your code
((MainActivity)getActivity()).setTextField(selectedItem);
As far as casting vs. an interface, an interface is a bit more flexible of an approach. If you tried to use this fragment in a different activity (not MainActivity) the casting approach would fail. If you are only ever going to use the fragment in this Activity then either would work.
I want to update listview in fragment from main activity after selecting item from dialog.
I am using FragmentPagerAdapter in this Activity
My Dialog method
private void showDialog(String routeName) {
MyTTCDB db = new MyTTCDB(this);
List<String> directions = db.getDirectionByRoute(routeName);
AlertDialog.Builder builderSingle = new AlertDialog.Builder(this);
builderSingle.setTitle("Direction");
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
this, android.R.layout.select_dialog_singlechoice);
for (String string : directions) {
arrayAdapter.add(string);
}
builderSingle.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builderSingle.setAdapter(arrayAdapter,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String side = arrayAdapter.getItem(which);
FragmentStops fragment = (FragmentStops) mSectionsPagerAdapter
.getItem(1);
fragment.refresh(side);
}
});
builderSingle.show();
}
My Fragment
import java.util.List;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.anilvasani.myttc.StopsActivity.Interface_FragmentStops;
import com.anilvasani.myttc.adapter.AdapterStops;
import com.anilvasani.myttc.data.MyTTCDB;
import com.anilvasani.myttc.models.Stop;
public class FragmentStops extends Fragment {
View view;
AdapterStops myAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragement_stops, container, false);
return view;
}
public void refresh(String side) {
// TODO Auto-generated method stub
String routeName = getActivity().getIntent()
.getStringExtra("routeName").toString();
ListView listStops = (ListView) view.findViewById(R.id.dialog_listView);
// EditText txtSearch=(EditText)
// view.findViewById(R.id.dialog_txtSearch);
MyTTCDB db = new MyTTCDB(getActivity());
List<Stop> allStops = db.getAllStopsByRouteAndSide(routeName, side);
myAdapter = new AdapterStops(getActivity(), allStops);
listStops.setAdapter(myAdapter);
}
}
I am getting errors like...
12-14 23:43:02.696: E/MessageQueue-JNI(7577): java.lang.NullPointerException
12-14 23:43:02.696: E/MessageQueue-JNI(7577): at com.anilvasani.myttc.FragmentStops.refresh(FragmentStops.java:34)
12-14 23:43:02.696: E/MessageQueue-JNI(7577): at com.anilvasani.myttc.StopsActivity$3.onClick(StopsActivity.java:120)
12-14 23:43:02.696: E/MessageQueue-JNI(7577): at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:941)
So please help me, How to call method of Fragment from Activity based on user's input.
It seems your error is coming from the line:
String routeName = getActivity().getIntent()
.getStringExtra("routeName").toString();
Make sure of the following things:
That when you started the activity that you calling refresh method (the activity that the dialog is attached to) that you start the activity in an intent since getIntent() is trying to return that intent.
Next make sure that there is a String named "routeName" and that that String is not null.
I hope this helps
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.