1 /* 2 * Copyright (C) 2013 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 com.android.layoutlib.bridge.impl.binding; 18 19 import com.android.ide.common.rendering.api.DataBindingItem; 20 import com.android.ide.common.rendering.api.IProjectCallback; 21 import com.android.ide.common.rendering.api.LayoutLog; 22 import com.android.ide.common.rendering.api.ResourceReference; 23 import com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute; 24 import com.android.layoutlib.bridge.Bridge; 25 import com.android.layoutlib.bridge.android.BridgeContext; 26 import com.android.layoutlib.bridge.impl.RenderAction; 27 import com.android.util.Pair; 28 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.widget.AdapterView; 32 import android.widget.Checkable; 33 import android.widget.ImageView; 34 import android.widget.TextView; 35 36 /** 37 * A Helper class to do fake data binding in {@link AdapterView} objects. 38 */ 39 @SuppressWarnings("deprecation") 40 public class AdapterHelper { 41 42 static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent, 43 IProjectCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) { 44 // we don't care about recycling here because we never scroll. 45 DataBindingItem dataBindingItem = item.getDataBindingItem(); 46 47 BridgeContext context = RenderAction.getCurrentContext(); 48 49 Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(), 50 parent, false /*attachToRoot*/, skipCallbackParser); 51 52 View view = pair.getFirst(); 53 skipCallbackParser |= pair.getSecond(); 54 55 if (view != null) { 56 fillView(context, view, item, parentItem, callback, adapterRef); 57 } else { 58 // create a text view to display an error. 59 TextView tv = new TextView(context); 60 tv.setText("Unable to find layout: " + dataBindingItem.getViewReference().getName()); 61 view = tv; 62 } 63 64 return Pair.of(view, skipCallbackParser); 65 } 66 67 private static void fillView(BridgeContext context, View view, AdapterItem item, 68 AdapterItem parentItem, IProjectCallback callback, ResourceReference adapterRef) { 69 if (view instanceof ViewGroup) { 70 ViewGroup group = (ViewGroup) view; 71 final int count = group.getChildCount(); 72 for (int i = 0 ; i < count ; i++) { 73 fillView(context, group.getChildAt(i), item, parentItem, callback, adapterRef); 74 } 75 } else { 76 int id = view.getId(); 77 if (id != 0) { 78 ResourceReference resolvedRef = context.resolveId(id); 79 if (resolvedRef != null) { 80 int fullPosition = item.getFullPosition(); 81 int positionPerType = item.getPositionPerType(); 82 int fullParentPosition = parentItem != null ? parentItem.getFullPosition() : 0; 83 int parentPositionPerType = parentItem != null ? 84 parentItem.getPositionPerType() : 0; 85 86 if (view instanceof TextView) { 87 TextView tv = (TextView) view; 88 Object value = callback.getAdapterItemValue( 89 adapterRef, context.getViewKey(view), 90 item.getDataBindingItem().getViewReference(), 91 fullPosition, positionPerType, 92 fullParentPosition, parentPositionPerType, 93 resolvedRef, ViewAttribute.TEXT, tv.getText().toString()); 94 if (value != null) { 95 if (value.getClass() != ViewAttribute.TEXT.getAttributeClass()) { 96 Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( 97 "Wrong Adapter Item value class for TEXT. Expected String, got %s", 98 value.getClass().getName()), null); 99 } else { 100 tv.setText((String) value); 101 } 102 } 103 } 104 105 if (view instanceof Checkable) { 106 Checkable cb = (Checkable) view; 107 108 Object value = callback.getAdapterItemValue( 109 adapterRef, context.getViewKey(view), 110 item.getDataBindingItem().getViewReference(), 111 fullPosition, positionPerType, 112 fullParentPosition, parentPositionPerType, 113 resolvedRef, ViewAttribute.IS_CHECKED, cb.isChecked()); 114 if (value != null) { 115 if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) { 116 Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( 117 "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s", 118 value.getClass().getName()), null); 119 } else { 120 cb.setChecked((Boolean) value); 121 } 122 } 123 } 124 125 if (view instanceof ImageView) { 126 ImageView iv = (ImageView) view; 127 128 Object value = callback.getAdapterItemValue( 129 adapterRef, context.getViewKey(view), 130 item.getDataBindingItem().getViewReference(), 131 fullPosition, positionPerType, 132 fullParentPosition, parentPositionPerType, 133 resolvedRef, ViewAttribute.SRC, iv.getDrawable()); 134 if (value != null) { 135 if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) { 136 Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( 137 "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s", 138 value.getClass().getName()), null); 139 } else { 140 // FIXME 141 } 142 } 143 } 144 } 145 } 146 } 147 } 148 } 149