2022-10-02 23:06:56 +02:00
|
|
|
package android.view;
|
|
|
|
|
2023-08-17 10:46:24 +02:00
|
|
|
import android.R;
|
|
|
|
import android.animation.LayoutTransition;
|
2022-10-02 23:06:56 +02:00
|
|
|
import android.content.Context;
|
2023-08-17 10:46:24 +02:00
|
|
|
import android.content.res.TypedArray;
|
2024-11-27 14:59:37 +01:00
|
|
|
import android.graphics.Canvas;
|
2024-11-30 17:58:31 +01:00
|
|
|
import android.graphics.GskCanvas;
|
2024-12-20 00:11:06 +01:00
|
|
|
import android.graphics.Rect;
|
2023-06-22 11:45:46 +02:00
|
|
|
import android.util.AttributeSet;
|
2024-12-20 00:11:06 +01:00
|
|
|
import android.util.Slog;
|
2022-10-02 23:06:56 +02:00
|
|
|
import java.util.ArrayList;
|
2023-08-17 12:59:37 +02:00
|
|
|
import java.util.Iterator;
|
2024-08-25 11:20:01 +02:00
|
|
|
import java.util.Objects;
|
2022-10-02 23:06:56 +02:00
|
|
|
|
|
|
|
public class ViewGroup extends View implements ViewParent, ViewManager {
|
|
|
|
public ArrayList<View> children;
|
2025-03-25 19:55:31 +01:00
|
|
|
private ArrayList<View> detachedChildren;
|
2024-03-16 12:49:28 +01:00
|
|
|
private OnHierarchyChangeListener onHierarchyChangeListener;
|
2024-11-22 18:02:54 +01:00
|
|
|
private LayoutTransition transition;
|
2022-10-02 23:06:56 +02:00
|
|
|
|
|
|
|
public ViewGroup(Context context) {
|
2023-12-29 11:05:05 +01:00
|
|
|
this(context, null);
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
|
2023-07-14 18:02:04 +02:00
|
|
|
public ViewGroup(Context context, AttributeSet attrs) {
|
2023-12-29 11:05:05 +01:00
|
|
|
this(context, attrs, 0);
|
2023-07-14 18:02:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
|
2023-12-29 11:05:05 +01:00
|
|
|
this(context, attrs, defStyleAttr, 0);
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
|
2023-11-08 18:13:47 +01:00
|
|
|
public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
|
|
|
super(context, attrs, defStyleAttr);
|
|
|
|
|
|
|
|
children = new ArrayList<View>();
|
2025-03-25 19:55:31 +01:00
|
|
|
detachedChildren = new ArrayList<View>();
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addView(View child) {
|
2023-09-01 13:16:01 +02:00
|
|
|
addView(child, -1);
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addView(View child, int index) {
|
2023-09-01 13:16:01 +02:00
|
|
|
LayoutParams params = child.getLayoutParams();
|
|
|
|
if (params == null) {
|
|
|
|
params = generateDefaultLayoutParams();
|
|
|
|
}
|
|
|
|
addView(child, index, params);
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addView(View child, LayoutParams params) {
|
|
|
|
addView(child, -1, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addView(View child, int width, int height) {
|
2023-09-01 13:16:01 +02:00
|
|
|
final LayoutParams params = generateDefaultLayoutParams();
|
|
|
|
params.width = width;
|
|
|
|
params.height = height;
|
|
|
|
addView(child, params);
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
|
2024-01-01 12:11:31 +01:00
|
|
|
protected void addViewInternal(View child, int index, LayoutParams params) {
|
2023-08-22 14:41:01 +02:00
|
|
|
if (child.parent == this)
|
|
|
|
return;
|
2024-04-03 01:51:26 +02:00
|
|
|
if (!checkLayoutParams(params))
|
2023-09-01 13:16:01 +02:00
|
|
|
params = generateLayoutParams(params);
|
2024-04-03 01:51:26 +02:00
|
|
|
|
2023-08-17 12:59:37 +02:00
|
|
|
child.parent = this;
|
2023-11-10 23:28:17 +01:00
|
|
|
child.setLayoutParams(params);
|
2023-08-23 09:30:38 +02:00
|
|
|
if (index < 0)
|
|
|
|
index = children.size();
|
|
|
|
children.add(index, child);
|
2023-08-17 12:59:37 +02:00
|
|
|
native_addView(widget, child.widget, index, params);
|
2024-04-03 01:51:26 +02:00
|
|
|
if (isAttachedToWindow())
|
2023-10-08 17:51:41 +02:00
|
|
|
child.onAttachedToWindow();
|
2024-04-03 01:51:26 +02:00
|
|
|
if (onHierarchyChangeListener != null)
|
2024-03-16 12:49:28 +01:00
|
|
|
onHierarchyChangeListener.onChildViewAdded(this, child);
|
2024-04-03 01:51:26 +02:00
|
|
|
|
2023-09-01 13:16:01 +02:00
|
|
|
requestLayout();
|
2023-08-17 12:59:37 +02:00
|
|
|
}
|
|
|
|
|
2023-08-23 09:16:45 +02:00
|
|
|
public void addView(View child, int index, LayoutParams params) {
|
|
|
|
addViewInternal(child, index, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected boolean addViewInLayout(View child, int index, LayoutParams params) {
|
|
|
|
addViewInternal(child, index, params);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-11-27 14:59:37 +01:00
|
|
|
protected boolean addViewInLayout(View child, int index, LayoutParams params, boolean preventRequestLayout) {
|
|
|
|
addViewInternal(child, index, params);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-03-27 22:47:11 +01:00
|
|
|
// This internal method is used to share code between removeView and removeViewInLayout.
|
|
|
|
// Reusing removeView in removeViewInLayout is not possible, because e.g.
|
|
|
|
// ViewPager overrides removeView to call removeViewInLayout
|
|
|
|
protected void removeViewInternal(View child) {
|
2024-09-27 15:11:00 +02:00
|
|
|
if (child == null || child.parent != this)
|
2023-08-22 14:41:01 +02:00
|
|
|
return;
|
2023-08-17 12:59:37 +02:00
|
|
|
child.parent = null;
|
|
|
|
children.remove(child);
|
|
|
|
native_removeView(widget, child.widget);
|
2024-07-26 21:47:08 +02:00
|
|
|
if (isAttachedToWindow())
|
2025-02-18 19:04:18 +01:00
|
|
|
child.detachFromWindowInternal();
|
2024-03-16 12:49:28 +01:00
|
|
|
if (onHierarchyChangeListener != null) {
|
|
|
|
onHierarchyChangeListener.onChildViewRemoved(this, child);
|
|
|
|
}
|
2023-08-17 12:59:37 +02:00
|
|
|
}
|
|
|
|
|
2024-03-27 22:47:11 +01:00
|
|
|
public void removeView(View child) {
|
|
|
|
removeViewInternal(child);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeViewInLayout(View child) {
|
|
|
|
removeViewInternal(child);
|
|
|
|
}
|
|
|
|
|
2023-08-22 14:41:01 +02:00
|
|
|
public void removeViewAt(int index) {
|
|
|
|
removeView(children.get(index));
|
|
|
|
}
|
|
|
|
|
2023-08-17 12:59:37 +02:00
|
|
|
public void removeAllViews() {
|
|
|
|
for (Iterator<View> it = children.iterator(); it.hasNext();) {
|
|
|
|
View child = it.next();
|
|
|
|
child.parent = null;
|
|
|
|
it.remove();
|
|
|
|
native_removeView(widget, child.widget);
|
2024-07-26 21:47:08 +02:00
|
|
|
if (isAttachedToWindow())
|
2025-02-18 19:04:18 +01:00
|
|
|
child.detachFromWindowInternal();
|
2024-03-16 12:49:28 +01:00
|
|
|
if (onHierarchyChangeListener != null) {
|
|
|
|
onHierarchyChangeListener.onChildViewRemoved(this, child);
|
|
|
|
}
|
2023-08-17 12:59:37 +02:00
|
|
|
}
|
|
|
|
}
|
2022-10-02 23:06:56 +02:00
|
|
|
|
2023-08-22 14:41:01 +02:00
|
|
|
public void detachViewFromParent(int index) {
|
2025-03-25 19:55:31 +01:00
|
|
|
View child = children.remove(index);
|
|
|
|
child.parent = null;
|
|
|
|
detachedChildren.add(child);
|
2023-08-22 14:41:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void attachViewToParent(View view, int index, LayoutParams params) {
|
2025-03-25 19:55:31 +01:00
|
|
|
if (!detachedChildren.remove(view)) {
|
|
|
|
addViewInternal(view, index, params);
|
|
|
|
}
|
2025-03-23 18:29:30 +01:00
|
|
|
if (!checkLayoutParams(params))
|
|
|
|
params = generateLayoutParams(params);
|
|
|
|
|
|
|
|
view.parent = this;
|
|
|
|
view.setLayoutParams(params);
|
|
|
|
if (index < 0)
|
|
|
|
index = children.size();
|
|
|
|
children.add(index, view);
|
2023-08-22 14:41:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void removeDetachedView(View child, boolean animate) {
|
2025-03-25 19:55:31 +01:00
|
|
|
if (!detachedChildren.remove(child))
|
|
|
|
return;
|
|
|
|
child.parent = null;
|
2025-03-23 18:29:30 +01:00
|
|
|
native_removeView(widget, child.widget);
|
|
|
|
if (isAttachedToWindow())
|
|
|
|
child.detachFromWindowInternal();
|
|
|
|
if (onHierarchyChangeListener != null) {
|
|
|
|
onHierarchyChangeListener.onChildViewRemoved(this, child);
|
|
|
|
}
|
2023-08-22 14:41:01 +02:00
|
|
|
}
|
|
|
|
|
2023-08-17 12:59:37 +02:00
|
|
|
protected native void native_addView(long widget, long child, int index, LayoutParams params);
|
|
|
|
protected native void native_removeView(long widget, long child);
|
2024-05-26 15:53:24 +02:00
|
|
|
@Override
|
|
|
|
protected native void native_drawChildren(long widget, long snapshot);
|
2024-11-30 17:58:31 +01:00
|
|
|
protected native void native_drawChild(long widget, long child, long snapshot);
|
2024-05-26 15:53:24 +02:00
|
|
|
@Override
|
|
|
|
protected void native_drawContent(long widget, long snapshot) {}
|
2022-10-02 23:06:56 +02:00
|
|
|
|
|
|
|
public View getChildAt(int index) {
|
2023-09-01 12:39:20 +02:00
|
|
|
try {
|
|
|
|
return children.get(index);
|
|
|
|
} catch (IndexOutOfBoundsException e) {
|
|
|
|
return null;
|
|
|
|
}
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
|
2023-08-22 14:41:01 +02:00
|
|
|
public int indexOfChild(View child) {
|
|
|
|
return children.indexOf(child);
|
|
|
|
}
|
|
|
|
|
2024-03-16 15:03:06 +01:00
|
|
|
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
|
2024-04-03 01:51:26 +02:00
|
|
|
view.setLayoutParams(params);
|
2024-03-16 15:03:06 +01:00
|
|
|
view.requestLayout();
|
|
|
|
}
|
2022-10-02 23:06:56 +02:00
|
|
|
|
|
|
|
public LayoutParams generateLayoutParams(AttributeSet attrs) {
|
2023-07-14 20:09:10 +02:00
|
|
|
return new LayoutParams(getContext(), attrs);
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
2023-09-01 12:55:04 +02:00
|
|
|
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
|
|
|
|
return p;
|
|
|
|
}
|
2022-10-02 23:06:56 +02:00
|
|
|
|
2022-11-24 23:10:27 +01:00
|
|
|
public void bringChildToFront(View child) {
|
|
|
|
// TODO: actually implement this (might make sense to implement it in the subclasses instead), when applicable
|
|
|
|
}
|
|
|
|
|
2023-06-18 11:03:43 +02:00
|
|
|
/**
|
2023-06-22 11:45:46 +02:00
|
|
|
* Returns the number of children in the group.
|
|
|
|
*
|
|
|
|
* @return a positive integer representing the number of children in
|
|
|
|
* the group
|
|
|
|
*/
|
|
|
|
public int getChildCount() {
|
|
|
|
return children.size();
|
|
|
|
}
|
2023-06-18 11:03:43 +02:00
|
|
|
|
2023-07-14 20:09:10 +02:00
|
|
|
public void setMotionEventSplittingEnabled(boolean enabled) {}
|
|
|
|
|
2024-03-16 12:49:28 +01:00
|
|
|
public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
|
|
|
|
this.onHierarchyChangeListener = listener;
|
|
|
|
}
|
2023-07-14 20:09:10 +02:00
|
|
|
|
2023-09-01 12:55:04 +02:00
|
|
|
protected boolean checkLayoutParams(LayoutParams params) {
|
2023-07-14 20:09:10 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-11-22 18:02:54 +01:00
|
|
|
public LayoutTransition getLayoutTransition() {
|
|
|
|
return transition;
|
|
|
|
}
|
2023-08-17 10:46:24 +02:00
|
|
|
|
|
|
|
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
|
|
|
|
int specMode = MeasureSpec.getMode(spec);
|
|
|
|
int specSize = MeasureSpec.getSize(spec);
|
|
|
|
int size = Math.max(0, specSize - padding);
|
|
|
|
int resultSize = 0;
|
|
|
|
int resultMode = 0;
|
|
|
|
switch (specMode) {
|
2024-03-14 12:36:06 +01:00
|
|
|
// Parent has imposed an exact size on us
|
|
|
|
case MeasureSpec.EXACTLY:
|
|
|
|
if (childDimension >= 0) {
|
|
|
|
resultSize = childDimension;
|
|
|
|
resultMode = MeasureSpec.EXACTLY;
|
|
|
|
} else if (childDimension == LayoutParams.MATCH_PARENT) {
|
|
|
|
// Child wants to be our size. So be it.
|
|
|
|
resultSize = size;
|
|
|
|
resultMode = MeasureSpec.EXACTLY;
|
|
|
|
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
|
|
|
|
// Child wants to determine its own size. It can't be
|
|
|
|
// bigger than us.
|
|
|
|
resultSize = size;
|
|
|
|
resultMode = MeasureSpec.AT_MOST;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
// Parent has imposed a maximum size on us
|
|
|
|
case MeasureSpec.AT_MOST:
|
|
|
|
if (childDimension >= 0) {
|
|
|
|
// Child wants a specific size... so be it
|
|
|
|
resultSize = childDimension;
|
|
|
|
resultMode = MeasureSpec.EXACTLY;
|
|
|
|
} else if (childDimension == LayoutParams.MATCH_PARENT) {
|
|
|
|
// Child wants to be our size, but our size is not fixed.
|
|
|
|
// Constrain child to not be bigger than us.
|
|
|
|
resultSize = size;
|
|
|
|
resultMode = MeasureSpec.AT_MOST;
|
|
|
|
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
|
|
|
|
// Child wants to determine its own size. It can't be
|
|
|
|
// bigger than us.
|
|
|
|
resultSize = size;
|
|
|
|
resultMode = MeasureSpec.AT_MOST;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
// Parent asked to see how big we want to be
|
|
|
|
case MeasureSpec.UNSPECIFIED:
|
|
|
|
if (childDimension >= 0) {
|
|
|
|
// Child wants a specific size... let them have it
|
|
|
|
resultSize = childDimension;
|
|
|
|
resultMode = MeasureSpec.EXACTLY;
|
|
|
|
} else if (childDimension == LayoutParams.MATCH_PARENT) {
|
|
|
|
// Child wants to be our size... find out how big it should
|
|
|
|
// be
|
|
|
|
resultSize = 0; // View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
|
|
|
|
resultMode = MeasureSpec.UNSPECIFIED;
|
|
|
|
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
|
|
|
|
// Child wants to determine its own size.... find out how
|
|
|
|
// big it should be
|
|
|
|
resultSize = 0; // View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
|
|
|
|
resultMode = MeasureSpec.UNSPECIFIED;
|
|
|
|
}
|
|
|
|
break;
|
2023-08-17 10:46:24 +02:00
|
|
|
}
|
2024-03-14 12:36:06 +01:00
|
|
|
// noinspection ResourceType
|
2023-08-17 10:46:24 +02:00
|
|
|
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
|
|
|
|
}
|
|
|
|
|
2023-08-22 14:18:33 +02:00
|
|
|
protected void measureChildWithMargins(View child,
|
2024-03-14 12:36:06 +01:00
|
|
|
int parentWidthMeasureSpec, int widthUsed,
|
|
|
|
int parentHeightMeasureSpec, int heightUsed) {
|
|
|
|
final MarginLayoutParams lp = (MarginLayoutParams)child.getLayoutParams();
|
2024-11-15 22:17:07 +01:00
|
|
|
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, paddingLeft + paddingRight + lp.leftMargin + lp.rightMargin + widthUsed, lp.width);
|
|
|
|
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, paddingTop + paddingBottom + lp.topMargin + lp.bottomMargin + heightUsed, lp.height);
|
2023-08-22 14:18:33 +02:00
|
|
|
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
|
|
|
|
}
|
|
|
|
|
2023-09-01 12:55:04 +02:00
|
|
|
protected void measureChild(View child, int parentWidthMeasureSpec,
|
2024-03-14 12:36:06 +01:00
|
|
|
int parentHeightMeasureSpec) {
|
|
|
|
final LayoutParams lp = child.getLayoutParams();
|
2024-11-15 22:17:07 +01:00
|
|
|
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, paddingLeft + paddingRight, lp.width);
|
|
|
|
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, paddingTop + paddingBottom, lp.height);
|
2024-03-14 12:36:06 +01:00
|
|
|
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
|
|
|
|
}
|
2023-09-01 12:55:04 +02:00
|
|
|
|
2024-03-14 12:47:51 +01:00
|
|
|
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
|
|
|
|
for (View child: children) {
|
|
|
|
measureChild(child, widthMeasureSpec, heightMeasureSpec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-22 14:41:01 +02:00
|
|
|
public void setAddStatesFromChildren(boolean addsStates) {}
|
|
|
|
|
2024-03-14 12:36:06 +01:00
|
|
|
public View getFocusedChild() { return null; }
|
2023-08-22 14:41:01 +02:00
|
|
|
|
2024-03-14 12:36:06 +01:00
|
|
|
public int getDescendantFocusability() { return 0; }
|
2023-08-22 14:41:01 +02:00
|
|
|
|
2023-09-01 12:55:04 +02:00
|
|
|
public void startViewTransition(View view) {}
|
|
|
|
public void endViewTransition(View view) {}
|
|
|
|
|
|
|
|
protected LayoutParams generateDefaultLayoutParams() {
|
2024-03-14 12:36:06 +01:00
|
|
|
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
|
|
|
}
|
2023-09-01 12:55:04 +02:00
|
|
|
|
|
|
|
public void focusableViewAvailable(View v) {}
|
2023-09-08 18:32:34 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setGravity(int gravity) {
|
|
|
|
super.setGravity(gravity);
|
|
|
|
// update children as necessary
|
|
|
|
for (View child: children) {
|
|
|
|
LayoutParams params = child.getLayoutParams();
|
|
|
|
if (params.gravity == -1)
|
|
|
|
child.setLayoutParams(params);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-12 23:18:47 +02:00
|
|
|
protected void setChildrenDrawingOrderEnabled(boolean enabled) {}
|
|
|
|
|
2023-09-19 23:22:21 +02:00
|
|
|
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
|
|
|
|
|
2023-10-08 17:51:41 +02:00
|
|
|
@Override
|
|
|
|
protected void onAttachedToWindow() {
|
|
|
|
super.onAttachedToWindow();
|
|
|
|
for (View child: children) {
|
|
|
|
child.onAttachedToWindow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-26 21:47:08 +02:00
|
|
|
@Override
|
2025-02-18 19:04:18 +01:00
|
|
|
protected void detachFromWindowInternal() {
|
|
|
|
super.detachFromWindowInternal();
|
2024-07-26 21:47:08 +02:00
|
|
|
for (View child: children) {
|
2025-02-18 19:04:18 +01:00
|
|
|
child.detachFromWindowInternal();
|
2024-07-26 21:47:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-30 22:35:31 +01:00
|
|
|
protected boolean isChildrenDrawingOrderEnabled() { return false; }
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-11-11 11:45:01 +01:00
|
|
|
@Override
|
|
|
|
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-02-09 16:41:37 +01:00
|
|
|
public void setClipToPadding(boolean clipToPadding) {}
|
|
|
|
|
2024-02-11 12:33:58 +01:00
|
|
|
public View findViewById(int id) {
|
2025-01-11 17:50:21 +01:00
|
|
|
Slog.v(TAG, "findViewById: looking for id: " + String.format("%x", id) + "(" + getResources().getAssets().getResourceName(id) + ")" + " | checking: " + this + ",id: " + String.format("%x", this.getId()) + ", id_str: " + this.getIdName());
|
2024-12-20 00:11:06 +01:00
|
|
|
if (this.id == id) {
|
|
|
|
Slog.v(TAG, "findViewById: found: "+this+" | id: " + String.format("%x", this.getId()) + ", id_str: " + this.getIdName());
|
2024-02-11 12:33:58 +01:00
|
|
|
return this;
|
2024-12-20 00:11:06 +01:00
|
|
|
}
|
2024-02-11 12:33:58 +01:00
|
|
|
for (View child: children) {
|
|
|
|
View result = child.findViewById(id);
|
|
|
|
if (result != null)
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2024-05-23 22:35:13 +02:00
|
|
|
public void detachViewFromParent(View view) {
|
2025-03-23 18:29:30 +01:00
|
|
|
children.remove(view);
|
|
|
|
view.parent = null;
|
2025-03-25 19:55:31 +01:00
|
|
|
detachedChildren.add(view);
|
2024-05-23 22:35:13 +02:00
|
|
|
}
|
|
|
|
|
2024-08-25 11:20:01 +02:00
|
|
|
public void setTouchscreenBlocksFocus(boolean touchscreenBlocksFocus) {}
|
|
|
|
|
|
|
|
public void setClipChildren(boolean clipChildren) {}
|
|
|
|
|
2024-11-23 09:36:42 +01:00
|
|
|
protected void dispatchSetPressed(boolean pressed) {}
|
2024-08-25 11:20:01 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public View findViewWithTag(Object tag) {
|
|
|
|
if (Objects.equals(tag, getTag()))
|
|
|
|
return this;
|
|
|
|
for (View child: children) {
|
|
|
|
View result = child.findViewWithTag(tag);
|
|
|
|
if (result != null)
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2024-11-22 18:02:54 +01:00
|
|
|
public void setLayoutTransition(LayoutTransition transition) {
|
|
|
|
this.transition = transition;
|
|
|
|
}
|
|
|
|
|
2024-11-27 14:59:37 +01:00
|
|
|
public boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
2024-11-30 17:58:31 +01:00
|
|
|
if (canvas instanceof GskCanvas)
|
|
|
|
native_drawChild(widget, child.widget, ((GskCanvas)canvas).snapshot);
|
2024-11-27 14:59:37 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void cleanupLayoutState(View child) {}
|
|
|
|
|
|
|
|
public boolean shouldDelayChildPressedState() { return false; }
|
|
|
|
|
2024-12-10 23:23:14 +01:00
|
|
|
public void removeAllViewsInLayout() {
|
|
|
|
for (int i = getChildCount() - 1; i >= 0; i--) {
|
|
|
|
removeViewInLayout(getChildAt(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-20 00:11:06 +01:00
|
|
|
public void offsetChildrenTopAndBottom(int offset) {
|
|
|
|
// FIXME
|
|
|
|
}
|
|
|
|
|
|
|
|
public final void offsetDescendantRectToMyCoords(View descendant, Rect rect) {
|
|
|
|
// FIXME
|
|
|
|
}
|
|
|
|
|
2025-01-11 18:01:43 +01:00
|
|
|
public boolean getClipToPadding() { return false; }
|
|
|
|
|
2025-02-10 18:19:55 +01:00
|
|
|
public boolean isTransitionGroup() { return false; }
|
|
|
|
|
2022-10-02 23:06:56 +02:00
|
|
|
public static class LayoutParams {
|
|
|
|
public static final int FILL_PARENT = -1;
|
|
|
|
public static final int MATCH_PARENT = -1;
|
|
|
|
public static final int WRAP_CONTENT = -2;
|
|
|
|
|
|
|
|
public int width = 0;
|
|
|
|
public int height = 0;
|
2023-09-08 18:32:34 +02:00
|
|
|
public float weight = 0;
|
2022-10-02 23:06:56 +02:00
|
|
|
public int gravity = -1;
|
|
|
|
|
|
|
|
public LayoutParams() {
|
2023-06-22 11:45:46 +02:00
|
|
|
// FIXME
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public LayoutParams(int width, int height) {
|
|
|
|
this.width = width;
|
|
|
|
this.height = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
public LayoutParams(int width, int height, float weight) {
|
|
|
|
this.width = width;
|
|
|
|
this.height = height;
|
|
|
|
this.weight = weight;
|
|
|
|
}
|
|
|
|
|
2023-07-14 20:09:10 +02:00
|
|
|
public LayoutParams(Context context, AttributeSet attrs) {
|
2023-08-17 10:46:24 +02:00
|
|
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout);
|
2024-03-21 16:19:19 +01:00
|
|
|
setBaseAttributes(a, R.styleable.ViewGroup_Layout_layout_width, R.styleable.ViewGroup_Layout_layout_height);
|
2023-07-14 20:09:10 +02:00
|
|
|
this.gravity = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "layout_gravity", -1);
|
2023-08-17 10:46:24 +02:00
|
|
|
a.recycle();
|
2023-07-14 20:09:10 +02:00
|
|
|
}
|
|
|
|
|
2024-03-21 16:19:19 +01:00
|
|
|
protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
|
|
|
|
width = a.getLayoutDimension(widthAttr, "layout_width");
|
|
|
|
height = a.getLayoutDimension(heightAttr, "layout_height");
|
|
|
|
}
|
|
|
|
|
2024-02-09 16:03:12 +01:00
|
|
|
public void resolveLayoutDirection(int layoutDirection) {}
|
|
|
|
|
2022-10-02 23:06:56 +02:00
|
|
|
/**
|
|
|
|
* Used to animate layouts.
|
|
|
|
*/
|
2024-03-14 12:36:06 +01:00
|
|
|
//public LayoutAnimationController.AnimationParameters layoutAnimationParameters;
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|
2023-06-18 11:03:43 +02:00
|
|
|
|
2023-06-22 11:45:46 +02:00
|
|
|
public static class MarginLayoutParams extends ViewGroup.LayoutParams {
|
2023-08-17 10:46:24 +02:00
|
|
|
public int leftMargin;
|
|
|
|
public int topMargin;
|
|
|
|
public int rightMargin;
|
|
|
|
public int bottomMargin;
|
2023-06-18 11:03:43 +02:00
|
|
|
|
|
|
|
public MarginLayoutParams() {
|
|
|
|
super();
|
|
|
|
}
|
|
|
|
|
2023-09-01 13:16:01 +02:00
|
|
|
public MarginLayoutParams(LayoutParams params) {
|
|
|
|
super();
|
|
|
|
width = params.width;
|
|
|
|
height = params.height;
|
|
|
|
}
|
|
|
|
|
2023-06-22 11:45:46 +02:00
|
|
|
public MarginLayoutParams(int width, int height) {
|
2023-06-18 11:03:43 +02:00
|
|
|
super(width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
public MarginLayoutParams(int width, int height, float weight) {
|
|
|
|
super(width, height, weight);
|
|
|
|
}
|
2023-07-14 20:09:10 +02:00
|
|
|
|
|
|
|
public MarginLayoutParams(Context context, AttributeSet attributeSet) {
|
|
|
|
super(context, attributeSet);
|
2024-11-15 22:17:07 +01:00
|
|
|
TypedArray a = context.obtainStyledAttributes(attributeSet, com.android.internal.R.styleable.ViewGroup_MarginLayout);
|
|
|
|
|
2024-10-24 14:32:21 +02:00
|
|
|
int margin = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_margin, -1);
|
|
|
|
|
2024-11-15 22:17:07 +01:00
|
|
|
int marginVertical = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_marginVertical, -1);
|
|
|
|
int marginHorizontal = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_marginHorizontal, -1);
|
|
|
|
|
|
|
|
int marginStart = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_marginStart, -1);
|
|
|
|
int marginEnd = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_marginEnd, -1);
|
|
|
|
|
|
|
|
leftMargin = 0;
|
|
|
|
topMargin = 0;
|
|
|
|
rightMargin = 0;
|
|
|
|
bottomMargin = 0;
|
|
|
|
|
2024-10-24 14:32:21 +02:00
|
|
|
if (margin >= 0) {
|
|
|
|
leftMargin = margin;
|
|
|
|
topMargin = margin;
|
|
|
|
rightMargin= margin;
|
|
|
|
bottomMargin = margin;
|
|
|
|
} else {
|
2024-11-15 22:17:07 +01:00
|
|
|
if(marginVertical >= 0){
|
|
|
|
topMargin = marginVertical;
|
|
|
|
bottomMargin = marginVertical;
|
|
|
|
} else {
|
|
|
|
topMargin = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_marginTop, 0);
|
|
|
|
bottomMargin = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (marginHorizontal >= 0) {
|
|
|
|
leftMargin = marginHorizontal;
|
|
|
|
rightMargin = marginHorizontal;
|
|
|
|
} else {
|
|
|
|
leftMargin = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_marginLeft, 0);
|
|
|
|
rightMargin = a.getDimensionPixelSize(com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0);
|
|
|
|
|
|
|
|
if (marginStart >= 0) {
|
|
|
|
leftMargin = marginStart;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (marginEnd >= 0) {
|
|
|
|
rightMargin = marginEnd;
|
|
|
|
}
|
|
|
|
}
|
2024-10-24 14:32:21 +02:00
|
|
|
}
|
2024-12-20 00:11:06 +01:00
|
|
|
|
2023-11-08 22:41:46 +01:00
|
|
|
a.recycle();
|
|
|
|
}
|
|
|
|
|
2024-08-25 11:20:01 +02:00
|
|
|
public MarginLayoutParams(ViewGroup.MarginLayoutParams source) {
|
|
|
|
super();
|
|
|
|
width = source.width;
|
|
|
|
height = source.height;
|
|
|
|
leftMargin = source.leftMargin;
|
|
|
|
topMargin = source.topMargin;
|
|
|
|
rightMargin = source.rightMargin;
|
|
|
|
bottomMargin = source.bottomMargin;
|
|
|
|
}
|
|
|
|
|
2023-11-08 22:41:46 +01:00
|
|
|
public void setMargins(int left, int top, int right, int bottom) {
|
|
|
|
leftMargin = left;
|
|
|
|
topMargin = top;
|
|
|
|
rightMargin = right;
|
|
|
|
bottomMargin = bottom;
|
2023-07-14 20:09:10 +02:00
|
|
|
}
|
2023-09-12 23:18:47 +02:00
|
|
|
|
|
|
|
public int getMarginStart() {
|
|
|
|
return leftMargin;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getMarginEnd() {
|
|
|
|
return rightMargin;
|
|
|
|
}
|
|
|
|
|
2023-11-08 22:41:46 +01:00
|
|
|
public void setMarginStart(int marginStart) {
|
|
|
|
leftMargin = marginStart;
|
|
|
|
}
|
|
|
|
public void setMarginEnd(int marginEnd) {
|
|
|
|
rightMargin = marginEnd;
|
|
|
|
}
|
2024-02-09 16:03:12 +01:00
|
|
|
|
|
|
|
public int getLayoutDirection() { return LAYOUT_DIRECTION_LTR; }
|
2023-07-14 20:09:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public interface OnHierarchyChangeListener {
|
2024-03-16 12:49:28 +01:00
|
|
|
public void onChildViewAdded(View parent, View child);
|
|
|
|
public void onChildViewRemoved(View parent, View child);
|
2023-06-18 11:03:43 +02:00
|
|
|
}
|
2025-02-10 18:19:55 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
throw new UnsupportedOperationException("Unimplemented method 'onNestedScrollAccepted'");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
throw new UnsupportedOperationException("Unimplemented method 'onNestedPreScroll'");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
throw new UnsupportedOperationException("Unimplemented method 'onNestedScroll'");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onStopNestedScroll(View target) {
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
throw new UnsupportedOperationException("Unimplemented method 'onStopNestedScroll'");
|
|
|
|
}
|
2025-03-25 19:24:06 +01:00
|
|
|
|
|
|
|
public void requestChildFocus(View child, View focused) {}
|
2022-10-02 23:06:56 +02:00
|
|
|
}
|