1/*
2 * Copyright (C) 2017 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
17package com.android.setupwizardlib.items;
18
19import android.content.Context;
20import android.content.res.ColorStateList;
21import android.content.res.TypedArray;
22import android.graphics.PorterDuff.Mode;
23import android.graphics.drawable.Drawable;
24import android.os.Build.VERSION;
25import android.os.Build.VERSION_CODES;
26import android.util.AttributeSet;
27import android.view.View;
28import android.view.View.OnClickListener;
29import android.widget.CompoundButton.OnCheckedChangeListener;
30import android.widget.TextView;
31
32import com.android.setupwizardlib.R;
33import com.android.setupwizardlib.view.CheckableLinearLayout;
34
35/**
36 * A switch item which is divided into two parts: the start (left for LTR) side shows the title and
37 * summary, and when that is clicked, will expand to show a longer summary. The end (right for LTR)
38 * side is a switch which can be toggled by the user.
39 *
40 * Note: It is highly recommended to use this item with recycler view rather than list view, because
41 * list view draws the touch ripple effect on top of the item, rather than letting the item handle
42 * it. Therefore you might see a double-ripple, one for the expandable area and one for the entire
43 * list item, when using this in list view.
44 */
45public class ExpandableSwitchItem extends SwitchItem
46        implements OnCheckedChangeListener, OnClickListener {
47
48    private CharSequence mCollapsedSummary;
49    private CharSequence mExpandedSummary;
50    private boolean mIsExpanded = false;
51
52    public ExpandableSwitchItem() {
53        super();
54    }
55
56    public ExpandableSwitchItem(Context context, AttributeSet attrs) {
57        super(context, attrs);
58        final TypedArray a =
59                context.obtainStyledAttributes(attrs, R.styleable.SuwExpandableSwitchItem);
60        mCollapsedSummary = a.getText(R.styleable.SuwExpandableSwitchItem_suwCollapsedSummary);
61        mExpandedSummary = a.getText(R.styleable.SuwExpandableSwitchItem_suwExpandedSummary);
62        a.recycle();
63    }
64
65    @Override
66    protected int getDefaultLayoutResource() {
67        return R.layout.suw_items_expandable_switch;
68    }
69
70    @Override
71    public CharSequence getSummary() {
72        return mIsExpanded ? getExpandedSummary() : getCollapsedSummary();
73    }
74
75    /**
76     * @return True if the item is currently expanded.
77     */
78    public boolean isExpanded() {
79        return mIsExpanded;
80    }
81
82    /**
83     * Sets whether the item should be expanded.
84     */
85    public void setExpanded(boolean expanded) {
86        if (mIsExpanded == expanded) {
87            return;
88        }
89        mIsExpanded = expanded;
90        notifyItemChanged();
91    }
92
93    /**
94     * @return The summary shown when in collapsed state.
95     */
96    public CharSequence getCollapsedSummary() {
97        return mCollapsedSummary;
98    }
99
100    /**
101     * Sets the summary text shown when the item is collapsed. Corresponds to the
102     * {@code app:suwCollapsedSummary} XML attribute.
103     */
104    public void setCollapsedSummary(CharSequence collapsedSummary) {
105        mCollapsedSummary = collapsedSummary;
106        if (!isExpanded()) {
107            notifyChanged();
108        }
109    }
110
111    /**
112     * @return The summary shown when in expanded state.
113     */
114    public CharSequence getExpandedSummary() {
115        return mExpandedSummary;
116    }
117
118    /**
119     * Sets the summary text shown when the item is expanded. Corresponds to the
120     * {@code app:suwExpandedSummary} XML attribute.
121     */
122    public void setExpandedSummary(CharSequence expandedSummary) {
123        mExpandedSummary = expandedSummary;
124        if (isExpanded()) {
125            notifyChanged();
126        }
127    }
128
129    @Override
130    public void onBindView(View view) {
131        // TODO: If it is possible to detect, log a warning if this is being used with ListView.
132        super.onBindView(view);
133        View content = view.findViewById(R.id.suw_items_expandable_switch_content);
134        content.setOnClickListener(this);
135
136        if (content instanceof CheckableLinearLayout) {
137            ((CheckableLinearLayout) content).setChecked(isExpanded());
138        }
139
140        tintCompoundDrawables(view);
141
142        // Expandable switch item has focusability on the expandable layout on the left, and the
143        // switch on the right, but not the item itself.
144        view.setFocusable(false);
145    }
146
147    @Override
148    public void onClick(View v) {
149        setExpanded(!isExpanded());
150    }
151
152    // Tint the expand arrow with the text color
153    private void tintCompoundDrawables(View view) {
154        final TypedArray a = view.getContext()
155                .obtainStyledAttributes(new int[] {android.R.attr.textColorPrimary});
156        final ColorStateList tintColor = a.getColorStateList(0);
157        a.recycle();
158
159        if (tintColor != null) {
160            TextView titleView = (TextView) view.findViewById(R.id.suw_items_title);
161            for (Drawable drawable : titleView.getCompoundDrawables()) {
162                if (drawable != null) {
163                    drawable.setColorFilter(tintColor.getDefaultColor(), Mode.SRC_IN);
164                }
165            }
166            if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
167                for (Drawable drawable : titleView.getCompoundDrawablesRelative()) {
168                    if (drawable != null) {
169                        drawable.setColorFilter(tintColor.getDefaultColor(), Mode.SRC_IN);
170                    }
171                }
172            }
173
174        }
175    }
176}
177