ZenFooter.java revision f88d8082a86bee00c604cbbcfb5261f5573936fe
1f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock/*
2f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Copyright (C) 2015 The Android Open Source Project
3f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *
4f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
5f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * you may not use this file except in compliance with the License.
6f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * You may obtain a copy of the License at
7f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *
8f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
9f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock *
10f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Unless required by applicable law or agreed to in writing, software
11f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
12f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * See the License for the specific language governing permissions and
14f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * limitations under the License.
15f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock */
16f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockpackage com.android.systemui.volume;
17f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
18f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.animation.LayoutTransition;
19f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.animation.ValueAnimator;
20f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.Context;
21f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.res.Resources;
22f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.provider.Settings.Global;
23f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.service.notification.Condition;
24f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.util.AttributeSet;
25f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.util.Log;
26f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.util.TypedValue;
27f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.view.View;
28f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.widget.CompoundButton;
29f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.widget.CompoundButton.OnCheckedChangeListener;
30f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.widget.LinearLayout;
31f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.widget.Switch;
32f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.widget.TextView;
33f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
34f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport com.android.systemui.R;
35f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport com.android.systemui.statusbar.policy.ZenModeController;
36f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
37f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock/**
38f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Switch bar + zen mode panel (conditions) attached to the bottom of the volume dialog.
39f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock */
40f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockpublic class ZenFooter extends LinearLayout {
41f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private static final String TAG = Util.logTag(ZenFooter.class);
42f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
43f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final Context mContext;
44f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final float mSecondaryAlpha;
45f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final LayoutTransition mLayoutTransition;
46f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
47f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private ZenModeController mController;
48f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private Switch mSwitch;
49f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private ZenModePanel mZenModePanel;
50f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private View mZenModePanelButtons;
51f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private View mZenModePanelMoreButton;
52f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private View mZenModePanelDoneButton;
53f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private View mSwitchBar;
54f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private View mSwitchBarIcon;
55f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private View mSummary;
56f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private TextView mSummaryLine1;
57f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private TextView mSummaryLine2;
58f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean mFooterExpanded;
59f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private int mZen = -1;
60f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private Callback mCallback;
61f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
62f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public ZenFooter(Context context, AttributeSet attrs) {
63f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        super(context, attrs);
64f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mContext = context;
65f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSecondaryAlpha = getFloat(context.getResources(), R.dimen.volume_secondary_alpha);
66f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mLayoutTransition = new LayoutTransition();
67f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mLayoutTransition.setDuration(new ValueAnimator().getDuration() / 2);
68f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mLayoutTransition.disableTransitionType(LayoutTransition.DISAPPEARING);
69f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
70f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
71f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
72f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private static float getFloat(Resources r, int resId) {
73f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final TypedValue tv = new TypedValue();
74f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        r.getValue(resId, tv, true);
75f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return tv.getFloat();
76f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
77f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
78f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    @Override
79f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    protected void onFinishInflate() {
80f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        super.onFinishInflate();
81f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitchBar = findViewById(R.id.volume_zen_switch_bar);
82f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitchBarIcon = findViewById(R.id.volume_zen_switch_bar_icon);
83f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitch = (Switch) findViewById(R.id.volume_zen_switch);
84f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZenModePanel = (ZenModePanel) findViewById(R.id.zen_mode_panel);
85f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZenModePanelButtons = findViewById(R.id.volume_zen_mode_panel_buttons);
86f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZenModePanelMoreButton = findViewById(R.id.volume_zen_mode_panel_more);
87f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZenModePanelDoneButton = findViewById(R.id.volume_zen_mode_panel_done);
88f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSummary = findViewById(R.id.volume_zen_panel_summary);
89f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSummaryLine1 = (TextView) findViewById(R.id.volume_zen_panel_summary_line_1);
90f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSummaryLine2 = (TextView) findViewById(R.id.volume_zen_panel_summary_line_2);
91f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
92f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
93f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void init(ZenModeController controller, Callback callback) {
94f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mCallback = callback;
95f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mController = controller;
96f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZenModePanel.init(controller);
97f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZenModePanel.setEmbedded(true);
98f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitch.setOnCheckedChangeListener(mCheckedListener);
99f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mController.addCallback(new ZenModeController.Callback() {
100f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            @Override
101f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            public void onZenChanged(int zen) {
102f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                setZen(zen);
103f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
104f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            @Override
105f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            public void onExitConditionChanged(Condition exitCondition) {
106f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                update();
107f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
108f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        });
109f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitchBar.setOnClickListener(new OnClickListener() {
110f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            @Override
111f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            public void onClick(View v) {
112f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mSwitch.setChecked(!mSwitch.isChecked());
113f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
114f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        });
115f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZenModePanelMoreButton.setOnClickListener(new OnClickListener() {
116f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            @Override
117f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            public void onClick(View v) {
118f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (mCallback != null) {
119f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    mCallback.onSettingsClicked();
120f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                }
121f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
122f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        });
123f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZenModePanelDoneButton.setOnClickListener(new OnClickListener() {
124f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            @Override
125f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            public void onClick(View v) {
126f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                if (mCallback != null) {
127f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                    mCallback.onDoneClicked();
128f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                }
129f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
130f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        });
131f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZen = mController.getZen();
132f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        update();
133f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
134f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
135f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private void setZen(int zen) {
136f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mZen == zen) return;
137f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mZen = zen;
138f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        update();
139f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
140f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
141f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public boolean isZen() {
142f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return isZenPriority() || isZenNone();
143f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
144f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
145f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean isZenPriority() {
146f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return mZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
147f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
148f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
149f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean isZenNone() {
150f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return mZen == Global.ZEN_MODE_NO_INTERRUPTIONS;
151f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
152f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
153f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    @Override
154f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    protected void onDetachedFromWindow() {
155f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        super.onDetachedFromWindow();
156f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        setLayoutTransition(null);
157f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        setFooterExpanded(false);
158f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
159f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
160f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    @Override
161f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    protected void onAttachedToWindow() {
162f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        super.onAttachedToWindow();
163f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        setLayoutTransition(mLayoutTransition);
164f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
165f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
166f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private boolean setFooterExpanded(boolean expanded) {
167f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mFooterExpanded == expanded) return false;
168f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mFooterExpanded = expanded;
169f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        update();
170f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        if (mCallback != null) {
171f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            mCallback.onFooterExpanded();
172f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
173f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return true;
174f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
175f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
176f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public boolean isFooterExpanded() {
177f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        return mFooterExpanded;
178f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
179f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
180f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public void update() {
181f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final boolean isZen = isZen();
182f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitch.setOnCheckedChangeListener(null);
183f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitch.setChecked(isZen);
184f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitch.setOnCheckedChangeListener(mCheckedListener);
185f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        Util.setVisOrGone(mZenModePanel, isZen && mFooterExpanded);
186f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        Util.setVisOrGone(mZenModePanelButtons, isZen && mFooterExpanded);
187f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        Util.setVisOrGone(mSummary, isZen && !mFooterExpanded);
188f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        mSwitchBarIcon.setAlpha(isZen ? 1 : mSecondaryAlpha);
189f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        final String line1 =
190f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                isZenPriority() ? mContext.getString(R.string.interruption_level_priority)
191f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                : isZenNone() ? mContext.getString(R.string.interruption_level_none)
192f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                : null;
193f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        Util.setText(mSummaryLine1, line1);
194f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        Util.setText(mSummaryLine2, mZenModePanel.getExitConditionText());
195f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
196f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
197f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    private final OnCheckedChangeListener mCheckedListener = new OnCheckedChangeListener() {
198f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        @Override
199f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
200f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (D.BUG) Log.d(TAG, "onCheckedChanged " + isChecked);
201f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            if (isChecked != isZen()) {
202f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                final int newZen = isChecked ? Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
203f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                        : Global.ZEN_MODE_OFF;
204f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mZen = newZen;  // this one's optimistic
205f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                setFooterExpanded(isChecked);
206f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock                mController.setZen(newZen);
207f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock            }
208f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        }
209f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    };
210f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock
211f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    public interface Callback {
212f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        void onFooterExpanded();
213f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        void onSettingsClicked();
214f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock        void onDoneClicked();
215f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock    }
216f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock}
217