アンドロイド7.0のためのスピナーモードでDatePickerDialogを修正するには?

Oranakia:

私は現在、サイト自体とAndroidのモバイルデバイス間の双方向性を向上させるためにマイナーな相互作用を持つWeb表示に包まれたウェブサイトからなる単純なプロジェクトを開発しています。

ウェブサイトがユーザの誕生日の日付入力フィールドが含まれているので、私はすべてのデバイスと互換性のあるスピナー形式で日付ピッカーを実装するために探していました。私は以下のソリューションを実装しようとしました。

`<style name="MyAppTheme" parent="android:Theme.Material">
    <item name="android:dialogTheme">@style/MyDialogTheme</item>
    <item name="android:datePickerStyle">@style/MyDatePicker</item>
</style>
<style name="MyDialogTheme" parent="android:Theme.Material.Dialog">
    <item name="android:datePickerStyle">@style/MyDatePicker</item>
</style>
<style name="MyDatePicker" parent="android:Widget.Material.DatePicker">
    <item name="android:datePickerMode">spinner</item>
</style>`

:に示すようにロリポップ[スピナーモード]でカレンダーの可視化せずに日付ピッカーダイアログ?

:答えは指摘するようにしかし、この解決策は、以下の既知のバグが原因のAndroid 7.0ヌガー/ API 24では動作しませんhttps://issuetracker.google.com/issues/37119315を

私のようないくつか提案されたソリューションに出くわしたいくつかの研究を行います。

https://gist.github.com/uqmessias/d9a8dc624af935f344dfa2e8928490ec

https://gist.github.com/lognaturel/232395ee1079ff9e4b1b8e7096c3afaf

DatePickerDialogホロスタイリングは、Android 7ヌガーに失敗しました。

しかし、私の場合には、それらのどれもアンドロイド7.0、または任意の他のデバイスとデバイスのいずれかのために働くように見えるん。

私はこれを引き起こしている可能性がありますかと思ったので、私はアンドロイドの開発に深く経験の浅いですし、解決策のいくつかは、彼らが時代遅れになっている可能性があることそのほとんどを廃棄し、最近まで維持されているように私は、それをどのように解決することができます。

私は投稿のコードで指摘されていない何かを実装する必要があると私は認識していない午前ですか?

日付ピッカー要素は、Webビューからではなく、私にこれらのソリューションは無用アプリ自体から直接呼び出されているという事実ですか?もしそうなら、このための周りのすべての作業はありますか?

タイラーV:

私は、(ユーザーが自分の誕生年を見つけるために、月によって40年の月の時間に戻ってスクロールしたくないと、ほとんどはあなただけ年をスクロールするには、Android日付ピッカーで年をクリックすることができます知っていない)同じ問題に遭遇しました。私はそれが今年の選択モードで起動させる方法(SOとGoogleからの助けを借りて)考え出したので、あなたのように、私は、普遍的に仕事にスピナーを取得できませんでした。

私のコードはDatePickerDialogFragment以下の貼り付けられます。

public class DatePickerDialogFragment extends DialogFragment {

    private DatePickerDialog.OnDateSetListener listener = null;

    void setListener(DatePickerDialog.OnDateSetListener listener) {
        this.listener = listener;
    }

    private static final String START_IN_YEARS = "com.myapp.picker.START_IN_YEARS";
    private static final String YEAR = "com.myapp.picker.YEAR";
    private static final String MONTH = "com.myapp.picker.MONTH";
    private static final String DAY_OF_MONTH = "com.myapp.picker.DAY_OF_MONTH";

    public static DatePickerDialogFragment newInstance(boolean startInYears, Calendar c) {
        DatePickerDialogFragment f = new DatePickerDialogFragment();

        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);

        Bundle args = new Bundle();
        args.putBoolean(START_IN_YEARS, startInYears);
        args.putInt(YEAR, year);
        args.putInt(MONTH, month);
        args.putInt(DAY_OF_MONTH, day);

        f.setArguments(args);
        return f;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        Bundle args = getArguments();
        DatePickerDialog dpd = null;

        if( listener != null && args != null) {
            boolean startInYears = args.getBoolean(START_IN_YEARS);

            Context context = getActivity();
            boolean requireSpinnerMode = isBrokenSamsungDevice();
            if (requireSpinnerMode) {
                context = new ContextThemeWrapper(context, android.R.style.Theme_Holo_Light_Dialog);
            }

            int year = args.getInt(YEAR);
            int month = args.getInt(MONTH);
            int day = args.getInt(DAY_OF_MONTH);

            dpd = new DatePickerDialog(context, listener, year, month, day);

            if (startInYears && !requireSpinnerMode) {
                boolean canOpenYearView = openYearView(dpd.getDatePicker());
                if (!canOpenYearView) {
                    context = new ContextThemeWrapper(getActivity(), android.R.style.Theme_Holo_Light_Dialog);
                    dpd = new DatePickerDialog(context, listener, year, month, day);
                }
            }
        }
        else {
            setShowsDialog(false);
            dismissAllowingStateLoss();
        }

        return dpd;
    }

    private static boolean isBrokenSamsungDevice() {
        return Build.MANUFACTURER.equalsIgnoreCase("samsung") &&
                isBetweenAndroidVersions(
                        Build.VERSION_CODES.LOLLIPOP,
                        Build.VERSION_CODES.LOLLIPOP_MR1);
    }

    private static boolean isBetweenAndroidVersions(int min, int max) {
        return Build.VERSION.SDK_INT >= min && Build.VERSION.SDK_INT <= max;
    }

    private static boolean openYearView(DatePicker datePicker) {
        if( isBrokenSamsungDevice() ) {
            return false;
        }

        View v = datePicker.findViewById(Resources.getSystem().getIdentifier("date_picker_header_year", "id", "android"));
        if( v != null ) {
            v.performClick();
        }
        else {
            try {
                Field mDelegateField = datePicker.getClass().getDeclaredField("mDelegate");
                mDelegateField.setAccessible(true);
                Object delegate = mDelegateField.get(datePicker);
                Method setCurrentViewMethod = delegate.getClass().getDeclaredMethod("setCurrentView", int.class);
                setCurrentViewMethod.setAccessible(true);
                setCurrentViewMethod.invoke(delegate, 1);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }
}

活動中のコード(メンバ変数とかでonCreate)これを起動する(と回転にそれを保存)するには、次のようになります。

// Class member variables
private Calendar myCalendar = Calendar.getInstance();
private boolean birthday_is_set = false;


// this next part is in onCreate

// set the calendar date to a saved date if applicable
// and change birthday_is_set if they had saved a birthday


final DatePickerDialog.OnDateSetListener birthdayListener = new DatePickerDialog.OnDateSetListener() {

    @Override
    public void onDateSet(DatePicker view, int year, int monthOfYear,
                          int dayOfMonth) {
        // I save the date in a calendar, replace this
        // with whatever you want to do with the selected date
        myCalendar.set(Calendar.YEAR, year);
        myCalendar.set(Calendar.MONTH, monthOfYear);
        myCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        birthday_is_set = true;
        updateBirthdayLabel();
    }
};

if (savedInstanceState != null) {
    DatePickerDialogFragment dpf;

    dpf = (DatePickerDialogFragment) getFragmentManager().findFragmentByTag("birthdayDatePicker");
    if (dpf != null) {
        // on rotation the listener will be referring to the old Activity,
        // so we have to reset it here to act on the current Activity
        dpf.setListener(birthdayListener);
    }
}

birthdayDatePicker.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // Your logic may vary here. I chose not to start it in year
        // mode if they've already selected a date.
        boolean startInYears = !birthday_is_set;
        DatePickerDialogFragment dpf = DatePickerDialogFragment.newInstance(startInYears, myCalendar);
        dpf.setListener(birthdayListener);
        dpf.show(getFragmentManager(), "birthdayDatePicker");
    }
});

これは、年モードで起動するために取得するハック、および特定のヴィンテージのサムスンのデバイス上でいくつかのランダムな日付ピッカーの障害の修正の両方を含んでいます。このバージョンでは、ここ数ヶ月のために15+ APIのためにクラッシュしたり、ユーザーからの苦情なしに取り組んできました。

EDIT:アンドロイド10上で動作するようにopenYearView更新しました

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=219417&siteId=1