For my app, I want my user to be able to press a "Change User" button, have a fragment pop-up, take in a text input, and then save to shared preferences upon exit, returning to the activity it was called from.
I would like my methodology to be similar to a TimePicker fragment I have already implemented, which I will post at the end of this.
I am currently using this tutorial as a guide: Dialog Fragment Tutorial
Here is my Dialog Fragment Class:
public class EditNameDialog extends DialogFragment {
private EditText mEditText;
public EditNameDialog() {
// Empty constructor required for DialogFragment
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edit_name, container);
getDialog().setTitle("Hello");
return view;
}
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return true;
}
}
Here is my MainActivity that calls it:
public class MainActivity extends Activity implements
TimePickerFragment.FragmentCallbacks {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Use the current time as the default values for the picker
SharedPreferences sharedPref = this.getSharedPreferences("prediction",
Context.MODE_PRIVATE);
final Calendar c = Calendar.getInstance();
int defaultHour = c.get(Calendar.HOUR_OF_DAY);
int defaultMinute = c.get(Calendar.MINUTE);
int hour = sharedPref.getInt("prediction_hour", defaultHour);
int minute = sharedPref.getInt("prediction_min", defaultMinute);
String timeString = Integer.toString(hour) + ":"
+ Integer.toString(minute);
TextView predictionText = (TextView) findViewById(R.id.prediction_time);
predictionText.setText(timeString);
}
public void showTimePickerDialog(View v) {
DialogFragment newFragment = new TimePickerFragment();
newFragment.show(getFragmentManager(), "timePicker");
}
public void showUserNameEdit(View c) {
EditNameDialog newFragment = new EditNameDialog();
newFragment.show(getSupportFragmentManager(), "editName");
}
@Override
public void TimeUpdated(int hour, int minute) {
Toast.makeText(this, "Hour: " + hour + " Minute: " + minute,
Toast.LENGTH_SHORT).show();
// finish();
// startActivity(new Intent(this, MainActivity.class));
String timeString = Integer.toString(hour) + ":"
+ Integer.toString(minute);
TextView predictionText = (TextView) findViewById(R.id.prediction_time);
predictionText.setText(timeString);
}
}
I believe that this is where the problem lies. Either I call show() with getFragmentManager() and it says that show() only takes getSupportFragmentManager(), or I call it with getSupportFragmentManager(), and it says that Activity does not have this method. I know that I could extend my activity with FragmentActivity instead, but this creates other issues. I would like to call it like my TimePickerFragment, shown below:
public class TimePickerFragment extends DialogFragment implements
TimePickerDialog.OnTimeSetListener {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the current time as the default values for the picker
Context context = getActivity();
SharedPreferences sharedPref = context.getSharedPreferences(
"prediction", Context.MODE_PRIVATE);
final Calendar c = Calendar.getInstance();
int defaultHour = c.get(Calendar.HOUR_OF_DAY);
int defaultMinute = c.get(Calendar.MINUTE);
int hour = sharedPref.getInt("prediction_hour", defaultHour);
int minute = sharedPref.getInt("prediction_min", defaultMinute);
// Create a new instance of TimePickerDialog and return it
return new TimePickerDialog(getActivity(), this, hour, minute,
DateFormat.is24HourFormat(getActivity()));
}
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Context context = getActivity();
SharedPreferences sharedPref = context.getSharedPreferences(
"prediction", Context.MODE_PRIVATE);
SharedPreferences.Editor editorh = sharedPref.edit();
editorh.putInt("prediction_hour", hourOfDay);
editorh.commit();
SharedPreferences.Editor editorm = sharedPref.edit();
editorm.putInt("prediction_min", minute);
editorm.commit();
mCallbacks.TimeUpdated(hourOfDay, minute);
}
/**
* Interface
*/
private FragmentCallbacks mCallbacks;
public interface FragmentCallbacks {
void TimeUpdated(int hour, int minute);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallbacks = (FragmentCallbacks) activity;
} catch (ClassCastException e) {
throw new ClassCastException(
"Activity must implement Fragment Two.");
}
}
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
}
I suggest staying up-to-date with the latest support libraries, so that your app uses the latest in user interface designs (Material Design) and across all devices your app will retain the same look. So I suggest do as follows:
For DialogFragments, you should pass arguments to start a new instance of your fragment, instead of using shared preferences. While shared preferences still works, it isn't a very ideal solution. Best practices for passing arguments to a dialog fragment are shown below with a method called newInstance(). The reason you don't pass the arguments to the constructor can be found here
Use AppCompatDialog in onCreateDialog, and the use the imports shown below:
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatDialog;
...
...
public class TimePickerFragment extends DialogFragment implements
TimePickerDialog.OnTimeSetListener {
public static TimePickerFragment newInstance(int hour, int min){
TimePickerFragment frag = new TimePickerFragment();
Bundle args = new Bundle();
args.putInt("hour", hour);
args.putInt("min", min);
frag.setArguements(args);
return frag;
}
@Override
public AppCompatDialog onCreateDialog(Bundle savedInstanceState) {
// Use the current time as the default values for the picker
final Calendar c = Calendar.getInstance();
int defaultHour = c.get(Calendar.HOUR_OF_DAY);
int defaultMinute = c.get(Calendar.MINUTE);
int hour = getArguments().getInt("hour");
int minute = getArguments().getInt("min");
// Create a new instance of TimePickerDialog and return it
return new TimePickerDialog(getActivity(), this, hour, minute,
DateFormat.is24HourFormat(getActivity()));
}
...
...
}
And when you show it do the following:
TimePickerFragment.newInstance(hour, min).show(getSupportFragmentManager(), "time_fragment");
And in your activity should extend AppCompatActivity like follows:
public class MainActivity extends AppCompatActivity implements
TimePickerFragment.FragmentCallbacks {
Then in your activity use getSupportFragmentManager() when calling show();
If you don't have the latest support libraries downloaded with your app, add these dependencies to your gradle file:
dependencies {
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.android.support:support-v4:22.1.1'
...
}