149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes/*
249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2014 The Android Open Source Project
349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * you may not use this file except in compliance with the License.
649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * You may obtain a copy of the License at
749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
1049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Unless required by applicable law or agreed to in writing, software
1149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * See the License for the specific language governing permissions and
1449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * limitations under the License.
1549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */
1649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
1749c78900da0d43140fb602431fb93212bd7f6c70Chris Banespackage android.support.v7.internal.widget;
1849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
191f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banesimport android.graphics.Rect;
201f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banesimport android.os.Build;
2149c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.view.ViewCompat;
221f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banesimport android.util.Log;
2349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.View;
2449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
254c5457da0e82b0090f03655545772ebb8cf4a978Chris Banesimport java.lang.reflect.InvocationTargetException;
261f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banesimport java.lang.reflect.Method;
271f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes
2849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes/**
2949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @hide
3049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */
3149c78900da0d43140fb602431fb93212bd7f6c70Chris Banespublic class ViewUtils {
321f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    private static final String TAG = "ViewUtils";
331f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes
341f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    private static Method sComputeFitSystemWindowsMethod;
351f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes
361f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    static {
371f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
381f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes            try {
391f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes                sComputeFitSystemWindowsMethod = View.class.getDeclaredMethod(
401f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes                        "computeFitSystemWindows", Rect.class, Rect.class);
414c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                if (!sComputeFitSystemWindowsMethod.isAccessible()) {
424c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                    sComputeFitSystemWindowsMethod.setAccessible(true);
434c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                }
441f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes            } catch (NoSuchMethodException e) {
454c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                Log.d(TAG, "Could not find method computeFitSystemWindows. Oh well.");
461f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes            }
471f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes        }
481f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    }
4949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
5049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private ViewUtils() {}
5149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
5249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public static boolean isLayoutRtl(View view) {
5349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL;
5449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
5549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
5649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
5749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Merge two states as returned by {@link ViewCompat#getMeasuredState(android.view.View)} ()}.
5849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param curState The current state as returned from a view or the result
5949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * of combining multiple views.
6049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param newState The new view state to combine.
6149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return Returns a new integer reflecting the combination of the two
6249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * states.
6349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
6449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public static int combineMeasuredStates(int curState, int newState) {
6549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return curState | newState;
6649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
671f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes
681f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    /**
691f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes     * Allow calling the hidden method {@code computeFitSystemWindows(Rect, Rect)} through
701f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes     * reflection on {@code view}.
711f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes     */
721f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    public static void computeFitSystemWindows(View view, Rect inoutInsets, Rect outLocalInsets) {
731f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes        if (sComputeFitSystemWindowsMethod != null) {
741f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes            try {
751f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes                sComputeFitSystemWindowsMethod.invoke(view, inoutInsets, outLocalInsets);
761f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes            } catch (Exception e) {
774c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                Log.d(TAG, "Could not invoke computeFitSystemWindows", e);
781f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes            }
791f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes        }
801f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    }
811f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes
821f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    /**
831f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes     * Allow calling the hidden method {@code makeOptionalFitsSystem()} through reflection on
841f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes     * {@code view}.
851f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes     */
861f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    public static void makeOptionalFitsSystemWindows(View view) {
874c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
881f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes            try {
894c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                // We need to use getMethod() for makeOptionalFitsSystemWindows since both View
904c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                // and ViewGroup implement the method
914c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                Method method = view.getClass().getMethod("makeOptionalFitsSystemWindows");
924c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                if (!method.isAccessible()) {
934c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                    method.setAccessible(true);
944c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                }
954c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                method.invoke(view);
964c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes            } catch (NoSuchMethodException e) {
974c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                Log.d(TAG, "Could not find method makeOptionalFitsSystemWindows. Oh well...");
984c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes            } catch (InvocationTargetException e) {
994c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                Log.d(TAG, "Could not invoke makeOptionalFitsSystemWindows", e);
1004c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes            } catch (IllegalAccessException e) {
1014c5457da0e82b0090f03655545772ebb8cf4a978Chris Banes                Log.d(TAG, "Could not invoke makeOptionalFitsSystemWindows", e);
1021f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes            }
1031f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes        }
1041f4989216d62f70088cea29f9ae200a9bb3ff955Chris Banes    }
10549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes}
106