I dont know why i am change an activity to fragment there it is not working as expected.
020-06-22 14:18:38.973 13510-13510/com.vikaskonaparthi.time E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.vikaskonaparthi.time, PID: 13510
java.lang.ClassCastException: com.vikaskonaparthi.time.MainActivity cannot be cast to android.app.TimePickerDialog$OnTimeSetListener
at com.vikaskonaparthi.time.dialogs.TimePickerDialogFragment.onAttach(TimePickerDialogFragment.java:29)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1247)
at android.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2431)
at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2210)
at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2166)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2067)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:742)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
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:935)
Here is Timepicker dialog fragment
public class TimePickerDialogFragment extends DialogFragment {
private int hour;
private int minute;
private TimePickerDialog.OnTimeSetListener listener;
public static final String FRAGMENT_TAG = "time_picker";
public static final String BUNDLE_KEY_ALARM_HOUR = "alarm_hour";
public static final String BUNDLE_KEY_ALARM_MINUTE = "alarm_minute";
@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (TimePickerDialog.OnTimeSetListener) context;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle bundle = getArguments();
hour = bundle.getInt(BUNDLE_KEY_ALARM_HOUR);
minute = bundle.getInt(BUNDLE_KEY_ALARM_MINUTE);
final AlarmTimePickerDialog timePickerDialog = new AlarmTimePickerDialog(getActivity(), listener, hour, minute, true);
LayoutInflater inflater = LayoutInflater.from(getActivity());
View customTitleView = inflater.inflate(R.layout.partial_timepicker_dialog_title, null);
timePickerDialog.setCustomTitle(customTitleView);
timePickerDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
timePickerDialog.showTimeLeft(hour, minute);
}
});
return timePickerDialog;
}
}
here is alert dialog
public class AlarmTimePickerDialog extends TimePickerDialog {
public AlarmTimePickerDialog(Context context, OnTimeSetListener listener, int hourOfDay, int minute,
boolean is24HourView) {
super(context, listener, hourOfDay, minute, is24HourView);
}
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
super.onTimeChanged(view, hourOfDay, minute);
showTimeLeft(hourOfDay, minute);
}
@Override
public void setCustomTitle(View customTitleView) {
if (getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { //title is displayed in portrait orientation only
super.setCustomTitle(customTitleView);
}
}
public void showTimeLeft(int hour, int minute) {
if (getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
TextView textView = (TextView) this.findViewById(R.id.textview_timepickerdialog_timeleft);
AlarmTime time = new AlarmTime(hour, minute);
textView.setText(getContext().getString(R.string.all_time_left, time.getHoursLeft(), time.getMinutesLeft()));
}
}
}
I had seen many like these and tried but nothing worked.Actually this code is working fine in as activity but when i changed activity to fragment the errors are throwing.
Thank You in advance.
public class Fragment1 extends Fragment implements
IntervalDialogFragment.IntervalDialogListener,
NumberOfAlarmsDialogFragment.NumberOfAlarmsDialogListener,
TimePickerDialog.OnTimeSetListener{
SwitchCompat onOffSwitch;
ListView alarmsListView;
TextView intervalBetweenAlarmsTextView;
TextView numberOfAlarmsTextView;
TextView firstAlarmTextView;
TextView timeLeftTextView;
LinearLayout firstAlarmLayout;
LinearLayout intervalLayout;
LinearLayout numberOfAlarmsLayout;
AlarmsListHelper alarmsListHelper;
SharedPreferencesHelper sharPrefHelper;
TimerManager timerManager;
AlarmParams alarmParams;
BroadcastReceiver timeLeftReceiver;
private final String LOG_TAG = Fragment1.class.getSimpleName();
final int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 45;
final float DISPLAYED_NUMBERS_SIZE_RELATIVE_TO_TEXT_PROPORTION = 2f; // number of alarms, first alarm, interval values text size is larger than text around them
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment1,container,false);
alarmsListView = (ListView) root.findViewById(R.id.listview_main_alarmslist);
onOffSwitch = (SwitchCompat) root.findViewById(R.id.switch_main);
intervalBetweenAlarmsTextView = (TextView) root.findViewById(R.id.textview_main_interval);
numberOfAlarmsTextView = (TextView) root.findViewById(R.id.textview_main_numberofalarms);
firstAlarmLayout = (LinearLayout) root.findViewById(R.id.layout_main_firstalarm);
firstAlarmTextView = (TextView) root.findViewById(R.id.textview_main_firstalarm_time);
timeLeftTextView = (TextView) root.findViewById(R.id.textview_main_timeleft);
intervalLayout = (LinearLayout) root.findViewById(R.id.layout_main_interval);
numberOfAlarmsLayout = (LinearLayout) root.findViewById(R.id.layout_main_numberofalarms);
sharPrefHelper = new SharedPreferencesHelper(getActivity());
sharPrefHelper.printAll();
alarmParams = sharPrefHelper.getParams();
timerManager = new TimerManager(getActivity());
alarmsListHelper = new AlarmsListHelper(getActivity(), alarmsListView);
showFirstAlarmTime(alarmParams.firstAlarmTime.toString());
showTimeLeft(alarmParams);
showInterval(sharPrefHelper.getIntervalStr());
showNumberOfAlarms(sharPrefHelper.getNumberOfAlarmsStr());
onOffSwitch.setChecked(sharPrefHelper.isAlarmTurnedOn());
alarmsListHelper.showList(alarmParams);
onOffSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
alarmParams.turnedOn = isChecked;
if (isChecked) {
checkNotificationPolicy();
checkOverlayPermission();
timerManager.startSingleAlarmTimer(alarmParams.firstAlarmTime.toMillis());
showToast(getString(R.string.main_alarm_turned_on_toast));
sharPrefHelper.setNumberOfAlreadyRangAlarms(0);
} else {
timerManager.cancelTimer();
showToast(getString(R.string.main_alarm_turned_off_toast));
}
alarmsListHelper.showList(alarmParams);
showTimeLeft(alarmParams);
sharPrefHelper.setAlarmState(isChecked);
}
});
intervalLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
IntervalDialogFragment dialog = new IntervalDialogFragment();
Bundle intervalBundle = new Bundle();
intervalBundle.putString(IntervalDialogFragment.BUNDLE_KEY_INTERVAL, sharPrefHelper.getIntervalStr());
dialog.setArguments(intervalBundle);
dialog.show(getActivity().getFragmentManager(), IntervalDialogFragment.FRAGMENT_TAG);
}
});
numberOfAlarmsLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NumberOfAlarmsDialogFragment dialog = new NumberOfAlarmsDialogFragment();
Bundle numberOfAlarmsBundle = new Bundle();
numberOfAlarmsBundle.putString(NumberOfAlarmsDialogFragment.BUNDLE_KEY_NUMBER_OF_ALARMS, sharPrefHelper.getNumberOfAlarmsStr());
dialog.setArguments(numberOfAlarmsBundle);
dialog.show(getActivity().getFragmentManager(), NumberOfAlarmsDialogFragment.FRAGMENT_TAG);
}
});
firstAlarmLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle timePickerBundle = new Bundle();
timePickerBundle.putInt(TimePickerDialogFragment.BUNDLE_KEY_ALARM_HOUR, sharPrefHelper.getHour());
timePickerBundle.putInt(TimePickerDialogFragment.BUNDLE_KEY_ALARM_MINUTE, sharPrefHelper.getMinute());
TimePickerDialogFragment timePicker = new TimePickerDialogFragment();
timePicker.setArguments(timePickerBundle);
timePicker.show(getActivity().getFragmentManager(), TimePickerDialogFragment.FRAGMENT_TAG);
}
});
return root;
}
@Override
public void onResume() {
super.onResume();
showTimeLeft(alarmParams);
timeLeftReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().compareTo(Intent.ACTION_TIME_TICK) == 0) { //i.e. every minute
showTimeLeft(alarmParams);
}
}
};
getActivity().registerReceiver(timeLeftReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
}
@Override
public void onPause() {
super.onPause();
if (timeLeftReceiver != null) {
getActivity().unregisterReceiver(timeLeftReceiver);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_settings: {
Intent intent = new Intent(getActivity(), PrefActivity.class);
startActivity(intent);
break;
}
}
return super.onOptionsItemSelected(item);
}
@Override
public void onIntervalChanged(String intervalStr) {
showInterval(intervalStr);
alarmParams.interval = Integer.parseInt(intervalStr);
alarmsListHelper.showList(alarmParams);
resetTimerIfTurnedOn();
sharPrefHelper.setInterval(intervalStr);
}
@Override
public void onNumberOfAlarmsChanged(String numberOfAlarmsStr) {
showNumberOfAlarms(numberOfAlarmsStr);
alarmParams.numberOfAlarms = Integer.parseInt(numberOfAlarmsStr);
alarmsListHelper.showList(alarmParams);
resetTimerIfTurnedOn();
sharPrefHelper.setNumberOfAlarms(numberOfAlarmsStr);
}
@Override
public void onTimeSet(TimePicker view, int hour, int minute) {
AlarmTime alarmTime = new AlarmTime(hour, minute);
alarmParams.firstAlarmTime = alarmTime;
showFirstAlarmTime(alarmTime.toString());
alarmsListHelper.showList(alarmParams);
showTimeLeft(alarmParams);
sharPrefHelper.setNumberOfAlreadyRangAlarms(0);
resetTimerIfTurnedOn();
sharPrefHelper.setTime(alarmTime);
}
private void showToast(String message) {
Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
}
private void resetTimerIfTurnedOn() {
if (onOffSwitch.isChecked()) {
timerManager.resetSingleAlarmTimer(alarmParams.firstAlarmTime.toMillis());
showToast(getString(R.string.main_alarm_reset_toast));
}
}
private void showInterval(String interval) {
String wholeTitle = getString(R.string.main_interval, interval);
SpannableString wholeTitleSpan = new SpannableString(wholeTitle);
wholeTitleSpan.setSpan(new RelativeSizeSpan(DISPLAYED_NUMBERS_SIZE_RELATIVE_TO_TEXT_PROPORTION), wholeTitle.indexOf(interval), interval.length() + 1, 0);
intervalBetweenAlarmsTextView.setText(wholeTitleSpan);
}
private void showNumberOfAlarms(String numberOfAlarms) {
int numberOfAlarmsInt = Integer.parseInt(numberOfAlarms);
String wholeTitle = this.getResources().getQuantityString(R.plurals.main_number_of_alarms, numberOfAlarmsInt, numberOfAlarmsInt);
SpannableString wholeTitleSpan = new SpannableString(wholeTitle);
wholeTitleSpan.setSpan(new RelativeSizeSpan(DISPLAYED_NUMBERS_SIZE_RELATIVE_TO_TEXT_PROPORTION),
wholeTitle.indexOf(numberOfAlarms),
numberOfAlarms.length() + 1, 0);
numberOfAlarmsTextView.setText(wholeTitleSpan);
}
private void showFirstAlarmTime(String firstAlarmTime) {
String wholeTitle = getString(R.string.main_firstalarm_time, firstAlarmTime);
SpannableString wholeTitleSpan = new SpannableString(wholeTitle);
wholeTitleSpan.setSpan(new RelativeSizeSpan(DISPLAYED_NUMBERS_SIZE_RELATIVE_TO_TEXT_PROPORTION),
wholeTitle.indexOf(firstAlarmTime) - 1,
wholeTitle.indexOf(firstAlarmTime) + firstAlarmTime.length(), 0);
firstAlarmTextView.setText(wholeTitleSpan);
}
private void showTimeLeft(AlarmParams alarmParams) {
AlarmTime alarmTime = alarmParams.firstAlarmTime;
timeLeftTextView.setText(getString(R.string.all_time_left, alarmTime.getHoursLeft(), alarmTime.getMinutesLeft()));
if (alarmParams.turnedOn) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
timeLeftTextView.setTextColor(getActivity().getColor(R.color.primary));
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
timeLeftTextView.setTextColor(getActivity().getColor(R.color.main_disabled_textcolor));
}
}
Log.d(LOG_TAG, "Time left: "+alarmTime.getHoursLeft() + ":" + alarmTime.getMinutesLeft());
}
private void checkNotificationPolicy() {
NotificationManager notificationManager =
(NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& !notificationManager.isNotificationPolicyAccessGranted()) {
Intent intent = new Intent(
android.provider.Settings
.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivity(intent);
}
}
/**
* needed for Android Q: on some devices activity doesn't show from fullScreenNotification without
* permission SYSTEM_ALERT_WINDOW
*/
private void checkOverlayPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if ((Build.VERSION.SDK_INT > Build.VERSION_CODES.P) && (!Settings.canDrawOverlays(getActivity()))) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getActivity().getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
}
}
Present your time picked dialogue using child fragment manager:
timePicker.show(getChildFragmentManager(), TimePickerDialogFragment.FRAGMENT_TAG);
What is child fragment manager for? Java docs will help us:
/**
* Return a private FragmentManager for placing and managing Fragments
* inside of this Fragment.
*/
@NonNull
final public FragmentManager getChildFragmentManager() {
if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " has not been attached yet.");
}
return mChildFragmentManager;
}
Thus your time picker dialogue will be "managed" by Fragment1
(not by the fragment directly of course).
After changing fragment manager you now can cast parent fragment (not manager) of TimePickerDialogFragment
to TimePickerDialog.OnTimeSetListener
.
public class TimePickerDialogFragment extends DialogFragment {
...
private TimePickerDialog.OnTimeSetListener listener;
...
@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (TimePickerDialog.OnTimeSetListener) getParentFragment();
}
...
You can get parent fragment by calling getParentFragment()
:
/**
* Returns the parent Fragment containing this Fragment. If this Fragment
* is attached directly to an Activity, returns null.
*/
@Nullable
final public Fragment getParentFragment() {
return mParentFragment;
}
Note: be aware of possible memory leaks.
Extend TimePickerDialogFragment
with DialogFragment
from the androidx
package: