1 /* 2 * Copyright (C) 2015 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 17 package android.support.v7.widget; 18 19 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.content.res.Resources.Theme; 23 import android.support.annotation.NonNull; 24 import android.support.annotation.Nullable; 25 import android.support.v7.view.ContextThemeWrapper; 26 import android.view.LayoutInflater; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.widget.SpinnerAdapter; 30 31 /** 32 * An extension of SpinnerAdapter that is capable of inflating drop-down views 33 * against a different theme than normal views. 34 * <p> 35 * Classes that implement this interface should use the theme provided to 36 * {@link #setDropDownViewTheme(Theme)} when creating views in 37 * {@link SpinnerAdapter#getDropDownView(int, View, ViewGroup)}. 38 * 39 * <p>The {@link Helper} class is provided to aide implementation in a backwards compatible way. 40 * </p> 41 */ 42 public interface ThemedSpinnerAdapter extends SpinnerAdapter { 43 /** 44 * Sets the {@link Resources.Theme} against which drop-down views are 45 * inflated. 46 * 47 * @param theme the context against which to inflate drop-down views, or 48 * {@code null} to use the default theme 49 * @see SpinnerAdapter#getDropDownView(int, View, ViewGroup) 50 */ 51 void setDropDownViewTheme(@Nullable Resources.Theme theme); 52 53 /** 54 * Returns the value previously set by a call to 55 * {@link #setDropDownViewTheme(Theme)}. 56 * 57 * @return the {@link Resources.Theme} against which drop-down views are 58 * inflated, or {@code null} if one has not been explicitly set 59 */ 60 @Nullable 61 Resources.Theme getDropDownViewTheme(); 62 63 /** 64 * A helper class which allows easy integration of {@link ThemedSpinnerAdapter} into existing 65 * {@link SpinnerAdapter}s in a backwards compatible way. 66 * 67 * <p>An example {@link android.widget.BaseAdapter BaseAdapter} implementation would be:</p> 68 * 69 * <pre> 70 * public class MyAdapter extends BaseAdapter implements ThemedSpinnerAdapter { 71 * private final ThemedSpinnerAdapter.Helper mDropDownHelper; 72 * 73 * public CheeseAdapter(Context context) { 74 * mDropDownHelper = new ThemedSpinnerAdapter.Helper(context); 75 * // ... 76 * } 77 * 78 * @Override 79 * public View getDropDownView(int position, View convertView, ViewGroup parent) { 80 * View view; 81 * 82 * if (convertView == null) { 83 * // Inflate the drop down using the helper's LayoutInflater 84 * LayoutInflater inflater = mDropDownHelper.getDropDownViewInflater(); 85 * view = inflater.inflate(R.layout.my_dropdown, parent, false); 86 * } 87 * 88 * // ... 89 * } 90 * 91 * @Override 92 * public void setDropDownViewTheme(@Nullable Resources.Theme theme) { 93 * // Pass the new theme to the helper 94 * mDropDownHelper.setDropDownViewTheme(theme); 95 * } 96 * 97 * @Override 98 * public Resources.Theme getDropDownViewTheme() { 99 * // Return the helper's value 100 * return mDropDownHelper.getDropDownViewTheme(); 101 * } 102 * } 103 * </pre> 104 */ 105 public final static class Helper { 106 private final Context mContext; 107 private final LayoutInflater mInflater; 108 private LayoutInflater mDropDownInflater; 109 110 public Helper(@NonNull Context context) { 111 mContext = context; 112 mInflater = LayoutInflater.from(context); 113 } 114 115 /** 116 * Should be called from your adapter's 117 * {@link ThemedSpinnerAdapter#setDropDownViewTheme(Theme)} 118 * 119 * @param theme the theme passed in to 120 * {@link ThemedSpinnerAdapter#setDropDownViewTheme(Theme)} 121 */ 122 public void setDropDownViewTheme(@Nullable Resources.Theme theme) { 123 if (theme == null) { 124 mDropDownInflater = null; 125 } else if (theme == mContext.getTheme()) { 126 mDropDownInflater = mInflater; 127 } else { 128 final Context context = new ContextThemeWrapper(mContext, theme); 129 mDropDownInflater = LayoutInflater.from(context); 130 } 131 } 132 133 /** 134 * Should be called from your adapter's {@link ThemedSpinnerAdapter#getDropDownViewTheme()}, 135 * returning the value returned from this method. 136 */ 137 @Nullable 138 public Resources.Theme getDropDownViewTheme() { 139 return mDropDownInflater == null ? null : mDropDownInflater.getContext().getTheme(); 140 } 141 142 /** 143 * Returns the {@link LayoutInflater} which should be used when inflating any layouts 144 * from your {@link SpinnerAdapter#getDropDownView(int, View, ViewGroup)}. 145 * 146 * <p>The instance returned will have a correct theme, meaning that any inflated views 147 * will be created with the same theme.</p> 148 */ 149 @NonNull 150 public LayoutInflater getDropDownViewInflater() { 151 return mDropDownInflater != null ? mDropDownInflater : mInflater; 152 } 153 } 154 } 155