In main activity is a dashboard and have tablayout & viewpager, and have icon menu to click and working well, but the problem is when showing dialog inside fragment. If showing dialog not in fragment (normal activity) the code working well, but my code not working well inside fragment. I was tried many suggestion from this forum but still don't how to fix this issue.
Here's the code for my Fragment:
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
public class ScanTabFragment extends Fragment implements View.OnClickListener, ProjectDialogActivity.DialogListener{
private CardView cardViewCreateProjectBatch;
private View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_scan_tab, container, false);
cardViewCreateProjectBatch = view.findViewById(R.id.cardViewCreateProjectBatch);
cardViewCreateProjectBatch.setOnClickListener(this);
return view;
}
#Override
public void onClick(View view) {
Intent i;
switch (view.getId()) {
case R.id.cardViewCreateProjectBatch:
newProjectDialog();
break;
}
}
private void newProjectDialog() {
String projectNameAuto;
projectNameAuto = "PJ-Batch-" + android.text.format.DateFormat.format("yyyy.MM.dd.kk.mm.ss", new java.util.Date());
FragmentManager fm = getSupportFragmentManager(); //this not working in fragment but working in normal activity (not fragment) and i have tried other code like this below but app crashed and dialog not show
//FragmentManager fm = getActivity().getSupportFragmentManager();
//FragmentManager fm = getActivity().getSupportFragmentManager();
//FragmentManager fm = this.getParentFragment().getChildFragmentManager();
//FragmentManager fm = this.getParentFragment().getFragmentManager();
//FragmentManager fm = this.getParentFragment().getFragmentManager().beginTransaction();
//FragmentManager fm = this.getChildFragmentManager();
//FragmentManager fm = getFragmentManager();
//FragmentManager fm = getParentFragment();
ProjectDialogActivity alertDialog = ProjectDialogActivity.newInstance("Create New Batch Project", projectNameAuto, "");
alertDialog.setCancelable(false);
alertDialog.show(fm, "fragment_alert");
ProjectDialogActivity alertDialog = ProjectDialogActivity.newInstance("Create New Batch Project", projectNameAuto, "");
alertDialog.setCancelable(false);
alertDialog.show(fm, "fragment_alert");
}
public long insertProject1(String project_name, String created_date, Integer status, String notes) {
mySQLiteAdapterBatch = new DatabaseHelperBatch(view.getContext());
SQLiteDatabase db = mySQLiteAdapterBatch.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("project_name", project_name);
contentValues.put("created_date", created_date);
contentValues.put("status", status);
contentValues.put("notes", notes);
return db.insert("project1", null, contentValues);
}
public long insertProject2(String project_name, String created_date, Integer status, String notes) {
mySQLiteAdapterBatch = new DatabaseHelperBatch(view.getContext());
SQLiteDatabase db = mySQLiteAdapterBatch.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("project_name", project_name);
contentValues.put("created_date", created_date);
contentValues.put("status", status);
contentValues.put("notes", notes);
return db.insert("project2", null, contentValues);
}
#Override
public void applyTexts(String project_name, String created_date, Integer status, String notes) {
if (ProjectDialogActivity.radioButtonProject1.isChecked() == true) {
insertProject1(project_name, created_date, status, notes);
Toast.makeText(view.getContext(), "New Batch project1 has been created", Toast.LENGTH_LONG).show();
;
}
if (ProjectDialogActivity.radioButtonProject2.isChecked() == true) {
insertProject2(project_name, created_date, status, notes);
Toast.makeText(view.getContext(), "New Batch project2 has been created", Toast.LENGTH_LONG).show();
}
}
}
Here's the code for the Dialog Fragment:
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDialogFragment;
public class ProjectDialogActivity extends AppCompatDialogFragment {
//Variables
private String projectName;
private String projectCreated;
private String projectNotes;
private Integer projectStatus;
private TextView textViewProjectName;
private TextView textViewNotes;
public static RadioButton radioButtonProject1;
public static RadioButton radioButtonProject2;
public static ProjectDialogActivity newInstance(String title, String getProjectName, String getNotes) {
ProjectDialogActivity frag = new ProjectDialogActivity();
Bundle args = new Bundle();
args.putString("title", title);
args.putString("inputProjectName", getProjectName);
args.putString("inputNotes", getNotes);
frag.setArguments(args);
return frag;
}
private ProjectDialogActivity.DialogListener listener;
//private EditText editTextRack;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
String title = getArguments().getString("title");
String inputProjectName = getArguments().getString("inputProjectName");
String inputNotes = getArguments().getString("inputNotes");
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
final View view = inflater.inflate(R.layout.activity_projectdialog, null);
radioButtonProject1 = view.findViewById(R.id.radioButtonScan1);
radioButtonProject2 = view.findViewById(R.id.radioButtonScan2);
textViewProjectName = view.findViewById(R.id.editTextProjectName);
textViewNotes = view.findViewById(R.id.editTextNotes);
textViewProjectName.setSingleLine(true);
textViewNotes.setSingleLine(true);
textViewProjectName.setText(inputProjectName);
textViewNotes.setText(inputNotes);
projectName = textViewProjectName.getText().toString();
builder.setView(view)
.setTitle(title)
//.setView(input)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialoginterface, int i) {
dialoginterface.cancel();
}
})
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//String Rack = editTextRack.getText().toString();
//String projectName = textProject.getText().toString();
////listener.applyTexts(textProject.getText().toString(), itemfrloc, itemtoloc, textNotes.getText().toString());
//String answer="OK";
//listener.applyOK_insert(answer);
}
});
return builder.create();
}
#Override
public void onResume() {
super.onResume();
final AlertDialog d = (AlertDialog) getDialog();
if (d != null) {
Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
projectName = textViewProjectName.getText().toString();
projectCreated = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
projectStatus = 0;
projectNotes = textViewNotes.getText().toString();
Boolean wantToCloseDialog;
//Do stuff, possibly set wantToCloseDialog to true then...
if (projectName.isEmpty()) {
Toast.makeText(getContext(), "Cannot left blank, Please input your project name", Toast.LENGTH_LONG).show();
textViewProjectName.requestFocus();
wantToCloseDialog = false;
} else {
wantToCloseDialog = true;
}
if (wantToCloseDialog == true) {
listener.applyTexts(projectName, projectCreated, projectStatus, projectNotes);
d.dismiss();
}
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
}
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
listener = (ProjectDialogActivity.DialogListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement DialogListener");
}
}
public interface DialogListener {
// This is called when the dialog is completed and the results have been passed
void applyTexts(String project_name, String created_date, Integer status, String Notes);
}
}
please try getParentFragmentManager() or getFragmentManager()
The App crashed/stopped not because Fragment Manager, So if write:
FragmentManager fm = getActivity().getSupportFragmentManager(); \\OK or Use FragmentManager fm = getFragmentManager();
then below that, write:
ProjectDialogActivity alertDialog = ProjectDialogActivity.newInstance("Create New Batch Project", projectNameAuto, "");
alertDialog.setTargetFragment(ScanTabFragment.this, 0); \\Your Tab Fragment Name
alertDialog.setCancelable(false);
alertDialog.show(fm, null);
and in other class: public class ProjectDialogActivity extends AppCompatDialogFragment, not need to write listener onAttach or onAttachFragment but write listener in this one:
#Override
public void onResume() {
super.onResume();
final AlertDialog d = (AlertDialog) getDialog();
if (d != null) {
Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
projectName = textViewProjectName.getText().toString();
projectCreated = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
projectStatus = 0;
projectNotes = textViewNotes.getText().toString();
Boolean wantToCloseDialog;
//Do stuff, possibly set wantToCloseDialog to true then...
if (projectName.isEmpty()) {
Toast.makeText(getContext(), "Cannot left blank, Please input your project name", Toast.LENGTH_LONG).show();
textViewProjectName.requestFocus();
wantToCloseDialog = false;
} else {
wantToCloseDialog = true;
}
if (wantToCloseDialog == true) {
\\write listener in here
DialogListener listener = (DialogListener) getTargetFragment();
listener.applyTexts(projectName, projectCreated, projectStatus, projectNotes);
d.dismiss();
}
//else dialog stays open. Make sure you have an obvious way to close the dialog especially if you set cancellable to false.
}
});
}
}
public interface DialogListener {
// This is called when the dialog is completed and the results have been passed
void applyTexts(String project_name, String created_date, Integer status, String Notes);
}
the first time i thought of this problem because of Fragment Manager, don't know the right code how to calling fragment manager inside fragment, the other users also giving a some clue how to called the right way for fragment manager but still error because the listener is null that's why the error happened.
Related
I am trying to send some data from a DialogFragment to a TextView from a Fragment.
After inserting the data in the available input and pressing SAVE, the app crashes.
I assume there is something wrong with the IncomeDialogListener.
I would appreciate some hints where I did wrong.
This is the Dialog Class
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_incomedialog, null);
builder.setView(view)
.setTitle("Add Income")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String Amount = enter_income_amount.getText().toString();
String Note = enter_income_note.getText().toString();
String Date = enter_income_date.getText().toString();
incomeDialogListener.addDetails(Amount, Note, Date);
}
});
enter_income_amount = view.findViewById(R.id.enter_income_amount);
enter_income_note = view.findViewById(R.id.enter_income_note);
enter_income_date = view.findViewById(R.id.enter_income_date);
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
incomeDialogListener = (IncomeDialogListener) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "Must Implement IncomeDialogListener");
}
}
public interface IncomeDialogListener {
void addDetails(String Amount, String Note, String Date);
}
This is the Fragment to which I want to send the data
public class IncomeFragment extends Fragment implements
IncomeDialog.IncomeDialogListener {
DatabaseHelper myDB;
Button btn_add_income;
TextView display_income;
public IncomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_placeholder2 , container, false);
display_income = (TextView) v.findViewById(R.id.display_income);
btn_add_income = (Button) v.findViewById(R.id.btn_add_income);
myDB = new DatabaseHelper(getActivity());
btn_add_income.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openIncomeDialog();
}
});
return v;
}
private void openIncomeDialog() {
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
IncomeDialog incomeDialog = new IncomeDialog();
incomeDialog.show(fragmentTransaction, "income dialog" );
}
#Override
public void addDetails(String Amount, String Note, String Date) {
display_income.setText(Amount);
}
}
Here is my solution for you:
IncomeFragment.java
public static final int INCOME_DIALOG_FRAGMENT = 1; // Add this line
private void openIncomeDialog() {
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
IncomeDialog incomeDialog = new IncomeDialog();
incomeDialog.setTargetFragment(IncomeFragment.this, INCOME_DIALOG_FRAGMENT); // Add this line
incomeDialog.show(fragmentTransaction, "income dialog");
}
IncomeDialog.java
#Override
public void onClick(DialogInterface dialog, int which) {
String Amount = enter_income_amount.getText().toString();
String Note = enter_income_note.getText().toString();
String Date = enter_income_date.getText().toString();
IncomeDialogListener listener = (IncomeDialogListener) getTargetFragment();
listener.addDetails(Amount, Note, Date);
}
Update: There is no magic behind, when you open dialog from fragment, you passed itself to dialog by calling setTargetFragment. Then in the dialog you can refer to the fragment that opened it by calling getTargetFragment. Actually there are 2 solutions you can use.
IncomeFragment incomeFragment = (IncomeFragment) getTargetFragment();
incomeFragment.addDetails(Amount, Note, Date);
or
IncomeDialogListener listerner = (IncomeDialogListener) getTargetFragment();
listerner.addDetails(Amount, Note, Date);
I prefer to use the second one because the dialog don't need to know about specific fragment that opened it. This makes the dialog is usable. Imagine a situation, three days later, you would like to open the dialog from another fragment, in that case you don't need to modify the dialog again, just let the another fragment implements IncomeDialogListener. If you use the first one, you must go to the dialog and modify it to make sure it works for the another fragment.
Im having some troubles with retrieving a bundle value in my onClickListener method or any other method in general. I have comments besides the code for better clarification. So what happens is i get a value from activityA put it in a bundle and pass the values to my fragment. I get the value from the bundle and set in my setter method the value i get from the bundle is not null if i toast the value it shows the correct one on the screen. Below im posting my whole onCreateMethod, im having this issue for the past couple of days so any help is greatly appreciated. What i think happens is that when i try to get the value from the bundle in my onClickListener method it resets itself to 0 for some reason.
Thanks for your help in advance
My onCreateView method in fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_todo_list, container, false);
FloatingActionButton floatingActionButton = view.findViewById(R.id.fab);
recyclerView = (RecyclerView) view.findViewById(R.id.list);
bundle = this.getArguments();
if(bundle != null) {
fk_id = bundle.getLong("fk");
setId_2(fk_id); // i try to set the value
Toast.makeText(getContext(), "iz fragmenta" + getId_2(), Toast.LENGTH_SHORT).show(); // this prints the correct value
floatingActionButton.setOnClickListener(new View.OnClickListener() { //this button stops working if in the if statement
#Override
public void onClick(View v) {
LayoutInflater li = LayoutInflater.from(getActivity());
View popupView = li.inflate(R.layout.popup_layout, null);
final EditText editText = popupView.findViewById(R.id.userInput);
AlertDialog.Builder adb = new AlertDialog.Builder(getContext());
adb.setView(popupView);
adb.setCancelable(false)
.setPositiveButton("Dodaj", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String naziv = editText.getText().toString();
Aktivnost_ ak = new Aktivnost_(naziv, "15-jun", fk_id, "kajetan", "todo");
dodajAktivnost(ak);
array.add(ak);
Toast.makeText(getContext(), "dodano" + getId_2(), Toast.LENGTH_LONG).show();
}
})
.setNegativeButton("Prekliči", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
Toast.makeText(getContext(), "Preklical sem", Toast.LENGTH_LONG).show();
}
});
AlertDialog alertDialog = adb.create();
alertDialog.setCancelable(true);
alertDialog.show();
}
});
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(), LinearLayoutManager.VERTICAL));
mmAdapter = new ToDoRecyclerViewAdapter(listAktivnosti(getId_2()), getContext(), mListener);
mmAdapter.setOnItemClickListner(new ToDoRecyclerViewAdapter.onItemClickListner() {
#Override
public void onClick(long i) {
Intent intent = new Intent(getActivity(), PodrobnostiActivity.class);
intent.putExtra("key_id", i);
startActivity(intent);
Toast.makeText(getContext(), "" + i, Toast.LENGTH_SHORT).show();
}
});
mmAdapter.setOnLongClick(new ToDoRecyclerViewAdapter.OnLongClickListener_() {
#Override
public void onLongClick(long i, String item) {
if (item.equals("doing")) {
boolean update_1 = db.updateList(i, item);
if (update_1) {
//NAREDI SE LEPE ANIMACIJE
android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(TodoFragment.this).attach(TodoFragment.this).commit();
Toast.makeText(getContext(), "Dodano v bazo.!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "Prislo je do napake!", Toast.LENGTH_SHORT).show();
}
}
}
});
recyclerView.setAdapter(mmAdapter);
}
return view;
}
EDITED
private long fk_id;
public long getId_2() {
return fk_id;
}
public void setId_2(long fk_id) {
this.fk_id = fk_id;
}
EDIT_2
This part is in my activities onCreate
Intent intent = getIntent();
long id = intent.getLongExtra("intVariableName",0);
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, TodoFragment.newInstance(id), "a");
fragmentTransaction.commit();
And i made a newInstance method in my fragment.
public static TodoFragment newInstance(long id) {
TodoFragment fragment = new TodoFragment();
Bundle b = new Bundle();
b.putLong("fk",id);
fragment.setArguments(b);
return fragment;
}
Try the following:
Since you already have access to the data within your variable fk_id in your Fragment, you can mark it as final, and pass it to your Toast:
Toast.makeText(getContext(), "dodano" + fk_id, Toast.LENGTH_LONG).show();
OR
Try marking your getId_2 and setId_2 with synchronized as well as your onCreateView(), this way, the data shared between the two methods will be synchronized.
I have a bare project, just the webview and implementation for alert and prompt... each works ok by themselves but the UI stops responding if prompt is immediately inside alert: alert(prompt("hi", "test"));
Any idea on what could be causing it? below please find the relevant parts of the code:
public class MainActivity extends AppCompatActivity implements JSDialogFragment.JSDialogResultListener{
private WebView m_webView;
public void OnJsDialogFragmentPositive(Bundle args, Object cb) {
Log.d("JSDialogFragment", "OnJsDialogFragmentPositive");
jsDialogType dType = (jsDialogType)args.getSerializable("dType");
if(null != dType && null != cb) {
if(JS_DIALOG_TYPE_ALERT == dType) {
((JsResult) cb).confirm();
} else if(JS_DIALOG_TYPE_PROMPT == dType) {
String value = args.getString("value");
((JsPromptResult) cb).confirm(null != value ? value : "");
}
}
}
public void OnJsDialogFragmentNegative(Bundle args, Object cb) {
Log.d("JSDialogFragment", "OnJsDialogFragmentNegative");
}
m_webView = (WebView) findViewById(R.id.m_webView);
m_webView.getSettings().setJavaScriptEnabled(true);
m_webView.setWebChromeClient(new WebChromeClient() {
// shared set up transaction code
FragmentTransaction showJsTransactionInit() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
android.app.Fragment prev = getFragmentManager().findFragmentByTag("mytag");
if (prev != null) ft.remove(prev);
ft.addToBackStack(null);
return ft;
}
#Override
public boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) {
FragmentTransaction ft = showJsTransactionInit();
DialogFragment frag = JSDialogFragment.newInstanceAlert(message, result);
frag.show(ft, "mytag");
return true; // handled
}
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final android.webkit.JsPromptResult result) {
FragmentTransaction ft = showJsTransactionInit();
DialogFragment frag = JSDialogFragment.newInstancePrompt(message, result);
frag.show(ft, "mytag");
return true; // handled
}
});
and the JSDialogFragment implementation that handles dialog:
public class JSDialogFragment extends DialogFragment {
interface JSDialogResultListener {
void OnJsDialogFragmentPositive(Bundle obj, Object cb);
void OnJsDialogFragmentNegative(Bundle obj, Object cb);
}
private Object mCB;
public void setCallBack(Object cb) {
mCB = cb;
}
// to init alert incase it may differ from how we show prompt
public static DialogFragment newInstanceAlert(String message, Object cb) {
JSDialogFragment frag = new JSDialogFragment();
frag.setCallBack(cb);
Bundle args = new Bundle();
args.putString("caption", message);
args.putSerializable("dType", jsDialogType.JS_DIALOG_TYPE_ALERT); (JS_DIALOG_TYPE_ALERT is just an enum to distinguish between the types)
frag.setArguments(args);
return frag;
}
// to init prompt incase it may differ from how we show alert
public static DialogFragment newInstancePrompt(String message, Object cb) {
JSDialogFragment frag = new JSDialogFragment();
frag.setCallBack(cb);
Bundle args = new Bundle();
args.putString("caption", message);
args.putSerializable("dType", jsDialogType.JS_DIALOG_TYPE_PROMPT);
frag.setArguments(args);
return frag;
}
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof JSDialogResultListener)) {
throw new ClassCastException(activity.toString() + " must implement JSDialogResultListener");
}
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle args = getArguments();
String caption = args.getString("caption");
jsDialogType jsDType = (jsDialogType)args.getSerializable("dType");
if(null==jsDType) jsDType = jsDialogType.JS_DIALOG_TYPE_ALERT;
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) //, R.style.jsDialogsTheme)
.setTitle(R.string.jsDialogTitle)
.setMessage(caption);
switch(jsDType) {
case JS_DIALOG_TYPE_ALERT:
builder.setPositiveButton(android.R.string.ok , new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((JSDialogResultListener) getActivity()).OnJsDialogFragmentPositive(args, mCB);
dialog.dismiss();
}
});
break;
case JS_DIALOG_TYPE_PROMPT:
builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
args.putString("value", "waaaawwweeeee3");
((JSDialogResultListener) getActivity()).OnJsDialogFragmentPositive(args, mCB);
dialog.dismiss();
}
}).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((JSDialogResultListener) getActivity()).OnJsDialogFragmentNegative(args, mCB);
dialog.dismiss();
}
});
break;
}
return builder.create();
}
}
Any thoughts, suggestions?
So i have a slight problem. I have a feeling its something simple that i must be overlooking. In my second fragment im writing to sharedpreferences a certain number of keys and applying() afterwords. After i have finished writing my data to the sharedpreferences, i replace the current fragment(fragment#2), with the home fragment(fragment#1). Upon loading this fragment i call readPreferences(), which should read the data stored ealier and write the data to the various textviews i have on the home fragment. This does not happen. Im unsure at this time if its due to a write error or a read error. your help is as always, appreciated. Thanks.
Second Fragment
package lucaclock.moticlock;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
public class secondFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private TimePicker timePicker;
private int hour = 0;
private int min = 0;
private String mParam1;
private String mParam2;
public SharedPreferences sharedPreferences;
public SharedPreferences.Editor prefEditor;
public static final String alarmPreferences = "alarmPreferences";
public static final String alarmTimeKey = "alarmTimeKey";
public static final String alarmNameKey = "alarmNameKey";
public static final String alarmOccuranceKey = "alarmOccuranceKey";
public static final String alarmVolumeKey = "alarmVolumeKey";
public static final String alarmSnoozeKey = "alarmSnoozeKey";
public static final String alarmVisibleKey = "alarmVisibleKey";
public int snoozeTime;
public secondFragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static secondFragment newInstance(String param1, String param2) {
secondFragment fragment = new secondFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_second, container, false);
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
final Button btnOK = (Button) view.findViewById(R.id.btnOK);
final TimePicker tp = (TimePicker) view.findViewById(R.id.timePicker);
//Stage 1 Components
final EditText edAlarmName = (EditText) view.findViewById(R.id.edAlarmName);
edAlarmName.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View view, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
edAlarmName.setText("");
}
return false;
}
});
final EditText edAlarmTime = (EditText) view.findViewById(R.id.edTime);
final EditText edOccurance = (EditText) view.findViewById(R.id.edOccurance);
edOccurance.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
dialogOccurance(view);
return true;
}
return false;
}
});
final SeekBar seekVolume = (SeekBar) view.findViewById(R.id.seekVolume);
seekVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
TextView tv = (TextView) view.findViewById(R.id.txtVolume);
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
tv.setText("How Loud?");
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
// TODO Auto-generated method stub
tv.setText("Volume: " + Integer.toString(progress));
//Toast.makeText(getApplicationContext(), String.valueOf(progress), Toast.LENGTH_LONG).show();
}
});
final RadioButton rad5min = (RadioButton) view.findViewById(R.id.radSnooze5min);
final RadioButton rad10min = (RadioButton) view.findViewById(R.id.radSnooze10min);
rad5min.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
if(rad5min.isChecked() == true)
{
rad10min.setChecked(false);
snoozeTime = 5;
}
}
});
rad10min.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
if(rad10min.isChecked() == true)
{
rad5min.setChecked(false);
snoozeTime = 10;
}
}
});
final EditText edCustomSnooze = (EditText) view.findViewById(R.id.edSnoozeTime);
edCustomSnooze.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View view, MotionEvent motion)
{
edCustomSnooze.setText("");
if(motion.getAction() == MotionEvent.ACTION_DOWN)
{
rad5min.setChecked(false);
rad10min.setChecked(false);
snoozeTime = 0;
}
return false;
}
});
Button btnSave = (Button) view.findViewById(R.id.btnSaveAlarm);
TextView txtOccur = (TextView) view.findViewById(R.id.txtOccur);
final TextView txtVolume = (TextView) view.findViewById(R.id.txtVolume);
TextView txtSnooze = (TextView) view.findViewById(R.id.txtSnooze);
final Button btnCancel = (Button) view.findViewById(R.id.btnCancel);
btnOK.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
String minString = null;
tp.setIs24HourView(false);
hour = tp.getCurrentHour();
min = tp.getCurrentMinute();
if(min < 10)
{
minString = new StringBuilder().append(Integer.toString(0)).append(min).toString();
}
else
minString = new StringBuilder().append(Integer.toString(min)).toString();
//tv.setText(formatTime(hour, minString));
//storeSetAlarmTime(formatTime(hour, minString));
setVisibleStage(0, view);
setVisibleStage(1, view);
edAlarmTime.setText(formatTime(hour, minString));
//HomeFragment hFrag = new HomeFragment();
//replaceFragment(hFrag);
}
});
btnCancel.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
HomeFragment hFrag = new HomeFragment();
replaceFragment(hFrag);
}
});
btnSave.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
edAlarmName.clearFocus();
edAlarmTime.clearFocus();
edOccurance.clearFocus();
edCustomSnooze.clearFocus();
//INPUT VALIDATION
//ALL INPUT IS OK. NO NULL VALUES ANYWHERE. PROCEED...
if(validateInput(edAlarmTime, edAlarmName, edOccurance, seekVolume, rad5min, rad10min, edCustomSnooze))
{
saveData(view, edAlarmName.getText().toString(), edAlarmTime.getText().toString(), edOccurance.getText().toString(), seekVolume.getProgress(), snoozeTime, sharedPreferences);
//dialogBuilder("Alarm Saved", "Your alarm has been saved");
}
else
dialogBuilder("Validation Error", "Fix your input and try again");
}
});
edAlarmTime.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View view, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
}
return false;
}
});
return view;
}
public void dialogBuilder(String title, String message)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(title);
builder.setMessage(message);
builder.show();
}
public void dialogOccurance(final View view)
{
CharSequence colors[] = new CharSequence[] {"Once", "Daily", "Weekly"};
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("How often will this alarm repeat?");
builder.setItems(colors, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
TextView tv = (TextView) view.findViewById(R.id.edOccurance);
if(which == 0)
{
tv.setText("ONCE");
}
else if(which == 1)
tv.setText("DAILY");
else if(which == 2)
tv.setText("WEEKLY");
}
});
builder.show();
}
public void saveData(View view, String alarmName, String alarmTime, String occurance, int volume, int snoozeTime, SharedPreferences sharedPreferences)
{
prefEditor = sharedPreferences.edit();
prefEditor.putString(alarmTimeKey, alarmTime);
prefEditor.putString(alarmNameKey, alarmName);
prefEditor.putString(alarmOccuranceKey, occurance);
prefEditor.putInt(alarmVolumeKey, volume);
prefEditor.putInt(alarmSnoozeKey, snoozeTime);
prefEditor.putBoolean(alarmVisibleKey, true);
prefEditor.commit();
if(!sharedPreferences.getBoolean(alarmVisibleKey, true))
{
dialogBuilder("ERROR", "We tried writing the data, however we cant verify it exists");
}
else
{
dialogBuilder("Write Successfull", "true");
}
Toast.makeText(getActivity().getApplicationContext(), "Alarm Added", Toast.LENGTH_LONG).show();
HomeFragment hFrag = new HomeFragment();
replaceFragment(hFrag);
}
public void setVisibleStage(int stage, View view)
{
//Stage 0 Components
TimePicker tp = (TimePicker) view.findViewById(R.id.timePicker);
Button btnOK = (Button) view.findViewById(R.id.btnOK);
Button btnCancel = (Button) view.findViewById(R.id.btnCancel);
//Stage 1 Components
EditText edAlarmName = (EditText) view.findViewById(R.id.edAlarmName);
EditText edAlarmTime = (EditText) view.findViewById(R.id.edTime);
EditText edOccurance = (EditText) view.findViewById(R.id.edOccurance);
SeekBar seekVolume = (SeekBar) view.findViewById(R.id.seekVolume);
RadioButton rad5min = (RadioButton) view.findViewById(R.id.radSnooze5min);
RadioButton rad10min = (RadioButton) view.findViewById(R.id.radSnooze10min);
EditText edCustomSnooze = (EditText) view.findViewById(R.id.edSnoozeTime);
Button btnSave = (Button) view.findViewById(R.id.btnSaveAlarm);
TextView txtOccur = (TextView) view.findViewById(R.id.txtOccur);
TextView txtVolume = (TextView) view.findViewById(R.id.txtVolume);
TextView txtSnooze = (TextView) view.findViewById(R.id.txtSnooze);
if(stage == 0)
{
//STAGE 0 = ANALOG CLOCK DISPLAY ONLY
tp.setVisibility(view.INVISIBLE);
btnOK.setVisibility(view.INVISIBLE);
btnCancel.setVisibility(view.INVISIBLE);
}
else if(stage == 1)
{
//STAGE 1 = EVERYTHING ELSE VISIBLE
edAlarmName.setVisibility(view.VISIBLE);
edAlarmTime.setVisibility(view.VISIBLE);
txtOccur.setVisibility(view.VISIBLE);
edOccurance.setVisibility(view.VISIBLE);
txtVolume.setVisibility(view.VISIBLE);
seekVolume.setVisibility(view.VISIBLE);
txtSnooze.setVisibility(view.VISIBLE);
rad5min.setVisibility(view.VISIBLE);
rad10min.setVisibility(view.VISIBLE);
edCustomSnooze.setVisibility(view.VISIBLE);
btnSave.setVisibility(view.VISIBLE);
}
}
public void replaceFragment(Fragment fragment)
{
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_container, fragment);
//fragmentTransaction.addToBackStack(fragment.toString());
fragmentTransaction.commit();
}
public boolean validateInput(EditText edAlarmTime, EditText edAlarmName, EditText edOccurance, SeekBar seekVolume, RadioButton rad5min, RadioButton rad10min, EditText customSnooze)
{
String alarmTimeOK = edAlarmTime.getText().toString();
String alarmNameOK = edAlarmName.getText().toString();
String OccuranceOK = edOccurance.getText().toString();
int volumeOK = seekVolume.getProgress();
boolean FiveMinChecked = rad5min.isChecked();
boolean TenMinChecked = rad10min.isChecked();
String customSnoozeOK = customSnooze.getText().toString();
if(alarmTimeOK.matches("") || !alarmTimeOK.contains(":"))
return false;
else if(alarmNameOK.matches("") || alarmNameOK.contains("Alarm Name"))
return false;
else if(OccuranceOK.matches("") || OccuranceOK.contains("Choose Occurance"))
return false;
else if(volumeOK == 0)
return false;
else if(FiveMinChecked && customSnoozeOK.matches("Enter your own"))
return true;
else if(TenMinChecked && customSnoozeOK.matches("Enter your own"))
return true;
else if(FiveMinChecked == false && customSnoozeOK.matches("Enter your own"))
return false;
else if(TenMinChecked == false && customSnoozeOK.matches("Enter your own"))
return false;
else
return true;
}
public String formatTime(int hour, String minString)
{
String formattedString = null;
if(hour > 12)
{
formattedString = new StringBuilder().append(Integer.toString(hour - 12)).append(":").append(minString).append("PM").toString();
}
else
formattedString = new StringBuilder().append(Integer.toString(hour)).append(":").append(minString).append("AM").toString();
return formattedString;
}
}
Home Fragment
public class HomeFragment extends Fragment{
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private boolean alarm1Active = false;
//private boolean alarm1Visible = false;
//public String alarm1Name;
//public String alarm1Time;
//public String alarm1Occurance;
//public int alarm1Snooze;
//public int alarm1Volume;
//public boolean fragmentSwitch;
SharedPreferences sharedPreferences;
SharedPreferences.Editor prefEditor;
public static final String alarmPreferences = "alarmPreferences";
public static final String alarmTimeKey = "alarmTimeKey";
public static final String alarmNameKey = "alarmNameKey";
public static final String alarmOccuranceKey = "alarmOccuranceKey";
public static final String alarmVolumeKey = "alarmVolumeKey";
public static final String alarmSnoozeKey = "alarmSnoozeKey";
public static final String alarmVisibleKey = "alarmVisibleKey";
public boolean devMode = true;
public HomeFragment() {
// Required empty public constructor
}
public static HomeFragment newInstance(String param1, String param2) {
HomeFragment fragment = new HomeFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
final View view = inflater.inflate(R.layout.fragment_home, container, false);
//CODE HERE
readPreferences(view);
FloatingActionButton fabAddAlarm = (FloatingActionButton) view.findViewById(R.id.fabRefresh);
fabAddAlarm.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(getActivity().getApplicationContext(), "Reading Preferences", Toast.LENGTH_LONG).show();
readPreferences(view);
}
});
return view;
}
public void readPreferences(View view)
{
TextView tvAlarm1Name = (TextView) view.findViewById(R.id.tvAlarm1Name);
TextView tvAlarm1Time = (TextView) view.findViewById(R.id.tvAlarm1Time);
TextView tvAlarm1Occurance = (TextView) view.findViewById(R.id.tvAlarm1Occurance);
Switch swAlarm1Active = (Switch) view.findViewById(R.id.swEnableAlarm1);
Button btnEditAlarm1 = (Button) view.findViewById(R.id.btnEditAlarm1);
TextView status = (TextView) view.findViewById(R.id.tvNoAlarms);
sharedPreferences = getActivity().getSharedPreferences(alarmPreferences, Context.MODE_PRIVATE);
String alarm1Name = sharedPreferences.getString(alarmNameKey, null);
String alarm1Time = sharedPreferences.getString(alarmTimeKey, null);
String alarm1Occurance = sharedPreferences.getString(alarmOccuranceKey, null);
int alarm1Snooze = sharedPreferences.getInt(alarmSnoozeKey, 0);
int alarm1Volume = sharedPreferences.getInt(alarmVolumeKey, 0);
boolean alarm1Visible = sharedPreferences.getBoolean(alarmVisibleKey, false);
if(!alarm1Visible)
{
status.setVisibility(View.VISIBLE);
status.setText("You have no alarms set!");
}
else if(alarm1Visible)
{
status.setVisibility(View.INVISIBLE);
tvAlarm1Time.setVisibility(View.VISIBLE);
tvAlarm1Name.setVisibility(View.VISIBLE);
tvAlarm1Occurance.setVisibility(View.VISIBLE);
btnEditAlarm1.setVisibility(View.VISIBLE);
swAlarm1Active.setVisibility(View.VISIBLE);
tvAlarm1Time.setText(alarm1Time);
tvAlarm1Name.setText(alarm1Name);
tvAlarm1Occurance.setText(alarm1Occurance);
}
}
}
While saving string on SharedPreferences make sure that you are not saving null. It will instead clear the preference key.
prefEditor.putString(alarmOccuranceKey, occurance);
Make sure that occurance is not null.
Please use commit() to save the data. Also you can create a simple reusable class for SharedPreferences. Please refer to my customized class for the same: https://codebegetter.wordpress.com/2016/08/04/shared-preferences-reusable-class/
Based on the comments in one of the answers it looks like you have applied a solution. However, based on the code you posted here was the issue:
You are not storing and retrieving values from the same SharedPreferences file. When you store values you are using a custom named SharedPreferences file. When you try to retrieve those values you are referencing the SharedPreferences file that is specific to the Activity which hosts your secondFragment. (Which, in a way, is actually custom named as well...the framework bases it on your Activity name).
When you write values to SharedPreferences in your secondFragment you call:
sharedPreferences = getActivity().getSharedPreferences(alarmPreferences, Context.MODE_PRIVATE);
//...
prefEditor = sharedPreferences.edit();
When you attempt to read those values in your HomeFragment you call:
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
These two code snippets don't reference the same SharePreferences file. The most direct solution would be to update the code in your HomeFragment so that you obtain the same SharePreferences file where you stored your values like so:
sharedPreferences = getActivity().getSharedPreferences(alarmPreferences, Context.MODE_PRIVATE);
This fairly simple dialog dismisses itself after screen rotation despite I setRetainInstance to true. Any ideas whats wrong?
public class StreetDialog extends DialogFragment {
public static StreetDialog newInstance(String[] values) {
StreetDialog f = new StreetDialog();
Bundle args = new Bundle();
args.putStringArray("values", values);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String[] values = getArguments().getStringArray("values");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//build my dialog
return builder.create();
}
#Override
public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
}
If I recall correctly is the normal behaviour. I usually provide a tag to the show method, and when the Activity's onCreate is called again, I look for the tag. If the fragment != null I remove it, before creating and showing the new one. In code, what I usually do is:
Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
if (fragment != null) {
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
new CustomDialogFragment().show(getSupportFragmentManager(), FRAGMENT_TAG );
This is an issue that I believe the best way to solve and using an approach below:
Create a static method to initialize a Dialog, remembering that this is a good practice since we always have the default constructor and the Bundle stores the state of the Fragment.
In onCreateDialog method, initialize the AlertDialog with the data passed in the "constructor method".
In your Activity you can implement an interface (because we can not keep the reference of it, since it may have been destroyed when rotating the device). To open the dialog,
checking that it has been added to FragmentManager otherwise exhibit.
see more here (Link in portuguese - br): http://nglauber.blogspot.com.br/2013_10_01_archive.html
public class SimpleDialog extends DialogFragment implements OnClickListener {
private static final String EXTRA_ID = "id";
private static final String EXTRA_MESSAGE = "message";
private static final String EXTRA_TITLE = "title";
private static final String EXTRA_BUTTONS = "buttons";
private static final String DIALOG_TAG = "SimpleDialog";
private int dialogId;
public static SimpleDialog newDialog(int id,
String title, String message, int[] buttonTexts){
// Using the Bundle to save state
Bundle bundle = new Bundle();
bundle.putInt(EXTRA_ID, id);
bundle.putString(EXTRA_TITLE, title);
bundle.putString(EXTRA_MESSAGE, message);
bundle.putIntArray(EXTRA_BUTTONS, buttonTexts);
SimpleDialog dialog = new SimpleDialog();
dialog.setArguments(bundle);
return dialog;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments() .getString(EXTRA_TITLE);
String message = getArguments().getString(EXTRA_MESSAGE);
int[] buttons = getArguments().getIntArray(EXTRA_BUTTONS);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setMessage(message);
switch (buttons.length) {
case 3:
alertDialogBuilder.setNeutralButton(buttons[2], this);
case 2:
alertDialogBuilder.setNegativeButton(buttons[1], this);
case 1:
alertDialogBuilder.setPositiveButton(buttons[0], this);
}
return alertDialogBuilder.create();
}
#Override
public void onClick(DialogInterface dialog, int which) {
// Your Activity must to implements this interface
((FragmentDialogInterface)getActivity()).onClick(dialogId, which);
}
public void openDialog( FragmentManager supportFragmentManager) {
if (supportFragmentManager.findFragmentByTag( DIALOG_TAG) == null){
show(supportFragmentManager, DIALOG_TAG);
}
}
// Interface that was invoked by clicking the button
public interface FragmentDialogInterface {
void onClick(int id, int which);
}
To open the dialog in your activity
public void openSimpleDialog(View v) {
SimpleDialog dialog = SimpleDialog.newDialog(
0, // Id from dialog
"Alert", // title
"Message", // menssage
new int[]{ // texts from buttons
android.R.string.ok,
android.R.string.cancel });
dialog.openDialog(getSupportFragmentManager());
}
#Override
public void onClick(int id, int which) {
Toast.makeText(MainActivity.this,
"Button clicked"+ which, Toast.LENGTH_SHORT)
.show();
}