From d025fd3ce39c41f3b3bb0ed11083853545fa1c00 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Wed, 8 Nov 2023 18:13:47 +0100 Subject: [PATCH] FrameLayout: replace with AOSPs implementation There are many Widgets extending FrameLayout and adding custom behaviour on top. For example NavigationView. This didn't realy work with our custom implementation --- meson.build | 1 - .../android_widget_FrameLayout.h | 213 ---------- .../widgets/android_widget_FrameLayout.c | 84 ---- src/api-impl/android/view/ViewGroup.java | 6 + src/api-impl/android/widget/FrameLayout.java | 374 ++++++++++++++++-- 5 files changed, 357 insertions(+), 321 deletions(-) delete mode 100644 src/api-impl-jni/generated_headers/android_widget_FrameLayout.h delete mode 100644 src/api-impl-jni/widgets/android_widget_FrameLayout.c diff --git a/meson.build b/meson.build index b4a45151..dc50dedb 100644 --- a/meson.build +++ b/meson.build @@ -89,7 +89,6 @@ libtranslationlayer_so = shared_library('translation_layer_main', [ 'src/api-impl-jni/widgets/android_widget_ImageButton.c', 'src/api-impl-jni/widgets/android_widget_ScrollView.c', 'src/api-impl-jni/widgets/android_widget_ImageView.c', - 'src/api-impl-jni/widgets/android_widget_FrameLayout.c', 'src/api-impl-jni/widgets/WrapperWidget.c', 'src/api-impl-jni/widgets/android_widget_TextView.c', 'src/api-impl-jni/widgets/android_widget_LinearLayout.c', diff --git a/src/api-impl-jni/generated_headers/android_widget_FrameLayout.h b/src/api-impl-jni/generated_headers/android_widget_FrameLayout.h deleted file mode 100644 index a5732d99..00000000 --- a/src/api-impl-jni/generated_headers/android_widget_FrameLayout.h +++ /dev/null @@ -1,213 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class android_widget_FrameLayout */ - -#ifndef _Included_android_widget_FrameLayout -#define _Included_android_widget_FrameLayout -#ifdef __cplusplus -extern "C" { -#endif -#undef android_widget_FrameLayout_NO_ID -#define android_widget_FrameLayout_NO_ID -1L -#undef android_widget_FrameLayout_NOT_FOCUSABLE -#define android_widget_FrameLayout_NOT_FOCUSABLE 0L -#undef android_widget_FrameLayout_FOCUSABLE -#define android_widget_FrameLayout_FOCUSABLE 1L -#undef android_widget_FrameLayout_FOCUSABLE_MASK -#define android_widget_FrameLayout_FOCUSABLE_MASK 1L -#undef android_widget_FrameLayout_FITS_SYSTEM_WINDOWS -#define android_widget_FrameLayout_FITS_SYSTEM_WINDOWS 2L -#undef android_widget_FrameLayout_VISIBLE -#define android_widget_FrameLayout_VISIBLE 0L -#undef android_widget_FrameLayout_INVISIBLE -#define android_widget_FrameLayout_INVISIBLE 4L -#undef android_widget_FrameLayout_GONE -#define android_widget_FrameLayout_GONE 8L -#undef android_widget_FrameLayout_VISIBILITY_MASK -#define android_widget_FrameLayout_VISIBILITY_MASK 12L -#undef android_widget_FrameLayout_ENABLED -#define android_widget_FrameLayout_ENABLED 0L -#undef android_widget_FrameLayout_DISABLED -#define android_widget_FrameLayout_DISABLED 32L -#undef android_widget_FrameLayout_ENABLED_MASK -#define android_widget_FrameLayout_ENABLED_MASK 32L -#undef android_widget_FrameLayout_WILL_NOT_DRAW -#define android_widget_FrameLayout_WILL_NOT_DRAW 128L -#undef android_widget_FrameLayout_DRAW_MASK -#define android_widget_FrameLayout_DRAW_MASK 128L -#undef android_widget_FrameLayout_SCROLLBARS_NONE -#define android_widget_FrameLayout_SCROLLBARS_NONE 0L -#undef android_widget_FrameLayout_SCROLLBARS_HORIZONTAL -#define android_widget_FrameLayout_SCROLLBARS_HORIZONTAL 256L -#undef android_widget_FrameLayout_SCROLLBARS_VERTICAL -#define android_widget_FrameLayout_SCROLLBARS_VERTICAL 512L -#undef android_widget_FrameLayout_SCROLLBARS_MASK -#define android_widget_FrameLayout_SCROLLBARS_MASK 768L -#undef android_widget_FrameLayout_FILTER_TOUCHES_WHEN_OBSCURED -#define android_widget_FrameLayout_FILTER_TOUCHES_WHEN_OBSCURED 1024L -#undef android_widget_FrameLayout_OPTIONAL_FITS_SYSTEM_WINDOWS -#define android_widget_FrameLayout_OPTIONAL_FITS_SYSTEM_WINDOWS 2048L -#undef android_widget_FrameLayout_FADING_EDGE_NONE -#define android_widget_FrameLayout_FADING_EDGE_NONE 0L -#undef android_widget_FrameLayout_FADING_EDGE_HORIZONTAL -#define android_widget_FrameLayout_FADING_EDGE_HORIZONTAL 4096L -#undef android_widget_FrameLayout_FADING_EDGE_VERTICAL -#define android_widget_FrameLayout_FADING_EDGE_VERTICAL 8192L -#undef android_widget_FrameLayout_FADING_EDGE_MASK -#define android_widget_FrameLayout_FADING_EDGE_MASK 12288L -#undef android_widget_FrameLayout_CLICKABLE -#define android_widget_FrameLayout_CLICKABLE 16384L -#undef android_widget_FrameLayout_DRAWING_CACHE_ENABLED -#define android_widget_FrameLayout_DRAWING_CACHE_ENABLED 32768L -#undef android_widget_FrameLayout_SAVE_DISABLED -#define android_widget_FrameLayout_SAVE_DISABLED 65536L -#undef android_widget_FrameLayout_SAVE_DISABLED_MASK -#define android_widget_FrameLayout_SAVE_DISABLED_MASK 65536L -#undef android_widget_FrameLayout_WILL_NOT_CACHE_DRAWING -#define android_widget_FrameLayout_WILL_NOT_CACHE_DRAWING 131072L -#undef android_widget_FrameLayout_FOCUSABLE_IN_TOUCH_MODE -#define android_widget_FrameLayout_FOCUSABLE_IN_TOUCH_MODE 262144L -#undef android_widget_FrameLayout_DRAWING_CACHE_QUALITY_LOW -#define android_widget_FrameLayout_DRAWING_CACHE_QUALITY_LOW 524288L -#undef android_widget_FrameLayout_DRAWING_CACHE_QUALITY_HIGH -#define android_widget_FrameLayout_DRAWING_CACHE_QUALITY_HIGH 1048576L -#undef android_widget_FrameLayout_DRAWING_CACHE_QUALITY_AUTO -#define android_widget_FrameLayout_DRAWING_CACHE_QUALITY_AUTO 0L -#undef android_widget_FrameLayout_DRAWING_CACHE_QUALITY_MASK -#define android_widget_FrameLayout_DRAWING_CACHE_QUALITY_MASK 1572864L -#undef android_widget_FrameLayout_LONG_CLICKABLE -#define android_widget_FrameLayout_LONG_CLICKABLE 2097152L -#undef android_widget_FrameLayout_DUPLICATE_PARENT_STATE -#define android_widget_FrameLayout_DUPLICATE_PARENT_STATE 4194304L -#undef android_widget_FrameLayout_SCROLLBARS_INSIDE_OVERLAY -#define android_widget_FrameLayout_SCROLLBARS_INSIDE_OVERLAY 0L -#undef android_widget_FrameLayout_SCROLLBARS_INSIDE_INSET -#define android_widget_FrameLayout_SCROLLBARS_INSIDE_INSET 16777216L -#undef android_widget_FrameLayout_SCROLLBARS_OUTSIDE_OVERLAY -#define android_widget_FrameLayout_SCROLLBARS_OUTSIDE_OVERLAY 33554432L -#undef android_widget_FrameLayout_SCROLLBARS_OUTSIDE_INSET -#define android_widget_FrameLayout_SCROLLBARS_OUTSIDE_INSET 50331648L -#undef android_widget_FrameLayout_SCROLLBARS_INSET_MASK -#define android_widget_FrameLayout_SCROLLBARS_INSET_MASK 16777216L -#undef android_widget_FrameLayout_SCROLLBARS_OUTSIDE_MASK -#define android_widget_FrameLayout_SCROLLBARS_OUTSIDE_MASK 33554432L -#undef android_widget_FrameLayout_SCROLLBARS_STYLE_MASK -#define android_widget_FrameLayout_SCROLLBARS_STYLE_MASK 50331648L -#undef android_widget_FrameLayout_KEEP_SCREEN_ON -#define android_widget_FrameLayout_KEEP_SCREEN_ON 67108864L -#undef android_widget_FrameLayout_SOUND_EFFECTS_ENABLED -#define android_widget_FrameLayout_SOUND_EFFECTS_ENABLED 134217728L -#undef android_widget_FrameLayout_HAPTIC_FEEDBACK_ENABLED -#define android_widget_FrameLayout_HAPTIC_FEEDBACK_ENABLED 268435456L -#undef android_widget_FrameLayout_PARENT_SAVE_DISABLED -#define android_widget_FrameLayout_PARENT_SAVE_DISABLED 536870912L -#undef android_widget_FrameLayout_PARENT_SAVE_DISABLED_MASK -#define android_widget_FrameLayout_PARENT_SAVE_DISABLED_MASK 536870912L -#undef android_widget_FrameLayout_FOCUSABLES_ALL -#define android_widget_FrameLayout_FOCUSABLES_ALL 0L -#undef android_widget_FrameLayout_FOCUSABLES_TOUCH_MODE -#define android_widget_FrameLayout_FOCUSABLES_TOUCH_MODE 1L -#undef android_widget_FrameLayout_FOCUS_BACKWARD -#define android_widget_FrameLayout_FOCUS_BACKWARD 1L -#undef android_widget_FrameLayout_FOCUS_FORWARD -#define android_widget_FrameLayout_FOCUS_FORWARD 2L -#undef android_widget_FrameLayout_FOCUS_LEFT -#define android_widget_FrameLayout_FOCUS_LEFT 17L -#undef android_widget_FrameLayout_FOCUS_UP -#define android_widget_FrameLayout_FOCUS_UP 33L -#undef android_widget_FrameLayout_FOCUS_RIGHT -#define android_widget_FrameLayout_FOCUS_RIGHT 66L -#undef android_widget_FrameLayout_FOCUS_DOWN -#define android_widget_FrameLayout_FOCUS_DOWN 130L -#undef android_widget_FrameLayout_MEASURED_SIZE_MASK -#define android_widget_FrameLayout_MEASURED_SIZE_MASK 16777215L -#undef android_widget_FrameLayout_MEASURED_STATE_MASK -#define android_widget_FrameLayout_MEASURED_STATE_MASK -16777216L -#undef android_widget_FrameLayout_MEASURED_HEIGHT_STATE_SHIFT -#define android_widget_FrameLayout_MEASURED_HEIGHT_STATE_SHIFT 16L -#undef android_widget_FrameLayout_MEASURED_STATE_TOO_SMALL -#define android_widget_FrameLayout_MEASURED_STATE_TOO_SMALL 16777216L -#undef android_widget_FrameLayout_PFLAG2_DRAG_CAN_ACCEPT -#define android_widget_FrameLayout_PFLAG2_DRAG_CAN_ACCEPT 1L -#undef android_widget_FrameLayout_PFLAG2_DRAG_HOVERED -#define android_widget_FrameLayout_PFLAG2_DRAG_HOVERED 2L -#undef android_widget_FrameLayout_LAYOUT_DIRECTION_LTR -#define android_widget_FrameLayout_LAYOUT_DIRECTION_LTR 0L -#undef android_widget_FrameLayout_LAYOUT_DIRECTION_RTL -#define android_widget_FrameLayout_LAYOUT_DIRECTION_RTL 1L -#undef android_widget_FrameLayout_LAYOUT_DIRECTION_INHERIT -#define android_widget_FrameLayout_LAYOUT_DIRECTION_INHERIT 2L -#undef android_widget_FrameLayout_LAYOUT_DIRECTION_LOCALE -#define android_widget_FrameLayout_LAYOUT_DIRECTION_LOCALE 3L -#undef android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT -#define android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT 2L -#undef android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_MASK -#define android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_MASK 12L -#undef android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL -#define android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 16L -#undef android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_RESOLVED -#define android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_RESOLVED 32L -#undef android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK -#define android_widget_FrameLayout_PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 48L -#undef android_widget_FrameLayout_STATUS_BAR_HIDDEN -#define android_widget_FrameLayout_STATUS_BAR_HIDDEN 1L -#undef android_widget_FrameLayout_STATUS_BAR_VISIBLE -#define android_widget_FrameLayout_STATUS_BAR_VISIBLE 0L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_FULLSCREEN -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_FULLSCREEN 4L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_HIDE_NAVIGATION -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_HIDE_NAVIGATION 2L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_IMMERSIVE -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_IMMERSIVE 2048L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_IMMERSIVE_STICKY -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_IMMERSIVE_STICKY 4096L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 1024L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 512L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_LAYOUT_STABLE -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_LAYOUT_STABLE 256L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_LOW_PROFILE -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_LOW_PROFILE 1L -#undef android_widget_FrameLayout_SYSTEM_UI_FLAG_VISIBLE -#define android_widget_FrameLayout_SYSTEM_UI_FLAG_VISIBLE 0L -#undef android_widget_FrameLayout_SYSTEM_UI_LAYOUT_FLAGS -#define android_widget_FrameLayout_SYSTEM_UI_LAYOUT_FLAGS 1536L -#undef android_widget_FrameLayout_TEXT_ALIGNMENT_CENTER -#define android_widget_FrameLayout_TEXT_ALIGNMENT_CENTER 4L -#undef android_widget_FrameLayout_TEXT_ALIGNMENT_GRAVITY -#define android_widget_FrameLayout_TEXT_ALIGNMENT_GRAVITY 1L -#undef android_widget_FrameLayout_TEXT_ALIGNMENT_INHERIT -#define android_widget_FrameLayout_TEXT_ALIGNMENT_INHERIT 0L -#undef android_widget_FrameLayout_TEXT_ALIGNMENT_TEXT_END -#define android_widget_FrameLayout_TEXT_ALIGNMENT_TEXT_END 3L -#undef android_widget_FrameLayout_TEXT_ALIGNMENT_TEXT_START -#define android_widget_FrameLayout_TEXT_ALIGNMENT_TEXT_START 2L -#undef android_widget_FrameLayout_TEXT_ALIGNMENT_VIEW_END -#define android_widget_FrameLayout_TEXT_ALIGNMENT_VIEW_END 6L -#undef android_widget_FrameLayout_TEXT_ALIGNMENT_VIEW_START -#define android_widget_FrameLayout_TEXT_ALIGNMENT_VIEW_START 5L -#undef android_widget_FrameLayout_TEXT_DIRECTION_ANY_RTL -#define android_widget_FrameLayout_TEXT_DIRECTION_ANY_RTL 2L -#undef android_widget_FrameLayout_TEXT_DIRECTION_FIRST_STRONG -#define android_widget_FrameLayout_TEXT_DIRECTION_FIRST_STRONG 1L -#undef android_widget_FrameLayout_TEXT_DIRECTION_INHERIT -#define android_widget_FrameLayout_TEXT_DIRECTION_INHERIT 0L -#undef android_widget_FrameLayout_TEXT_DIRECTION_LOCALE -#define android_widget_FrameLayout_TEXT_DIRECTION_LOCALE 5L -#undef android_widget_FrameLayout_TEXT_DIRECTION_LTR -#define android_widget_FrameLayout_TEXT_DIRECTION_LTR 3L -#undef android_widget_FrameLayout_TEXT_DIRECTION_RTL -#define android_widget_FrameLayout_TEXT_DIRECTION_RTL 4L -/* - * Class: android_widget_FrameLayout - * Method: native_constructor - * Signature: (Landroid/content/Context;Landroid/util/AttributeSet;)J - */ -JNIEXPORT jlong JNICALL Java_android_widget_FrameLayout_native_1constructor - (JNIEnv *, jobject, jobject, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/api-impl-jni/widgets/android_widget_FrameLayout.c b/src/api-impl-jni/widgets/android_widget_FrameLayout.c deleted file mode 100644 index 965ab90c..00000000 --- a/src/api-impl-jni/widgets/android_widget_FrameLayout.c +++ /dev/null @@ -1,84 +0,0 @@ -#include - -#include "../defines.h" -#include "../util.h" - -#include "WrapperWidget.h" - -#include "../generated_headers/android_widget_FrameLayout.h" -#include "../generated_headers/android_view_ViewGroup.h" - -G_DECLARE_FINAL_TYPE (FrameLayoutWidget, frame_layout_widget, FRAME_LAYOUT, WIDGET, GtkWidget) - -struct _FrameLayoutWidget -{ - GtkWidget parent_instance; -}; - -struct _FrameLayoutWidgetClass -{ - GtkWidgetClass parent_class; -}; - -G_DEFINE_TYPE(FrameLayoutWidget, frame_layout_widget, GTK_TYPE_WIDGET) - -static void frame_layout_widget_init (FrameLayoutWidget *frame_layout) -{ - -} - -static void frame_layout_widget_dispose(GObject *frame_layout) -{ - GtkWidget *child; - while((child = gtk_widget_get_first_child(GTK_WIDGET(frame_layout))) != NULL) { - gtk_widget_unparent(child); - } - - G_OBJECT_CLASS (frame_layout_widget_parent_class)->dispose (frame_layout); -} - -static void frame_layout_widget_class_init(FrameLayoutWidgetClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); - - object_class->dispose = frame_layout_widget_dispose; - - gtk_widget_class_set_layout_manager_type(widget_class, GTK_TYPE_BIN_LAYOUT); -} - -GtkWidget * frame_layout_widget_new (void) -{ - return g_object_new (frame_layout_widget_get_type(), NULL); -} - -void frame_layout_widget_insert_child(FrameLayoutWidget *parent, GtkWidget *child) -{ - printf("::::::::::: FrameLayoutWidget: inserting something at the end of the widget list\n"); - gtk_widget_insert_before(child, GTK_WIDGET(parent), NULL); -} - -void frame_layout_widget_insert_child_at_index(FrameLayoutWidget *parent, GtkWidget *child, int index) -{ - printf("::::::::::: FrameLayoutWidget: inserting something at index %d\n", index); - GtkWidget *iter = gtk_widget_get_first_child(GTK_WIDGET(parent)); - for(int i = 0; i < index; i++) { - iter = gtk_widget_get_next_sibling(iter); - if(iter == NULL) - break; - } - - gtk_widget_insert_before(child, GTK_WIDGET(parent), iter); -} - -// --- - -JNIEXPORT jlong JNICALL Java_android_widget_FrameLayout_native_1constructor(JNIEnv *env, jobject this, jobject context, jobject attrs) -{ - GtkWidget *wrapper = g_object_ref(wrapper_widget_new()); - GtkWidget *frame_layout = frame_layout_widget_new(); - wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), frame_layout); - wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this); - gtk_widget_set_name(GTK_WIDGET(frame_layout), "FrameLayout"); - return _INTPTR(frame_layout); -} diff --git a/src/api-impl/android/view/ViewGroup.java b/src/api-impl/android/view/ViewGroup.java index 79cd6b99..31eccd33 100644 --- a/src/api-impl/android/view/ViewGroup.java +++ b/src/api-impl/android/view/ViewGroup.java @@ -34,6 +34,12 @@ public class ViewGroup extends View implements ViewParent, ViewManager { children = new ArrayList(); } + public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr); + + children = new ArrayList(); + } + public ViewGroup(int _id) { // FIXME children = new ArrayList(); diff --git a/src/api-impl/android/widget/FrameLayout.java b/src/api-impl/android/widget/FrameLayout.java index e2789e5a..48727fa2 100644 --- a/src/api-impl/android/widget/FrameLayout.java +++ b/src/api-impl/android/widget/FrameLayout.java @@ -1,58 +1,386 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * 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 android.widget; import android.content.Context; +import android.content.res.TypedArray; import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; import android.view.ViewGroup; +import com.android.internal.R; +import java.util.ArrayList; +/** + * FrameLayout is designed to block out an area on the screen to display + * a single item. Generally, FrameLayout should be used to hold a single child view, because it can + * be difficult to organize child views in a way that's scalable to different screen sizes without + * the children overlapping each other. You can, however, add multiple children to a FrameLayout + * and control their position within the FrameLayout by assigning gravity to each child, using the + * {@code + * android:layout_gravity} attribute. + *

Child views are drawn in a stack, with the most recently added child on top. + * The size of the FrameLayout is the size of its largest child (plus padding), visible + * or not (if the FrameLayout's parent permits). Views that are {@link android.view.View#GONE} are + * used for sizing + * only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()} + * is set to true. + * + * @attr ref android.R.styleable#FrameLayout_measureAllChildren + */ public class FrameLayout extends ViewGroup { - - public FrameLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } + private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START; + boolean mMeasureAllChildren = false; + // private int mForegroundPaddingLeft = 0; + // private int mForegroundPaddingTop = 0; + // private int mForegroundPaddingRight = 0; + // private int mForegroundPaddingBottom = 0; + private final ArrayList mMatchParentChildren = new ArrayList<>(1); public FrameLayout(Context context) { super(context); } - public FrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); + public FrameLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); } - @Override - protected native long native_constructor(Context context, AttributeSet attrs); - - @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); + public FrameLayout(Context context, AttributeSet attrs, + int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); } + public FrameLayout(Context context, AttributeSet attrs, + int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.FrameLayout, defStyleAttr, defStyleRes); + // saveAttributeDataForStyleable(context, R.styleable.FrameLayout, + // attrs, a, defStyleAttr, defStyleRes); + if (a.getBoolean(R.styleable.FrameLayout_measureAllChildren, false)) { + setMeasureAllChildren(true); + } + a.recycle(); + } + + /** + * Returns a set of layout parameters with a width of + * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, + * and a height of {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}. + */ @Override protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } - public static class LayoutParams extends ViewGroup.MarginLayoutParams { - public LayoutParams (Context c, AttributeSet attrs) { + int getPaddingLeftWithForeground() { + // return isForegroundInsidePadding() ? Math.max(mPaddingLeft, mForegroundPaddingLeft) : + // mPaddingLeft + mForegroundPaddingLeft; + return 0; + } + + int getPaddingRightWithForeground() { + // return isForegroundInsidePadding() ? Math.max(mPaddingRight, mForegroundPaddingRight) : + // mPaddingRight + mForegroundPaddingRight; + return 0; + } + + private int getPaddingTopWithForeground() { + // return isForegroundInsidePadding() ? Math.max(mPaddingTop, mForegroundPaddingTop) : + // mPaddingTop + mForegroundPaddingTop; + return 0; + } + + private int getPaddingBottomWithForeground() { + // return isForegroundInsidePadding() ? Math.max(mPaddingBottom, mForegroundPaddingBottom) : + // mPaddingBottom + mForegroundPaddingBottom; + return 0; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int count = getChildCount(); + final boolean measureMatchParentChildren = + MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || + MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; + mMatchParentChildren.clear(); + int maxHeight = 0; + int maxWidth = 0; + int childState = 0; + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (mMeasureAllChildren || child.getVisibility() != GONE) { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + maxWidth = Math.max(maxWidth, + child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); + maxHeight = Math.max(maxHeight, + child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); + childState = combineMeasuredStates(childState, child.getMeasuredState()); + if (measureMatchParentChildren) { + if (lp.width == LayoutParams.MATCH_PARENT || + lp.height == LayoutParams.MATCH_PARENT) { + mMatchParentChildren.add(child); + } + } + } + } + // Account for padding too + maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground(); + maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground(); + // Check against our minimum height and width + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + // Check against our foreground's minimum height and width + // final Drawable drawable = getForeground(); + // if (drawable != null) { + // maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); + // maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); + // } + setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), + resolveSizeAndState(maxHeight, heightMeasureSpec, + childState << MEASURED_HEIGHT_STATE_SHIFT)); + count = mMatchParentChildren.size(); + if (count > 1) { + for (int i = 0; i < count; i++) { + final View child = mMatchParentChildren.get(i); + final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); + final int childWidthMeasureSpec; + if (lp.width == LayoutParams.MATCH_PARENT) { + final int width = Math.max(0, getMeasuredWidth() + - getPaddingLeftWithForeground() - getPaddingRightWithForeground() + - lp.leftMargin - lp.rightMargin); + childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + width, MeasureSpec.EXACTLY); + } else { + childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, + getPaddingLeftWithForeground() + getPaddingRightWithForeground() + + lp.leftMargin + lp.rightMargin, + lp.width); + } + final int childHeightMeasureSpec; + if (lp.height == LayoutParams.MATCH_PARENT) { + final int height = Math.max(0, getMeasuredHeight() + - getPaddingTopWithForeground() - getPaddingBottomWithForeground() + - lp.topMargin - lp.bottomMargin); + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + height, MeasureSpec.EXACTLY); + } else { + childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, + getPaddingTopWithForeground() + getPaddingBottomWithForeground() + + lp.topMargin + lp.bottomMargin, + lp.height); + } + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + layoutChildren(left, top, right, bottom, false /* no force left gravity */); + } + + void layoutChildren(int left, int top, int right, int bottom, boolean forceLeftGravity) { + final int count = getChildCount(); + final int parentLeft = getPaddingLeftWithForeground(); + final int parentRight = right - left - getPaddingRightWithForeground(); + final int parentTop = getPaddingTopWithForeground(); + final int parentBottom = bottom - top - getPaddingBottomWithForeground(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + int childLeft; + int childTop; + int gravity = lp.gravity; + if (gravity == -1) { + gravity = DEFAULT_CHILD_GRAVITY; + } + final int layoutDirection = getLayoutDirection(); + final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection); + final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; + switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + childLeft = parentLeft + (parentRight - parentLeft - width) / 2 + + lp.leftMargin - lp.rightMargin; + break; + case Gravity.RIGHT: + if (!forceLeftGravity) { + childLeft = parentRight - width - lp.rightMargin; + break; + } + case Gravity.LEFT: + default: + childLeft = parentLeft + lp.leftMargin; + } + switch (verticalGravity) { + case Gravity.TOP: + childTop = parentTop + lp.topMargin; + break; + case Gravity.CENTER_VERTICAL: + childTop = parentTop + (parentBottom - parentTop - height) / 2 + + lp.topMargin - lp.bottomMargin; + break; + case Gravity.BOTTOM: + childTop = parentBottom - height - lp.bottomMargin; + break; + default: + childTop = parentTop + lp.topMargin; + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + } + } + + /** + * Sets whether to consider all children, or just those in + * the VISIBLE or INVISIBLE state, when measuring. Defaults to false. + * + * @param measureAll true to consider children marked GONE, false otherwise. + * Default value is false. + * + * @attr ref android.R.styleable#FrameLayout_measureAllChildren + */ + public void setMeasureAllChildren(boolean measureAll) { + mMeasureAllChildren = measureAll; + } + + /** + * Determines whether all children, or just those in the VISIBLE or + * INVISIBLE state, are considered when measuring. + * + * @return Whether all children are considered when measuring. + * + * @deprecated This method is deprecated in favor of + * {@link #getMeasureAllChildren() getMeasureAllChildren()}, which was + * renamed for consistency with + * {@link #setMeasureAllChildren(boolean) setMeasureAllChildren()}. + */ + @Deprecated + public boolean getConsiderGoneChildrenWhenMeasuring() { + return getMeasureAllChildren(); + } + + /** + * Determines whether all children, or just those in the VISIBLE or + * INVISIBLE state, are considered when measuring. + * + * @return Whether all children are considered when measuring. + */ + public boolean getMeasureAllChildren() { + return mMeasureAllChildren; + } + + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new FrameLayout.LayoutParams(getContext(), attrs); + } + + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams; + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { + // if (sPreserveMarginParamsInLayoutParamConversion) { + // if (lp instanceof LayoutParams) { + // return new LayoutParams((LayoutParams) lp); + // } else if (lp instanceof MarginLayoutParams) { + // return new LayoutParams((MarginLayoutParams) lp); + // } + // } + return new LayoutParams(lp); + } + + /** + * Per-child layout information for layouts that support margins. + * See {@link android.R.styleable#FrameLayout_Layout FrameLayout Layout Attributes} + * for a list of all child view attributes that this class supports. + * + * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity + */ + public static class LayoutParams extends MarginLayoutParams { + /** + * Value for {@link #gravity} indicating that a gravity has not been + * explicitly specified. + */ + public static final int UNSPECIFIED_GRAVITY = -1; + + /** + * The gravity to apply with the View to which these layout parameters + * are associated. + *

+ * The default value is {@link #UNSPECIFIED_GRAVITY}, which is treated + * by FrameLayout as {@code Gravity.TOP | Gravity.START}. + * + * @see android.view.Gravity + * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity + */ + public int gravity = UNSPECIFIED_GRAVITY; + + public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); + final TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.FrameLayout_Layout); + gravity = a.getInt(R.styleable.FrameLayout_Layout_layout_gravity, UNSPECIFIED_GRAVITY); + a.recycle(); } public LayoutParams(int width, int height) { super(width, height); } - public LayoutParams(int width, int height, float weight) { - super(width, height, weight); - } - + /** + * Creates a new set of layout parameters with the specified width, height + * and gravity. + * + * @param width the width, either {@link #MATCH_PARENT}, + * {@link #WRAP_CONTENT} or a fixed size in pixels + * @param height the height, either {@link #MATCH_PARENT}, + * {@link #WRAP_CONTENT} or a fixed size in pixels + * @param gravity the gravity + * + * @see android.view.Gravity + */ public LayoutParams(int width, int height, int gravity) { - this.width = width; - this.height = height; + super(width, height); this.gravity = gravity; } - public LayoutParams (ViewGroup.LayoutParams params) { - this.width = params.width; - this.height = params.height; + public LayoutParams(ViewGroup.LayoutParams source) { + super(source); + } + + public LayoutParams(ViewGroup.MarginLayoutParams source) { + super(source); + } + + /** + * Copy constructor. Clones the width, height, margin values, and + * gravity of the source. + * + * @param source The layout params to copy from. + */ + public LayoutParams(LayoutParams source) { + super(source); + this.gravity = source.gravity; } } }