1f933672168f6deff5e3636584bec735416b5a93bChris Banes/* 2f933672168f6deff5e3636584bec735416b5a93bChris Banes * Copyright (C) 2015 The Android Open Source Project 3f933672168f6deff5e3636584bec735416b5a93bChris Banes * 4f933672168f6deff5e3636584bec735416b5a93bChris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 5f933672168f6deff5e3636584bec735416b5a93bChris Banes * you may not use this file except in compliance with the License. 6f933672168f6deff5e3636584bec735416b5a93bChris Banes * You may obtain a copy of the License at 7f933672168f6deff5e3636584bec735416b5a93bChris Banes * 8f933672168f6deff5e3636584bec735416b5a93bChris Banes * http://www.apache.org/licenses/LICENSE-2.0 9f933672168f6deff5e3636584bec735416b5a93bChris Banes * 10f933672168f6deff5e3636584bec735416b5a93bChris Banes * Unless required by applicable law or agreed to in writing, software 11f933672168f6deff5e3636584bec735416b5a93bChris Banes * distributed under the License is distributed on an "AS IS" BASIS, 12f933672168f6deff5e3636584bec735416b5a93bChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f933672168f6deff5e3636584bec735416b5a93bChris Banes * See the License for the specific language governing permissions and 14f933672168f6deff5e3636584bec735416b5a93bChris Banes * limitations under the License. 15f933672168f6deff5e3636584bec735416b5a93bChris Banes */ 16f933672168f6deff5e3636584bec735416b5a93bChris Banes 17f933672168f6deff5e3636584bec735416b5a93bChris Banespackage android.support.v7.widget; 18f933672168f6deff5e3636584bec735416b5a93bChris Banes 19f933672168f6deff5e3636584bec735416b5a93bChris Banes 2010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banesimport android.content.Context; 21f933672168f6deff5e3636584bec735416b5a93bChris Banesimport android.content.res.Resources; 22f933672168f6deff5e3636584bec735416b5a93bChris Banesimport android.content.res.Resources.Theme; 2310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banesimport android.support.annotation.NonNull; 24f933672168f6deff5e3636584bec735416b5a93bChris Banesimport android.support.annotation.Nullable; 2510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banesimport android.support.v7.internal.view.ContextThemeWrapper; 2610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banesimport android.view.LayoutInflater; 27f933672168f6deff5e3636584bec735416b5a93bChris Banesimport android.view.View; 28f933672168f6deff5e3636584bec735416b5a93bChris Banesimport android.view.ViewGroup; 29f933672168f6deff5e3636584bec735416b5a93bChris Banesimport android.widget.SpinnerAdapter; 30f933672168f6deff5e3636584bec735416b5a93bChris Banes 31f933672168f6deff5e3636584bec735416b5a93bChris Banes/** 32f933672168f6deff5e3636584bec735416b5a93bChris Banes * An extension of SpinnerAdapter that is capable of inflating drop-down views 33f933672168f6deff5e3636584bec735416b5a93bChris Banes * against a different theme than normal views. 34f933672168f6deff5e3636584bec735416b5a93bChris Banes * <p> 35f933672168f6deff5e3636584bec735416b5a93bChris Banes * Classes that implement this interface should use the theme provided to 36f933672168f6deff5e3636584bec735416b5a93bChris Banes * {@link #setDropDownViewTheme(Theme)} when creating views in 37f933672168f6deff5e3636584bec735416b5a93bChris Banes * {@link SpinnerAdapter#getDropDownView(int, View, ViewGroup)}. 3810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 3910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * <p>The {@link Helper} class is provided to aide implementation in a backwards compatible way. 4010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * </p> 41f933672168f6deff5e3636584bec735416b5a93bChris Banes */ 42f933672168f6deff5e3636584bec735416b5a93bChris Banespublic interface ThemedSpinnerAdapter extends SpinnerAdapter { 43f933672168f6deff5e3636584bec735416b5a93bChris Banes /** 44f933672168f6deff5e3636584bec735416b5a93bChris Banes * Sets the {@link Resources.Theme} against which drop-down views are 45f933672168f6deff5e3636584bec735416b5a93bChris Banes * inflated. 46f933672168f6deff5e3636584bec735416b5a93bChris Banes * 47f933672168f6deff5e3636584bec735416b5a93bChris Banes * @param theme the context against which to inflate drop-down views, or 48f933672168f6deff5e3636584bec735416b5a93bChris Banes * {@code null} to use the default theme 49f933672168f6deff5e3636584bec735416b5a93bChris Banes * @see SpinnerAdapter#getDropDownView(int, View, ViewGroup) 50f933672168f6deff5e3636584bec735416b5a93bChris Banes */ 51f933672168f6deff5e3636584bec735416b5a93bChris Banes void setDropDownViewTheme(@Nullable Resources.Theme theme); 52f933672168f6deff5e3636584bec735416b5a93bChris Banes 53f933672168f6deff5e3636584bec735416b5a93bChris Banes /** 54f933672168f6deff5e3636584bec735416b5a93bChris Banes * Returns the value previously set by a call to 55f933672168f6deff5e3636584bec735416b5a93bChris Banes * {@link #setDropDownViewTheme(Theme)}. 56f933672168f6deff5e3636584bec735416b5a93bChris Banes * 57f933672168f6deff5e3636584bec735416b5a93bChris Banes * @return the {@link Resources.Theme} against which drop-down views are 58f933672168f6deff5e3636584bec735416b5a93bChris Banes * inflated, or {@code null} if one has not been explicitly set 59f933672168f6deff5e3636584bec735416b5a93bChris Banes */ 60f933672168f6deff5e3636584bec735416b5a93bChris Banes @Nullable 61f933672168f6deff5e3636584bec735416b5a93bChris Banes Resources.Theme getDropDownViewTheme(); 6210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes 6310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes /** 6410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * A helper class which allows easy integration of {@link ThemedSpinnerAdapter} into existing 6510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * {@link SpinnerAdapter}s in a backwards compatible way. 6610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 6710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * <p>An example {@link android.widget.BaseAdapter BaseAdapter} implementation would be:</p> 6810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 6910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * <pre> 7010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * public class MyAdapter extends BaseAdapter implements ThemedSpinnerAdapter { 7110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * private final ThemedSpinnerAdapter.Helper mDropDownHelper; 7210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 7310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * public CheeseAdapter(Context context) { 7410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * mDropDownHelper = new ThemedSpinnerAdapter.Helper(context); 7510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * // ... 7610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * } 7710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 7810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * @Override 7910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * public View getDropDownView(int position, View convertView, ViewGroup parent) { 8010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * View view; 8110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 8210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * if (convertView == null) { 8310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * // Inflate the drop down using the helper's LayoutInflater 8410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * LayoutInflater inflater = mDropDownHelper.getDropDownViewInflater(); 8510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * view = inflater.inflate(R.layout.my_dropdown, parent, false); 8610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * } 8710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 8810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * // ... 8910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * } 9010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 9110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * @Override 9210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * public void setDropDownViewTheme(@Nullable Resources.Theme theme) { 9310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * // Pass the new theme to the helper 9410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * mDropDownHelper.setDropDownViewTheme(theme); 9510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * } 9610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 9710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * @Override 9810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * public Resources.Theme getDropDownViewTheme() { 9910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * // Return the helper's value 10010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * return mDropDownHelper.getDropDownViewTheme(); 10110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * } 10210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * } 10310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * </pre> 10410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes */ 10510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes public final static class Helper { 10610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes private final Context mContext; 10710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes private final LayoutInflater mInflater; 10810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes private LayoutInflater mDropDownInflater; 10910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes 11010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes public Helper(@NonNull Context context) { 11110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes mContext = context; 11210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes mInflater = LayoutInflater.from(context); 11310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes } 11410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes 11510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes /** 11610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * Should be called from your adapter's 11710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * {@link ThemedSpinnerAdapter#setDropDownViewTheme(Theme)} 11810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 11910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * @param theme the theme passed in to 12010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * {@link ThemedSpinnerAdapter#setDropDownViewTheme(Theme)} 12110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes */ 12210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes public void setDropDownViewTheme(@Nullable Resources.Theme theme) { 12310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes if (theme == null) { 12410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes mDropDownInflater = null; 12510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes } else if (theme == mContext.getTheme()) { 12610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes mDropDownInflater = mInflater; 12710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes } else { 12810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes final Context context = new ContextThemeWrapper(mContext, theme); 12910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes mDropDownInflater = LayoutInflater.from(context); 13010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes } 13110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes } 13210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes 13310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes /** 13410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * Should be called from your adapter's {@link ThemedSpinnerAdapter#getDropDownViewTheme()}, 13510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * returning the value returned from this method. 13610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes */ 13710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes @Nullable 13810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes public Resources.Theme getDropDownViewTheme() { 13910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes return mDropDownInflater == null ? null : mDropDownInflater.getContext().getTheme(); 14010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes } 14110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes 14210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes /** 14310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * Returns the {@link LayoutInflater} which should be used when inflating any layouts 14410c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * from your {@link SpinnerAdapter#getDropDownView(int, View, ViewGroup)}. 14510c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * 14610c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * <p>The instance returned will have a correct theme, meaning that any inflated views 14710c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes * will be created with the same theme.</p> 14810c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes */ 14910c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes @NonNull 15010c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes public LayoutInflater getDropDownViewInflater() { 15110c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes return mDropDownInflater != null ? mDropDownInflater : mInflater; 15210c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes } 15310c8130fe03a6fb77857ac8ec91c0a21b81fcc5eChris Banes } 154f933672168f6deff5e3636584bec735416b5a93bChris Banes} 155