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