首页 > 解决方案 > MainActivity 无法强制转换为 android.app.TimePickerDialog$OnTimeSetListener 无法解决

问题描述

我不知道为什么我要改变一个活动来分段它没有按预期工作。

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)

这是 Timepicker 对话框片段

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;
}
}

这是警报对话框

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()));
    }
}
}

我见过很多这样的东西并尝试过,但没有任何效果。实际上,这段代码在活动中运行良好,但是当我将活动更改为碎片时,错误正在抛出。

先感谢您。

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);
        }
    }
}
}

标签: javaandroidandroid-studioandroid-fragmentsandroid-activity

解决方案


尝试为您的片段实现 TimePickerDialog.OnTimeSetListener:

public class TimePickerDialogFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener

////

@Override
    public void onAttach(Context context) {
        super.onAttach(context);
        listener = this;
    }

    @Override
    public void onTimeSet(TimePicker timePicker, int i, int i1) {
        // get selected time
    }

推荐阅读