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
This commit is contained in:
Julian Winkler
2023-11-08 18:13:47 +01:00
parent 6ef1e523cc
commit d025fd3ce3
5 changed files with 357 additions and 321 deletions

View File

@@ -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',

View File

@@ -1,213 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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

View File

@@ -1,84 +0,0 @@
#include <gtk/gtk.h>
#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);
}

View File

@@ -34,6 +34,12 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
children = new ArrayList<View>();
}
public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr);
children = new ArrayList<View>();
}
public ViewGroup(int _id) { // FIXME
children = new ArrayList<View>();

View File

@@ -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
* <a href="FrameLayout.LayoutParams.html#attr_android:layout_gravity">{@code
* android:layout_gravity}</a> attribute.
* <p>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<View> 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.
* <p>
* 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;
}
}
}