1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.ui.preference;
18 
19 import android.app.AlertDialog;
20 import android.content.DialogInterface;
21 import android.graphics.Bitmap;
22 import android.graphics.Canvas;
23 import android.graphics.drawable.BitmapDrawable;
24 import android.graphics.drawable.Drawable;
25 import android.os.Bundle;
26 
27 import androidx.annotation.Nullable;
28 import androidx.fragment.app.Fragment;
29 import androidx.preference.DialogPreference;
30 import androidx.preference.PreferenceFragmentCompat;
31 
32 /**
33  * Abstract base class which presents a dialog associated with a {@link
34  * androidx.preference.DialogPreference}. Since the preference object may not be available during
35  * fragment re-creation, the necessary information for displaying the dialog is read once during
36  * the initial call to {@link #onCreate(Bundle)} and saved/restored in the saved instance state.
37  * Custom subclasses should also follow this pattern.
38  *
39  * <p>Note: this has the same functionality and interface as {@link
40  * androidx.preference.PreferenceDialogFragmentCompat} with updates to formatting to match the
41  * project style. This class preserves the {@link DialogPreference.TargetFragment} interface
42  * requirement that was removed in {@link CarUiDialogFragment}. Automotive applications should use
43  * children of this fragment in order to launch the system themed platform {@link AlertDialog}
44  * instead of the one in the support library.
45  */
46 public abstract class PreferenceDialogFragment extends CarUiDialogFragment implements
47         DialogInterface.OnClickListener {
48 
49     protected static final String ARG_KEY = "key";
50 
51     private DialogPreference mPreference;
52 
53     @Override
onCreate(@ullable Bundle savedInstanceState)54     public void onCreate(@Nullable Bundle savedInstanceState) {
55         super.onCreate(savedInstanceState);
56 
57         Fragment rawFragment = getTargetFragment();
58         if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
59             throw new IllegalStateException(
60                     "Target fragment must implement TargetFragment interface");
61         }
62 
63         DialogPreference.TargetFragment fragment =
64                 (DialogPreference.TargetFragment) rawFragment;
65 
66         String key = getArguments().getString(ARG_KEY);
67         if (savedInstanceState == null) {
68             mPreference = (DialogPreference) fragment.findPreference(key);
69             mDialogTitle = mPreference.getDialogTitle();
70             mPositiveButtonText = mPreference.getPositiveButtonText();
71             mNegativeButtonText = mPreference.getNegativeButtonText();
72             mDialogMessage = mPreference.getDialogMessage();
73             mDialogLayoutRes = mPreference.getDialogLayoutResource();
74 
75             Drawable icon = mPreference.getDialogIcon();
76             if (icon == null || icon instanceof BitmapDrawable) {
77                 mDialogIcon = (BitmapDrawable) icon;
78             } else {
79                 Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(),
80                         icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
81                 Canvas canvas = new Canvas(bitmap);
82                 icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
83                 icon.draw(canvas);
84                 mDialogIcon = new BitmapDrawable(getResources(), bitmap);
85             }
86         }
87     }
88 
89     /**
90      * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has
91      * been called on the {@link PreferenceFragmentCompat} which launched this dialog.
92      *
93      * @return the {@link DialogPreference} associated with this dialog.
94      */
getPreference()95     public DialogPreference getPreference() {
96         if (mPreference == null) {
97             String key = getArguments().getString(ARG_KEY);
98             DialogPreference.TargetFragment fragment =
99                     (DialogPreference.TargetFragment) getTargetFragment();
100             mPreference = (DialogPreference) fragment.findPreference(key);
101         }
102         return mPreference;
103     }
104 }
105