/* * Copyright (C) 2016 Square, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.squareup.coordinators; import android.os.Build; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; public final class Coordinators { private Coordinators() { } /** * Attempts to bind a view to a {@link Coordinator}. * * Immediately calls provider to obtain a Coordinator for the view. If a non-null Coordinator is * returned, that Coordinator is permanently bound to the View. */ public static void bind(@NonNull View view, @NonNull CoordinatorProvider provider) { final Coordinator coordinator = provider.provideCoordinator(view); if (coordinator == null) { return; } View.OnAttachStateChangeListener binding = new Binding(coordinator, view); view.addOnAttachStateChangeListener(binding); // Sometimes we missed the first attach because the child's already been added. // Sometimes we didn't. The binding keeps track to avoid double attachment of the Coordinator, // and to guard against attachment to two different views simultaneously. if (isAttachedToWindow(view)) { binding.onViewAttachedToWindow(view); } } /** * Installs a binder that calls {@link #bind(View, CoordinatorProvider)} for any child view added * to the group. */ public static void installBinder(@NonNull ViewGroup viewGroup, @NonNull final CoordinatorProvider provider) { int childCount = viewGroup.getChildCount(); for (int i = 0; i < childCount; i++) { bind(viewGroup.getChildAt(i), provider); } viewGroup.setOnHierarchyChangeListener(new Binder(provider)); } @Nullable public static Coordinator getCoordinator(@NonNull View view) { return (Coordinator) view.getTag(R.id.coordinator); } private static boolean isAttachedToWindow(View view) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return view.getWindowToken() != null; } else { return view.isAttachedToWindow(); } } }