/*
* Copyright (C) 2014 Andrey Kulikov (andkulikov@gmail.com)
*
* 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.transitionseverywhere.utils;
import android.annotation.TargetApi;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.view.View;
import android.view.ViewGroup;
import com.transitionseverywhere.R;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@TargetApi(VERSION_CODES.ICE_CREAM_SANDWICH)
public class ViewUtils {
static class BaseViewUtils {
private static final Field FIELD_VIEW_FLAGS =
ReflectionUtils.getPrivateField(View.class, "mViewFlags");
private static final Field FIELD_LAYOUT_PARAMS =
ReflectionUtils.getPrivateField(View.class, "mLayoutParams");
private static final int VIEW_VISIBILITY_MASK = 0x0000000C;
private static final Method METHOD_SET_FRAME =
ReflectionUtils.getPrivateMethod(View.class, "setFrame", int.class, int.class,
int.class, int.class);
public float getTransitionAlpha(View v) {
return v.getAlpha();
}
public boolean isLaidOut(View v, boolean defaultValue) {
return defaultValue;
}
public void setClipBounds(View v, Rect clipBounds) {
// TODO: Implement support behavior
}
public Rect getClipBounds(View v) {
// TODO: Implement support behavior
return null;
}
public void setTransitionName(View v, String name) {
v.setTag(R.id.transitionName, name);
}
public String getTransitionName(View v) {
return (String) v.getTag(R.id.transitionName);
}
public void setTranslationZ(View view, float z) {
// do nothing
}
public float getTranslationZ(View view) {
return 0;
}
public View addGhostView(View view, ViewGroup viewGroup, Matrix matrix) {
return null;
}
public void removeGhostView(View view) {
// do nothing
}
public void transformMatrixToGlobal(View view, Matrix matrix) {
// TODO: Implement support behavior
}
public void transformMatrixToLocal(View v, Matrix matrix) {
// TODO: Implement support behavior
}
public void setAnimationMatrix(View view, Matrix matrix) {
// TODO: Implement support behavior
}
public Object getWindowId(View view) {
return view.getWindowToken();
}
public boolean isRtl(View view) {
return false;
}
public void setHasTransientState(View view, boolean hasTransientState) {
// do nothing; API doesn't exist
}
public boolean hasTransientState(View view) {
return false;
}
public void setTransitionVisibility(View v, int visibility) {
int value = (Integer) ReflectionUtils.getFieldValue(v, 0, FIELD_VIEW_FLAGS);
value = (value & ~VIEW_VISIBILITY_MASK) | visibility;
ReflectionUtils.setFieldValue(v, FIELD_VIEW_FLAGS, value);
}
public void setLeftTopRightBottom(View v, int left, int top, int right, int bottom) {
ReflectionUtils.invoke(v, null, METHOD_SET_FRAME, left, top, right, bottom);
}
public void setLayoutParamsSilently(View view, ViewGroup.LayoutParams layoutParams) {
ReflectionUtils.setFieldValue(view, FIELD_LAYOUT_PARAMS, layoutParams);
}
}
@TargetApi(VERSION_CODES.JELLY_BEAN)
static class ViewUtilsJellyBean extends BaseViewUtils {
@Override
public void setHasTransientState(View view, boolean hasTransientState) {
view.setHasTransientState(hasTransientState);
}
@Override
public boolean hasTransientState(View view) {
return view.hasTransientState();
}
}
@TargetApi(VERSION_CODES.JELLY_BEAN_MR1)
static class ViewUtilsJellyBeanMR1 extends ViewUtilsJellyBean {
@Override
public boolean isRtl(View view) {
return view != null && view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
}
}
@TargetApi(VERSION_CODES.JELLY_BEAN_MR2)
static class ViewUtilsJellyBeanMR2 extends ViewUtilsJellyBeanMR1 {
@Override
public void setClipBounds(View v, Rect clipBounds) {
v.setClipBounds(clipBounds);
}
@Override
public Rect getClipBounds(View v) {
return v.getClipBounds();
}
@Override
public Object getWindowId(View view) {
return view.getWindowId();
}
}
@TargetApi(VERSION_CODES.KITKAT)
static class ViewUtilsKitKat extends ViewUtilsJellyBeanMR2 {
@Override
public boolean isLaidOut(View v, boolean defaultValue) {
return v.isLaidOut();
}
}
private static final BaseViewUtils IMPL;
static {
final int version = VERSION.SDK_INT;
if (version >= VERSION_CODES.LOLLIPOP_MR1) {
IMPL = new ViewUtilsLollipopMr1();
} else if (version >= VERSION_CODES.LOLLIPOP) {
IMPL = new ViewUtilsLollipop();
} else if (version >= VERSION_CODES.KITKAT) {
IMPL = new ViewUtilsKitKat();
} else if (version >= VERSION_CODES.JELLY_BEAN_MR2) {
IMPL = new ViewUtilsJellyBeanMR2();
} else if (version >= VERSION_CODES.JELLY_BEAN_MR1) {
IMPL = new ViewUtilsJellyBeanMR1();
} else if (version >= VERSION_CODES.JELLY_BEAN) {
IMPL = new ViewUtilsJellyBean();
} else {
IMPL = new BaseViewUtils();
}
}
public static float getTransitionAlpha(View v) {
return IMPL.getTransitionAlpha(v);
}
public static boolean isLaidOut(View v, boolean defaultValue) {
return IMPL.isLaidOut(v, defaultValue);
}
public static void setClipBounds(View v, Rect clipBounds) {
IMPL.setClipBounds(v, clipBounds);
}
public static Rect getClipBounds(View v) {
return IMPL.getClipBounds(v);
}
public static void setTransitionName(View v, String name) {
IMPL.setTransitionName(v, name);
}
public static String getTransitionName(View v) {
return IMPL.getTransitionName(v);
}
public static float getTranslationZ(View view) {
return IMPL.getTranslationZ(view);
}
public static void setTranslationZ(View view, float z) {
IMPL.setTranslationZ(view, z);
}
public static void transformMatrixToGlobal(View view, Matrix matrix) {
IMPL.transformMatrixToGlobal(view, matrix);
}
public static void transformMatrixToLocal(View view, Matrix matrix) {
IMPL.transformMatrixToLocal(view, matrix);
}
public static void setAnimationMatrix(View view, Matrix matrix) {
IMPL.setAnimationMatrix(view, matrix);
}
public static View addGhostView(View view, ViewGroup viewGroup, Matrix matrix) {
return IMPL.addGhostView(view, viewGroup, matrix);
}
public static void removeGhostView(View view) {
IMPL.removeGhostView(view);
}
public static Object getWindowId(View view) {
return IMPL.getWindowId(view);
}
public static boolean isRtl(View view) {
return IMPL.isRtl(view);
}
public static boolean hasTransientState(View view) {
return IMPL.hasTransientState(view);
}
public static void setHasTransientState(View view, boolean hasTransientState) {
IMPL.setHasTransientState(view, hasTransientState);
}
/**
* Change the visibility of the View without triggering any other changes. This is
* important for transitions, where visibility changes should not adjust focus or
* trigger a new layout. This is only used when the visibility has already been changed
* and we need a transient value during an animation. When the animation completes,
* the original visibility value is always restored.
*
* @param visibility One of View.VISIBLE, View.INVISIBLE, or View.GONE.
*/
public static void setTransitionVisibility(View view, int visibility) {
IMPL.setTransitionVisibility(view, visibility);
}
public static void setLeftTopRightBottom(View view, int left, int top, int right, int bottom) {
if (view != null) {
IMPL.setLeftTopRightBottom(view, left, top, right, bottom);
}
}
public static void setLayoutParamsSilently(View view, ViewGroup.LayoutParams layoutParams) {
IMPL.setLayoutParamsSilently(view, layoutParams);
}
}