CustomBar.java revision 01b6c755dbcf24e71192dc44757e2eea2a426091
1/* 2 * Copyright (C) 2011 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.layoutlib.bridge.bars; 18 19import com.android.ide.common.rendering.api.RenderResources; 20import com.android.ide.common.rendering.api.ResourceValue; 21import com.android.ide.common.rendering.api.StyleResourceValue; 22import com.android.layoutlib.bridge.Bridge; 23import com.android.layoutlib.bridge.android.BridgeContext; 24import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 25import com.android.layoutlib.bridge.impl.ParserFactory; 26import com.android.layoutlib.bridge.impl.ResourceHelper; 27import com.android.resources.Density; 28import com.android.resources.ResourceType; 29 30import org.xmlpull.v1.XmlPullParser; 31import org.xmlpull.v1.XmlPullParserException; 32 33import android.content.Context; 34import android.content.res.ColorStateList; 35import android.graphics.Bitmap; 36import android.graphics.Bitmap_Delegate; 37import android.graphics.drawable.BitmapDrawable; 38import android.graphics.drawable.Drawable; 39import android.util.TypedValue; 40import android.view.Gravity; 41import android.view.LayoutInflater; 42import android.view.View; 43import android.widget.ImageView; 44import android.widget.LinearLayout; 45import android.widget.TextView; 46 47import java.io.IOException; 48import java.io.InputStream; 49 50/** 51 * Base "bar" class for the window decor around the the edited layout. 52 * This is basically an horizontal layout that loads a given layout on creation (it is read 53 * through {@link Class#getResourceAsStream(String)}). 54 * 55 * The given layout should be a merge layout so that all the children belong to this class directly. 56 * 57 * It also provides a few utility methods to configure the content of the layout. 58 */ 59abstract class CustomBar extends LinearLayout { 60 61 protected abstract TextView getStyleableTextView(); 62 63 protected CustomBar(Context context, Density density, String layoutPath, String name) 64 throws XmlPullParserException { 65 super(context); 66 setOrientation(LinearLayout.HORIZONTAL); 67 setGravity(Gravity.CENTER_VERTICAL); 68 69 LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( 70 Context.LAYOUT_INFLATER_SERVICE); 71 72 XmlPullParser parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), 73 name); 74 75 BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( 76 parser, (BridgeContext) context, false /*platformFile*/); 77 78 try { 79 inflater.inflate(bridgeParser, this, true); 80 } finally { 81 bridgeParser.ensurePopped(); 82 } 83 } 84 85 private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut, 86 boolean tryOtherDensities) { 87 // current density 88 Density density = densityInOut[0]; 89 90 // bitmap url relative to this class 91 pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName; 92 93 InputStream stream = getClass().getResourceAsStream(pathOut[0]); 94 if (stream == null && tryOtherDensities) { 95 for (Density d : Density.values()) { 96 if (d != density) { 97 densityInOut[0] = d; 98 stream = getIcon(iconName, densityInOut, pathOut, false /*tryOtherDensities*/); 99 if (stream != null) { 100 return stream; 101 } 102 } 103 } 104 } 105 106 return stream; 107 } 108 109 protected void loadIcon(int index, String iconName, Density density) { 110 View child = getChildAt(index); 111 if (child instanceof ImageView) { 112 ImageView imageView = (ImageView) child; 113 114 String[] pathOut = new String[1]; 115 Density[] densityInOut = new Density[] { density }; 116 InputStream stream = getIcon(iconName, densityInOut, pathOut, 117 true /*tryOtherDensities*/); 118 density = densityInOut[0]; 119 120 if (stream != null) { 121 // look for a cached bitmap 122 Bitmap bitmap = Bridge.getCachedBitmap(pathOut[0], true /*isFramework*/); 123 if (bitmap == null) { 124 try { 125 bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density); 126 Bridge.setCachedBitmap(pathOut[0], bitmap, true /*isFramework*/); 127 } catch (IOException e) { 128 return; 129 } 130 } 131 132 if (bitmap != null) { 133 BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), 134 bitmap); 135 imageView.setImageDrawable(drawable); 136 } 137 } 138 } 139 } 140 141 protected void loadIcon(int index, String iconReference) { 142 ResourceValue value = getResourceValue(iconReference); 143 if (value != null) { 144 loadIcon(index, value); 145 } 146 } 147 148 protected void loadIconById(int id, String iconReference) { 149 ResourceValue value = getResourceValue(iconReference); 150 if (value != null) { 151 loadIconById(id, value); 152 } 153 } 154 155 156 protected Drawable loadIcon(int index, ResourceType type, String name) { 157 BridgeContext bridgeContext = (BridgeContext) mContext; 158 RenderResources res = bridgeContext.getRenderResources(); 159 160 // find the resource 161 ResourceValue value = res.getFrameworkResource(type, name); 162 163 // resolve it if needed 164 value = res.resolveResValue(value); 165 return loadIcon(index, value); 166 } 167 168 private Drawable loadIcon(int index, ResourceValue value) { 169 View child = getChildAt(index); 170 if (child instanceof ImageView) { 171 ImageView imageView = (ImageView) child; 172 173 return loadIcon(imageView, value); 174 } 175 176 return null; 177 } 178 179 private Drawable loadIconById(int id, ResourceValue value) { 180 View child = findViewById(id); 181 if (child instanceof ImageView) { 182 ImageView imageView = (ImageView) child; 183 184 return loadIcon(imageView, value); 185 } 186 187 return null; 188 } 189 190 191 private Drawable loadIcon(ImageView imageView, ResourceValue value) { 192 Drawable drawable = ResourceHelper.getDrawable(value, (BridgeContext) mContext); 193 if (drawable != null) { 194 imageView.setImageDrawable(drawable); 195 } 196 197 return drawable; 198 } 199 200 protected TextView setText(int index, String stringReference) { 201 View child = getChildAt(index); 202 if (child instanceof TextView) { 203 TextView textView = (TextView) child; 204 setText(textView, stringReference); 205 return textView; 206 } 207 208 return null; 209 } 210 211 protected TextView setTextById(int id, String stringReference) { 212 View child = findViewById(id); 213 if (child instanceof TextView) { 214 TextView textView = (TextView) child; 215 setText(textView, stringReference); 216 return textView; 217 } 218 219 return null; 220 } 221 222 private void setText(TextView textView, String stringReference) { 223 ResourceValue value = getResourceValue(stringReference); 224 if (value != null) { 225 textView.setText(value.getValue()); 226 } else { 227 textView.setText(stringReference); 228 } 229 } 230 231 protected void setStyle(String themeEntryName) { 232 233 BridgeContext bridgeContext = (BridgeContext) mContext; 234 RenderResources res = bridgeContext.getRenderResources(); 235 236 ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/); 237 value = res.resolveResValue(value); 238 239 if (value instanceof StyleResourceValue == false) { 240 return; 241 } 242 243 StyleResourceValue style = (StyleResourceValue) value; 244 245 // get the background 246 ResourceValue backgroundValue = res.findItemInStyle(style, "background", 247 true /*isFrameworkAttr*/); 248 backgroundValue = res.resolveResValue(backgroundValue); 249 if (backgroundValue != null) { 250 Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext); 251 if (d != null) { 252 setBackground(d); 253 } 254 } 255 256 TextView textView = getStyleableTextView(); 257 if (textView != null) { 258 // get the text style 259 ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle", 260 true /*isFrameworkAttr*/); 261 textStyleValue = res.resolveResValue(textStyleValue); 262 if (textStyleValue instanceof StyleResourceValue) { 263 StyleResourceValue textStyle = (StyleResourceValue) textStyleValue; 264 265 ResourceValue textSize = res.findItemInStyle(textStyle, "textSize", 266 true /*isFrameworkAttr*/); 267 textSize = res.resolveResValue(textSize); 268 269 if (textSize != null) { 270 TypedValue out = new TypedValue(); 271 if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out, 272 true /*requireUnit*/)) { 273 textView.setTextSize( 274 out.getDimension(bridgeContext.getResources().getDisplayMetrics())); 275 } 276 } 277 278 279 ResourceValue textColor = res.findItemInStyle(textStyle, "textColor", 280 true /*isFrameworkAttr*/); 281 textColor = res.resolveResValue(textColor); 282 if (textColor != null) { 283 ColorStateList stateList = ResourceHelper.getColorStateList( 284 textColor, bridgeContext); 285 if (stateList != null) { 286 textView.setTextColor(stateList); 287 } 288 } 289 } 290 } 291 } 292 293 private ResourceValue getResourceValue(String reference) { 294 BridgeContext bridgeContext = (BridgeContext) mContext; 295 RenderResources res = bridgeContext.getRenderResources(); 296 297 // find the resource 298 ResourceValue value = res.findResValue(reference, false /*isFramework*/); 299 300 // resolve it if needed 301 return res.resolveResValue(value); 302 } 303} 304