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