1d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam/* 2d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * Copyright (C) 2017 The Android Open Source Project 3d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * 4d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * Licensed under the Apache License, Version 2.0 (the "License"); 5d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * you may not use this file except in compliance with the License. 6d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * You may obtain a copy of the License at 7d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * 8d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * http://www.apache.org/licenses/LICENSE-2.0 9d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * 10d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * Unless required by applicable law or agreed to in writing, software 11d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * distributed under the License is distributed on an "AS IS" BASIS, 12d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * See the License for the specific language governing permissions and 14d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * limitations under the License. 15d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 16d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 17d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lampackage com.android.setupwizardlib.template; 18d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 19d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.content.Context; 20d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.content.res.TypedArray; 21d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.graphics.drawable.Drawable; 22d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.os.Build; 23d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.os.Build.VERSION_CODES; 24d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.support.annotation.AttrRes; 25d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.support.annotation.NonNull; 26d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.support.annotation.Nullable; 27d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.util.AttributeSet; 28d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.view.View; 29d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.widget.HeaderViewListAdapter; 30d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.widget.ListAdapter; 31d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport android.widget.ListView; 32d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 33d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport com.android.setupwizardlib.R; 34d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport com.android.setupwizardlib.TemplateLayout; 35d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport com.android.setupwizardlib.items.ItemAdapter; 36d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport com.android.setupwizardlib.items.ItemGroup; 37d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport com.android.setupwizardlib.items.ItemInflater; 38d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lamimport com.android.setupwizardlib.util.DrawableLayoutDirectionHelper; 39d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 40d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam/** 41d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * A {@link Mixin} for interacting with ListViews. 42d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 43d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lampublic class ListMixin implements Mixin { 44d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 45d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam private TemplateLayout mTemplateLayout; 46d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 47d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam @Nullable 48d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam private ListView mListView; 49d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 50d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam private Drawable mDivider; 51d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam private Drawable mDefaultDivider; 526011b35deae30839cd454e0ec5866487e90860f5Maurice Lam 536011b35deae30839cd454e0ec5866487e90860f5Maurice Lam private int mDividerInsetStart; 546011b35deae30839cd454e0ec5866487e90860f5Maurice Lam private int mDividerInsetEnd; 55d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 56d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam /** 57d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * @param layout The layout this mixin belongs to. 58d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 59d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam public ListMixin(@NonNull TemplateLayout layout, @Nullable AttributeSet attrs, 60d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam @AttrRes int defStyleAttr) { 61d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam mTemplateLayout = layout; 62d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 63d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final Context context = layout.getContext(); 64d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final TypedArray a = context.obtainStyledAttributes( 65d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam attrs, R.styleable.SuwListMixin, defStyleAttr, 0); 66d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 67d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final int entries = a.getResourceId(R.styleable.SuwListMixin_android_entries, 0); 68d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (entries != 0) { 69d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final ItemGroup inflated = 70d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam (ItemGroup) new ItemInflater(context).inflate(entries); 71d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam setAdapter(new ItemAdapter(inflated)); 72d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 73d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam int dividerInset = 746011b35deae30839cd454e0ec5866487e90860f5Maurice Lam a.getDimensionPixelSize(R.styleable.SuwListMixin_suwDividerInset, -1); 756011b35deae30839cd454e0ec5866487e90860f5Maurice Lam if (dividerInset != -1) { 766011b35deae30839cd454e0ec5866487e90860f5Maurice Lam setDividerInset(dividerInset); 776011b35deae30839cd454e0ec5866487e90860f5Maurice Lam } else { 786011b35deae30839cd454e0ec5866487e90860f5Maurice Lam int dividerInsetStart = 796011b35deae30839cd454e0ec5866487e90860f5Maurice Lam a.getDimensionPixelSize(R.styleable.SuwListMixin_suwDividerInsetStart, 0); 806011b35deae30839cd454e0ec5866487e90860f5Maurice Lam int dividerInsetEnd = 816011b35deae30839cd454e0ec5866487e90860f5Maurice Lam a.getDimensionPixelSize(R.styleable.SuwListMixin_suwDividerInsetEnd, 0); 826011b35deae30839cd454e0ec5866487e90860f5Maurice Lam setDividerInsets(dividerInsetStart, dividerInsetEnd); 836011b35deae30839cd454e0ec5866487e90860f5Maurice Lam } 84d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam a.recycle(); 85d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 86d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 87d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam /** 88d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * @return The list view contained in the layout, as marked by {@code @android:id/list}. This 89d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * will return {@code null} if the list doesn't exist in the layout. 90d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 91d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam public ListView getListView() { 92d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam return getListViewInternal(); 93d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 94d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 95d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam // Client code can assume getListView() will not be null if they know their template contains 96d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam // the list, but this mixin cannot. Any usages of getListView in this mixin needs null checks. 97d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam @Nullable 98d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam private ListView getListViewInternal() { 99d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (mListView == null) { 100d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final View list = mTemplateLayout.findManagedViewById(android.R.id.list); 101d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (list instanceof ListView) { 102d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam mListView = (ListView) list; 103d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 104d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 105d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam return mListView; 106d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 107d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 108d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam /** 109d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * List mixin needs to update the dividers if the layout direction has changed. This method 110d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * should be called when {@link View#onLayout(boolean, int, int, int, int)} of the template 111d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * is called. 112d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 113d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam public void onLayout() { 114d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (mDivider == null) { 115d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam // Update divider in case layout direction has just been resolved 116d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam updateDivider(); 117d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 118d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 119d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 120d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam /** 121d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * Gets the adapter of the list view in this layout. If the adapter is a HeaderViewListAdapter, 122d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * this method will unwrap it and return the underlying adapter. 123d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * 124d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * @return The adapter, or {@code null} if there is no list, or if the list has no adapter. 125d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 126d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam public ListAdapter getAdapter() { 127d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final ListView listView = getListViewInternal(); 128d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (listView != null) { 129d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final ListAdapter adapter = listView.getAdapter(); 130d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (adapter instanceof HeaderViewListAdapter) { 131d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam return ((HeaderViewListAdapter) adapter).getWrappedAdapter(); 132d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 133d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam return adapter; 134d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 135d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam return null; 136d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 137d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 138d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam /** 139d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * Sets the adapter on the list view in this layout. 140d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 141d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam public void setAdapter(ListAdapter adapter) { 142d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final ListView listView = getListViewInternal(); 143d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (listView != null) { 144d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam listView.setAdapter(adapter); 145d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 146d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 147d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 148d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam /** 1496011b35deae30839cd454e0ec5866487e90860f5Maurice Lam * @deprecated Use {@link #setDividerInsets(int, int)} instead. 1506011b35deae30839cd454e0ec5866487e90860f5Maurice Lam */ 1516011b35deae30839cd454e0ec5866487e90860f5Maurice Lam @Deprecated 1526011b35deae30839cd454e0ec5866487e90860f5Maurice Lam public void setDividerInset(int inset) { 1536011b35deae30839cd454e0ec5866487e90860f5Maurice Lam setDividerInsets(inset, 0); 1546011b35deae30839cd454e0ec5866487e90860f5Maurice Lam } 1556011b35deae30839cd454e0ec5866487e90860f5Maurice Lam 1566011b35deae30839cd454e0ec5866487e90860f5Maurice Lam /** 157d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * Sets the start inset of the divider. This will use the default divider drawable set in the 1586011b35deae30839cd454e0ec5866487e90860f5Maurice Lam * theme and apply insets to it. 159d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * 1606011b35deae30839cd454e0ec5866487e90860f5Maurice Lam * @param start The number of pixels to inset on the "start" side of the list divider. Typically 161d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * this will be either {@code @dimen/suw_items_glif_icon_divider_inset} or 162d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * {@code @dimen/suw_items_glif_text_divider_inset}. 1636011b35deae30839cd454e0ec5866487e90860f5Maurice Lam * @param end The number of pixels to inset on the "end" side of the list divider. 164d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 1656011b35deae30839cd454e0ec5866487e90860f5Maurice Lam public void setDividerInsets(int start, int end) { 1666011b35deae30839cd454e0ec5866487e90860f5Maurice Lam mDividerInsetStart = start; 1676011b35deae30839cd454e0ec5866487e90860f5Maurice Lam mDividerInsetEnd = end; 168d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam updateDivider(); 169d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 170d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 171d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam /** 172d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * @return The number of pixels inset on the start side of the divider. 1736011b35deae30839cd454e0ec5866487e90860f5Maurice Lam * @deprecated This is the same as {@link #getDividerInsetStart()}. Use that instead. 174d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 1756011b35deae30839cd454e0ec5866487e90860f5Maurice Lam @Deprecated 176d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam public int getDividerInset() { 1776011b35deae30839cd454e0ec5866487e90860f5Maurice Lam return getDividerInsetStart(); 1786011b35deae30839cd454e0ec5866487e90860f5Maurice Lam } 1796011b35deae30839cd454e0ec5866487e90860f5Maurice Lam 1806011b35deae30839cd454e0ec5866487e90860f5Maurice Lam /** 1816011b35deae30839cd454e0ec5866487e90860f5Maurice Lam * @return The number of pixels inset on the start side of the divider. 1826011b35deae30839cd454e0ec5866487e90860f5Maurice Lam */ 1836011b35deae30839cd454e0ec5866487e90860f5Maurice Lam public int getDividerInsetStart() { 1846011b35deae30839cd454e0ec5866487e90860f5Maurice Lam return mDividerInsetStart; 1856011b35deae30839cd454e0ec5866487e90860f5Maurice Lam } 1866011b35deae30839cd454e0ec5866487e90860f5Maurice Lam 1876011b35deae30839cd454e0ec5866487e90860f5Maurice Lam /** 1886011b35deae30839cd454e0ec5866487e90860f5Maurice Lam * @return The number of pixels inset on the end side of the divider. 1896011b35deae30839cd454e0ec5866487e90860f5Maurice Lam */ 1906011b35deae30839cd454e0ec5866487e90860f5Maurice Lam public int getDividerInsetEnd() { 1916011b35deae30839cd454e0ec5866487e90860f5Maurice Lam return mDividerInsetEnd; 192d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 193d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 194d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam private void updateDivider() { 195d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam final ListView listView = getListViewInternal(); 196d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (listView == null) { 197d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam return; 198d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 199d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam boolean shouldUpdate = true; 200d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT) { 201d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam shouldUpdate = mTemplateLayout.isLayoutDirectionResolved(); 202d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 203d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (shouldUpdate) { 204d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam if (mDefaultDivider == null) { 205d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam mDefaultDivider = listView.getDivider(); 206d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 207d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam mDivider = DrawableLayoutDirectionHelper.createRelativeInsetDrawable( 208d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam mDefaultDivider, 2096011b35deae30839cd454e0ec5866487e90860f5Maurice Lam mDividerInsetStart /* start */, 210d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 0 /* top */, 2116011b35deae30839cd454e0ec5866487e90860f5Maurice Lam mDividerInsetEnd /* end */, 212d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 0 /* bottom */, 213d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam mTemplateLayout); 214d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam listView.setDivider(mDivider); 215d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 216d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 217d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam 218d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam /** 219d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam * @return The drawable used as the divider. 220d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam */ 221d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam public Drawable getDivider() { 222d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam return mDivider; 223d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam } 224d349adb3941c88ae27ec451acd19641ba03205dfMaurice Lam} 225