/******************************************************************************* * Copyright 2012-present Pixate, 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.pixate.freestyle.util; import android.app.Activity; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import com.pixate.freestyle.PXHierarchyListener; import com.pixate.freestyle.styling.PXStyleUtils; public class ViewUtil { public static final int TAG_ID = Integer.MIN_VALUE; public static final int TAG_CLASS = TAG_ID + 1; public static final int TAG_STYLE = TAG_ID + 2; public static final int TAG_ELEMENT_NAME = TAG_ID + 3; public static final int TAG_ELEMENT_INDEX = TAG_ID + 4; public static final int TAG_ELEMENTS_COUNT = TAG_ID + 5; public static final int TAG_ELEMENT_FUTURE_PARENT = TAG_ID + 6; public static final int TAG_TAGGED = TAG_ID + 7; public static void initView(View view, AttributeSet attrs) { String cssClass = null, cssStyle = null; if (attrs != null) { cssClass = attrs.getClassAttribute(); cssStyle = attrs.getAttributeValue(null, "style"); } initView(view, null, cssClass, cssStyle); } public static void initView(final View view, String cssId, String cssClass, String cssStyle) { initTags(view, cssId, cssClass, cssStyle); if (view instanceof ViewGroup) { prepareViewGroupListeners((ViewGroup) view); } } public static void initTags(View view, String cssId, String cssClass, String cssStyle) { if (cssId == null) { cssId = getViewId(view); } setStyleId(view, cssId, false); setStyleClass(view, cssClass, false); setStyle(view, cssStyle, false); } public static void initTags(View view) { initTags(view, null, null, null); } private static void markTagged(View view) { view.setTag(TAG_TAGGED, Boolean.TRUE); } public static boolean isTagged(View view) { return view.getTag(TAG_TAGGED) != null; } /** * Check the View's id, then use that to find the name given to it in XML. * * @param view * @return String the name, if found, else null. */ private static String getViewId(View view) { try { int id = view.getId(); if (id == View.NO_ID) { return null; } return view.getContext().getResources().getResourceEntryName(id); } catch (Resources.NotFoundException e) { // No-op } return null; } public static void style(View view) { PXStyleUtils.updateStyles(view, true); } public static void style(View view, boolean styleChildren) { PXStyleUtils.updateStyles(view, styleChildren); } public static void prepareViewGroupListeners(ViewGroup viewGroup) { if (viewGroup == null) { return; } PXHierarchyListener.setFor(viewGroup); int count = viewGroup.getChildCount(); for (int i = 0; i < count; i++) { View child = viewGroup.getChildAt(i); if (child instanceof ViewGroup) { prepareViewGroupListeners((ViewGroup) child); } } } public static void prepareViewGroupListeners(Activity activity) { if (activity == null) { return; } View contentView = activity.findViewById(android.R.id.content); if (contentView instanceof ViewGroup) { prepareViewGroupListeners((ViewGroup) contentView); } } public static void setStyleId(View view, String cssId) { setStyleId(view, cssId, view.getParent() != null); } public static void setStyleId(View view, String cssId, boolean restyleNow) { markTagged(view); view.setTag(TAG_ID, cssId); if (restyleNow) { style(view); } } public static void setStyleClass(View view, String cssClass) { setStyleClass(view, cssClass, view.getParent() != null); } public static void setStyleClass(View view, String cssClass, boolean restyleNow) { markTagged(view); view.setTag(TAG_CLASS, cssClass); if (restyleNow) { style(view); } } public static void setStyle(View view, String cssStyle) { setStyle(view, cssStyle, view.getParent() != null); } public static void setStyle(View view, String cssStyle, boolean restyleNow) { markTagged(view); view.setTag(TAG_STYLE, cssStyle); if (restyleNow) { style(view); } } public static String getStyleId(View view) { String result = null; if (view != null) { result = (String) view.getTag(TAG_ID); } return result; } public static String getStyleClass(View view) { String result = null; if (view != null) { result = (String) view.getTag(TAG_CLASS); } return result; } public static String getElementName(View view) { String result = null; if (view != null) { // TODO figure out and cache result = (String) view.getTag(TAG_ELEMENT_NAME); if (result == null) { result = view.getClass().getSimpleName(); } } return result; } public static RectF getBounds(View view) { if (view != null) { Rect r = new Rect(); view.getDrawingRect(r); return new RectF(r); } return null; } /** * Returns the View's width. In case the {@link View#getWidth()} returns * zero, we try to get the width via the layout params. * * @param view * @return the View's width */ public static int getWidth(View view) { if (view == null) { return 0; } int w = view.getWidth(); if (w == 0) { // try to get it from the layout LayoutParams layoutParams = view.getLayoutParams(); if (layoutParams != null) { w = layoutParams.width; } } return w; } /** * Returns the View's height. In case the {@link View#getHeight()} returns * zero, we try to get the height via the layout params. * * @param view * @return the View's height */ public static int getHeight(View view) { if (view == null) { return 0; } int h = view.getHeight(); if (h == 0) { // try to get it from the layout LayoutParams layoutParams = view.getLayoutParams(); if (layoutParams != null) { h = layoutParams.height; } } return h; } public static void sendToBack(View view) { /* * There is no single "send to back" method in Android. Instead, move * everything "under" this view to the front, one at a time. Also have * to do that for the views "above" this view, so they take back their * rightful place at the top after the lower views have been moved above * them by "bringChildToFront". When all is said and done, this view * will be sitting at the bottom, and the views above it will retain * their original order. In Android L (as part of Material Design), * view's will have an `elevation` property for this. */ if (view != null && view.getParent() instanceof ViewGroup) { ViewGroup parent = (ViewGroup) view.getParent(); int thisIndex = parent.indexOfChild(view); for (int i = 0; i < parent.getChildCount(); i++) { if (i < thisIndex) { parent.bringChildToFront(parent.getChildAt(0)); } else if (i > thisIndex) { parent.bringChildToFront(parent.getChildAt(1)); } } } } }