You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AndroidX环境下无法使用DialogPreference的解决方案咨询

解决AndroidX下自定义DialogPreference的类型转换异常

你碰到的com.example.todolist.TimePickerPreference cannot be cast to androidx.preference.Preference异常,确实是因为自定义Preference继承了旧框架的android.preference.DialogPreference,但项目里其他组件用的是AndroidX库——这俩属于完全不同的框架体系,自然没法互相转换。下面我一步步教你把代码迁移到AndroidX版本:

1. 替换导入包

把所有旧的android.preference相关导入,全部换成AndroidX的androidx.preference包。比如直接把import android.preference.DialogPreference;改成import androidx.preference.DialogPreference;,其他涉及旧Preference的导入也同理替换。

2. 修正构造方法

AndroidX的DialogPreference构造方法和旧版本有细微差别,建议使用标准的重载形式,这样兼容性更好:

public TimePickerPreference(Context context, AttributeSet attrs) {
    this(context, attrs, androidx.preference.R.attr.dialogPreferenceStyle);
}

public TimePickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    setDialogLayoutResource(R.layout.timepickerpreferencelayout);
    setPositiveButtonText("ok");
    setNegativeButtonText("cancel");
}

3. 修正时间计算逻辑(额外小修复)

你的getMinute方法原来的计算会返回毫秒数,不是分钟数,这会导致时间显示错误,我帮你修正了这个问题。

修改后的完整代码

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import android.widget.TimePicker;
import androidx.preference.DialogPreference;

public class TimePickerPreference extends DialogPreference {
    private static final int DEFAULT_TIME = 0;
    private TimePicker mTimePicker;
    private int currentTime;

    public TimePickerPreference(Context context, AttributeSet attrs) {
        this(context, attrs, androidx.preference.R.attr.dialogPreferenceStyle);
    }

    public TimePickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setDialogLayoutResource(R.layout.timepickerpreferencelayout);
        setPositiveButtonText("ok");
        setNegativeButtonText("cancel");
    }

    private static int getTime(int hour, int minute){
        return hour*60*60*1000 + minute*60*1000;
    }

    private static int getHour(int value){
        return (int)(value / (60*60*1000));
    }

    private static int getMinute(int value){
        // 修正:把毫秒数转成分钟
        return (int)((value % (60*60*1000)) / (60*1000));
    }

    @Override
    protected View onCreateDialogView() {
        View view = super.onCreateDialogView();
        mTimePicker = view.findViewById(R.id.timePicker);
        mTimePicker.setIs24HourView(true);
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mTimePicker.setHour(getHour(currentTime));
            mTimePicker.setMinute(getMinute(currentTime));
        } else {
            mTimePicker.setCurrentHour(getHour(currentTime));
            mTimePicker.setCurrentMinute(getMinute(currentTime));
        }
        
        mTimePicker.setOnTimeChangedListener((timePicker, hour, minute) -> 
            currentTime = getTime(hour, minute));
        
        TextView messageTextView = view.findViewById(R.id.messageTextView);
        if (getDialogMessage() == null || getDialogMessage().toString().trim().isEmpty()) {
            messageTextView.setVisibility(View.GONE);
        } else {
            messageTextView.setText(getDialogMessage());
        }
        return view;
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return a.getInt(index, DEFAULT_TIME);
    }

    @Override
    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
        if(restorePersistedValue) {
            currentTime = getPersistedInt(defaultValue == null ? DEFAULT_TIME : (int) defaultValue);
        } else {
            currentTime = (int) defaultValue;
            if (shouldPersist()) {
                persistInt(currentTime);
            }
        }
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            persistInt(currentTime);
        }
    }
}

最后提醒:Preference布局的引用

在你的PreferenceScreen布局文件里引用这个自定义Preference时,要使用app:前缀的属性(AndroidX的标准写法),比如:

<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
    <com.example.todolist.TimePickerPreference
        app:key="alarm_time"
        app:title="设置闹钟时间"
        app:dialogMessage="选择每日提醒时间"/>
</PreferenceScreen>

内容的提问来源于stack exchange,提问作者David Yao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:53:28