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.fragment.app.Fragment;
28 import androidx.preference.DialogPreference;
29 import androidx.preference.PreferenceFragmentCompat;
30 
31 /**
32  * Abstract base class which presents a dialog associated with a {@link
33  * androidx.preference.DialogPreference}. Since the preference object may not be available during
34  * fragment re-creation, the necessary information for displaying the dialog is read once during
35  * the initial call to {@link #onCreate(Bundle)} and saved/restored in the saved instance state.
36  * Custom subclasses should also follow this pattern.
37  *
38  * <p>Note: this has the same functionality and interface as {@link
39  * androidx.preference.PreferenceDialogFragmentCompat} with updates to formatting to match the
40  * project style. This class preserves the {@link DialogPreference.TargetFragment} interface
41  * requirement that was removed in {@link CarUiDialogFragment}. Automotive applications should use
42  * children of this fragment in order to launch the system themed platform {@link AlertDialog}
43  * instead of the one in the support library.
44  */
45 public abstract class PreferenceDialogFragment extends CarUiDialogFragment implements
46         DialogInterface.OnClickListener {
47 
48     protected static final String ARG_KEY = "key";
49 
50     private DialogPreference mPreference;
51 
52     @Override
onCreate(Bundle savedInstanceState)53     public void onCreate(Bundle savedInstanceState) {
54         super.onCreate(savedInstanceState);
55 
56         Fragment rawFragment = getTargetFragment();
57         if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
58             throw new IllegalStateException(
59                     "Target fragment must implement TargetFragment interface");
60         }
61 
62         DialogPreference.TargetFragment fragment =
63                 (DialogPreference.TargetFragment) rawFragment;
64 
65         String key = getArguments().getString(ARG_KEY);
66         if (savedInstanceState == null) {
67             mPreference = (DialogPreference) fragment.findPreference(key);
68             mDialogTitle = mPreference.getDialogTitle();
69             mPositiveButtonText = mPreference.getPositiveButtonText();
70             mNegativeButtonText = mPreference.getNegativeButtonText();
71             mDialogMessage = mPreference.getDialogMessage();
72             mDialogLayoutRes = mPreference.getDialogLayoutResource();
73 
74             Drawable icon = mPreference.getDialogIcon();
75             if (icon == null || icon instanceof BitmapDrawable) {
76                 mDialogIcon = (BitmapDrawable) icon;
77             } else {
78                 Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(),
79                         icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
80                 Canvas canvas = new Canvas(bitmap);
81                 icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
82                 icon.draw(canvas);
83                 mDialogIcon = new BitmapDrawable(getResources(), bitmap);
84             }
85         }
86     }
87 
88     /**
89      * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has
90      * been called on the {@link PreferenceFragmentCompat} which launched this dialog.
91      *
92      * @return the {@link DialogPreference} associated with this dialog.
93      */
getPreference()94     public DialogPreference getPreference() {
95         if (mPreference == null) {
96             String key = getArguments().getString(ARG_KEY);
97             DialogPreference.TargetFragment fragment =
98                     (DialogPreference.TargetFragment) getTargetFragment();
99             mPreference = (DialogPreference) fragment.findPreference(key);
100         }
101         return mPreference;
102     }
103 }
104