14c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount/* 24c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * Copyright (C) 2015 The Android Open Source Project 34c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * 44c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * Licensed under the Apache License, Version 2.0 (the "License"); 54c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * you may not use this file except in compliance with the License. 64c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * You may obtain a copy of the License at 74c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * 84c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * http://www.apache.org/licenses/LICENSE-2.0 94c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * 104c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * Unless required by applicable law or agreed to in writing, software 114c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * distributed under the License is distributed on an "AS IS" BASIS, 124c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * See the License for the specific language governing permissions and 144c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * limitations under the License. 154c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount */ 164c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount 17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding; 184c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount 19ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mountimport android.app.Activity; 20ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mountimport android.support.annotation.Nullable; 216a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mountimport android.view.InflateException; 224c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mountimport android.view.LayoutInflater; 234c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mountimport android.view.View; 244c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mountimport android.view.ViewGroup; 25ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mountimport android.view.ViewParent; 264c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount 274c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount/** 284c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount * Utility class to create {@link ViewDataBinding} from layouts. 294c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount */ 304c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mountpublic class DataBindingUtil { 31125f08f32dbe73b457768aeca4accfbc44dd44b6George Mount private static DataBinderMapper sMapper = new DataBinderMapper(); 32e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount private static DataBindingComponent sDefaultComponent = null; 33e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount 34e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount /** 35c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Prevent DataBindingUtil from being instantiated. 36c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount */ 37c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount private DataBindingUtil() {} 38c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount 39c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount /** 40c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Set the default {@link DataBindingComponent} to use for data binding. 41c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <p> 42c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <code>bindingComponent</code> may be passed as the first parameter of binding adapters. 43c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <p> 44c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * When instance method BindingAdapters are used, the class instance for the binding adapter 45c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * is retrieved from the DataBindingComponent. 46e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount */ 47e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount public static void setDefaultComponent(DataBindingComponent bindingComponent) { 48e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount sDefaultComponent = bindingComponent; 49e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount } 50e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount 51e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount /** 52c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Returns the default {@link DataBindingComponent} used in data binding. This can be 53c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <code>null</code> if no default was set in 54c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * {@link #setDefaultComponent(DataBindingComponent)}. 55c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * 56c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * @return the default {@link DataBindingComponent} used in data binding. This can be 57c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <code>null</code> if no default was set in 58c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * {@link #setDefaultComponent(DataBindingComponent)}. 59e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount */ 60e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount public static DataBindingComponent getDefaultComponent() { 61e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return sDefaultComponent; 62e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount } 634c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount 64ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount /** 65ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * Inflates a binding layout and returns the newly-created binding for that layout. 66e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * This uses the DataBindingComponent set in 67e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * {@link #setDefaultComponent(DataBindingComponent)}. 68c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <p> 69c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Use this version only if <code>layoutId</code> is unknown in advance. Otherwise, use 70c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * the generated Binding's inflate method to ensure type-safe inflation. 71ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * 72ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @param inflater The LayoutInflater used to inflate the binding layout. 73ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @param layoutId The layout resource ID of the layout to inflate. 74ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @param parent Optional view to be the parent of the generated hierarchy 75ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * (if attachToParent is true), or else simply an object that provides 76ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * a set of LayoutParams values for root of the returned hierarchy 77ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * (if attachToParent is false.) 78ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @param attachToParent Whether the inflated hierarchy should be attached to the 79ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * parent parameter. If false, parent is only used to create 80ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * the correct subclass of LayoutParams for the root view in the XML. 816a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * @return The newly-created binding for the inflated layout or <code>null</code> if 826a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * the layoutId wasn't for a binding layout. 836a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * @throws InflateException When a merge layout was used and attachToParent was false. 84e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @see #setDefaultComponent(DataBindingComponent) 85ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount */ 869bdb2415487832e88a05c7bd19391b05440b468eGeorge Mount public static <T extends ViewDataBinding> T inflate(LayoutInflater inflater, int layoutId, 87ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount @Nullable ViewGroup parent, boolean attachToParent) { 88e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return inflate(inflater, layoutId, parent, attachToParent, sDefaultComponent); 89e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount } 90e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount 91e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount /** 92e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * Inflates a binding layout and returns the newly-created binding for that layout. 93c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <p> 94c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Use this version only if <code>layoutId</code> is unknown in advance. Otherwise, use 95c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * the generated Binding's inflate method to ensure type-safe inflation. 96e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * 97e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param inflater The LayoutInflater used to inflate the binding layout. 98e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param layoutId The layout resource ID of the layout to inflate. 99e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param parent Optional view to be the parent of the generated hierarchy 100e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * (if attachToParent is true), or else simply an object that provides 101e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * a set of LayoutParams values for root of the returned hierarchy 102e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * (if attachToParent is false.) 103e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param attachToParent Whether the inflated hierarchy should be attached to the 104e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * parent parameter. If false, parent is only used to create 105e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * the correct subclass of LayoutParams for the root view in the XML. 106e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param bindingComponent The DataBindingComponent to use in the binding. 107e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @return The newly-created binding for the inflated layout or <code>null</code> if 108e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * the layoutId wasn't for a binding layout. 109e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @throws InflateException When a merge layout was used and attachToParent was false. 110e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount */ 111e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount public static <T extends ViewDataBinding> T inflate( 112e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount LayoutInflater inflater, int layoutId, @Nullable ViewGroup parent, 113e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount boolean attachToParent, DataBindingComponent bindingComponent) { 114ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount final boolean useChildren = parent != null && attachToParent; 115ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount final int startChildren = useChildren ? parent.getChildCount() : 0; 1164c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount final View view = inflater.inflate(layoutId, parent, attachToParent); 117ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (useChildren) { 118ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount final int endChildren = parent.getChildCount(); 119ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount final int childrenAdded = endChildren - startChildren; 120ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (childrenAdded == 1) { 121ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount final View childView = parent.getChildAt(endChildren - 1); 122e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return bind(bindingComponent, childView, layoutId); 123ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } else { 124ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount final View[] children = new View[childrenAdded]; 125ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount for (int i = 0; i < childrenAdded; i++) { 126ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount children[i] = parent.getChildAt(i + startChildren); 127ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 128e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return bind(bindingComponent, children, layoutId); 129ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 130ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } else { 131e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return bind(bindingComponent, view, layoutId); 132ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 1334c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount } 1344c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount 135ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount /** 136ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * Returns the binding for the given layout root or creates a binding if one 137e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * does not exist. This uses the DataBindingComponent set in 138e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * {@link #setDefaultComponent(DataBindingComponent)}. 139c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <p> 140c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Prefer using the generated Binding's <code>bind</code> method to ensure type-safe inflation 141c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * when it is known that <code>root</code> has not yet been bound. 142ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * 143ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @param root The root View of the inflated binding layout. 144ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @return A ViewDataBinding for the given root View. If one already exists, the 145ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * existing one will be returned. 146ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @throws IllegalArgumentException when root is not from an inflated binding layout. 147ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @see #getBinding(View) 148ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount */ 1494c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount @SuppressWarnings("unchecked") 150ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount public static <T extends ViewDataBinding> T bind(View root) { 151e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return bind(root, sDefaultComponent); 152e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount } 153e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount 154e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount /** 155e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * Returns the binding for the given layout root or creates a binding if one 156e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * does not exist. 157c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * <p> 158c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Prefer using the generated Binding's <code>bind</code> method to ensure type-safe inflation 159c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * when it is known that <code>root</code> has not yet been bound. 160e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * 161e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param root The root View of the inflated binding layout. 162e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param bindingComponent The DataBindingComponent to use in data binding. 163e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @return A ViewDataBinding for the given root View. If one already exists, the 164e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * existing one will be returned. 165e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @throws IllegalArgumentException when root is not from an inflated binding layout. 166e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @see #getBinding(View) 167e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount */ 168e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount @SuppressWarnings("unchecked") 169e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount public static <T extends ViewDataBinding> T bind(View root, 170e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount DataBindingComponent bindingComponent) { 171ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount T binding = getBinding(root); 172ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (binding != null) { 173ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount return binding; 174ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 175ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount Object tagObj = root.getTag(); 176ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (!(tagObj instanceof String)) { 177ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount throw new IllegalArgumentException("View is not a binding layout"); 178ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } else { 179ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount String tag = (String) tagObj; 180ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount int layoutId = sMapper.getLayoutId(tag); 181ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (layoutId == 0) { 182ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount throw new IllegalArgumentException("View is not a binding layout"); 183ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 184e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return (T) sMapper.getDataBinder(bindingComponent, root, layoutId); 185ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 1864c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount } 18796e1c821dd446d1ed78f8ae61131550588f60a24George Mount 18896e1c821dd446d1ed78f8ae61131550588f60a24George Mount @SuppressWarnings("unchecked") 189e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount static <T extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View[] roots, 190e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount int layoutId) { 191e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return (T) sMapper.getDataBinder(bindingComponent, roots, layoutId); 19296e1c821dd446d1ed78f8ae61131550588f60a24George Mount } 193ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount 194e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount static <T extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View root, 195e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount int layoutId) { 196e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return (T) sMapper.getDataBinder(bindingComponent, root, layoutId); 197ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 198ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount 199ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount /** 200ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * Retrieves the binding responsible for the given View. If <code>view</code> is not a 201ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * binding layout root, its parents will be searched for the binding. If there is no binding, 202ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * <code>null</code> will be returned. 203ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * <p> 204ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * This differs from {@link #getBinding(View)} in that findBinding takes any view in the 205c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * layout and searches for the binding associated with the root. <code>getBinding</code> 206ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * takes only the root view. 207ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * 208ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @param view A <code>View</code> in the bound layout. 209ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @return The ViewDataBinding associated with the given view or <code>null</code> if 210ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * view is not part of a bound layout. 211ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount */ 212ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount public static <T extends ViewDataBinding> T findBinding(View view) { 213ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount while (view != null) { 214ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount ViewDataBinding binding = ViewDataBinding.getBinding(view); 215ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (binding != null) { 216ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount return (T) binding; 217ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 218ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount Object tag = view.getTag(); 219ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (tag instanceof String) { 220ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount String tagString = (String) tag; 221ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (tagString.startsWith("layout") && tagString.endsWith("_0")) { 222ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount final char nextChar = tagString.charAt(6); 223ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount final int slashIndex = tagString.indexOf('/', 7); 224ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount boolean isUnboundRoot = false; 225ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (nextChar == '/') { 226ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount // only one slash should exist 227ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount isUnboundRoot = slashIndex == -1; 228ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } else if (nextChar == '-' && slashIndex != -1) { 229ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount int nextSlashIndex = tagString.indexOf('/', slashIndex + 1); 230ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount // only one slash should exist 231ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount isUnboundRoot = nextSlashIndex == -1; 232ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 233ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (isUnboundRoot) { 234ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount // An inflated, but unbound layout 235ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount return null; 236ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 237ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 238ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 239ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount ViewParent viewParent = view.getParent(); 240ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount if (viewParent instanceof View) { 241ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount view = (View) viewParent; 242ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } else { 243ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount view = null; 244ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 245ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 246ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount return null; 247ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 248ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount 249ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount /** 250ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * Retrieves the binding responsible for the given View layout root. If there is no binding, 251e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * <code>null</code> will be returned. This uses the DataBindingComponent set in 252e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * {@link #setDefaultComponent(DataBindingComponent)}. 253ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * 254ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @param view The root <code>View</code> in the layout with binding. 255ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * @return The ViewDataBinding associated with the given view or <code>null</code> if 256ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount * either the view is not a root View for a layout or view hasn't been bound. 257ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount */ 258ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount public static <T extends ViewDataBinding> T getBinding(View view) { 259ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount return (T) ViewDataBinding.getBinding(view); 260ed6428586a939e00d9e66314d5cf1056ad48767eGeorge Mount } 2616a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount 2626a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount /** 2636a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * Set the Activity's content view to the given layout and return the associated binding. 2646a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * The given layout resource must not be a merge layout. 2656a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * 2666a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * @param activity The Activity whose content View should change. 2676a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * @param layoutId The resource ID of the layout to be inflated, bound, and set as the 2686a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * Activity's content. 2696a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount * @return The binding associated with the inflated content view. 2706a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount */ 2716a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount public static <T extends ViewDataBinding> T setContentView(Activity activity, int layoutId) { 272e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount return setContentView(activity, layoutId, sDefaultComponent); 273e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount } 274e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount 275e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount /** 276e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * Set the Activity's content view to the given layout and return the associated binding. 277e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * The given layout resource must not be a merge layout. 278e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * 279e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param bindingComponent The DataBindingComponent to use in data binding. 280e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param activity The Activity whose content View should change. 281e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @param layoutId The resource ID of the layout to be inflated, bound, and set as the 282e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * Activity's content. 283e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount * @return The binding associated with the inflated content view. 284e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount */ 285e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount public static <T extends ViewDataBinding> T setContentView(Activity activity, int layoutId, 286e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount DataBindingComponent bindingComponent) { 2876a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount // Force the content view to exist if it didn't already. 2886a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount View decorView = activity.getWindow().getDecorView(); 2896a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount ViewGroup contentView = (ViewGroup) decorView.findViewById(android.R.id.content); 290e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount T binding = inflate(activity.getLayoutInflater(), layoutId, contentView, false, 291e4cd38824a6627b9fef229c549c636e35ad63b5fGeorge Mount bindingComponent); 2926a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount activity.setContentView(binding.getRoot(), binding.getRoot().getLayoutParams()); 2936a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount return binding; 2946a5e8f49ed279b7ff0fe8097010ba985bf5c5ed6George Mount } 2954df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 2964df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar /** 2974df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar * Converts the given BR id to its string representation which might be useful for logging 2984df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar * purposes. 2994df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar * 3004df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar * @param id The integer id, which should be a field from BR class. 3014df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar * @return The name if the BR id or null if id is out of bounds. 3024df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar */ 3034df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar public static String convertBrIdToString(int id) { 3044df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar return sMapper.convertBrIdToString(id); 3054df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 3064c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount} 307