将视图放置在父级之外而不被剪切

问题描述 投票:0回答:1

我有一个像这样的 JSON:

{
  "name": "view",
  "attributes": {
    "style": {
      "backgroundColor": "yellow",
    }
  },
  "children": [
    {
      "name": "view",
      "attributes": {
        "style": {
          "backgroundColor": "red",
          "width": 400,
          "height": 400,
        }
      }
    },
    {
      "name": "view",
      "attributes": {
        "style": {
          "backgroundColor": "yellow",
          "top": 150,
          "left": 100,
          "width": 200,
          "height": 200,
        }
      }
    }
  ]
}

我正在使用递归来显示基于该 JSON 的布局。

我的 CustomLayout 扩展自 ViewGroup。它类似于 LinearLayout。

public static class CustomLayout extends ViewGroup {

    private int orientation; // 0 for horizontal, 1 for vertical

    public CustomLayout(Context context) {
        super(context);
    }

    public CustomLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    // Set the orientation (horizontal or vertical)
    public void setOrientation(int orientation) {
        this.orientation = orientation;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Measure the size of your layout and its children here
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width = 0;
        int height = 0;

        // Measure each child view
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            if (orientation == 0) { // Horizontal layout
                width += child.getMeasuredWidth();
                height = Math.max(height, child.getMeasuredHeight());
            } else { // Vertical layout
                width = Math.max(width, child.getMeasuredWidth());
                height += child.getMeasuredHeight();
            }
        }

        // Take padding into account
        width += getPaddingLeft() + getPaddingRight();
        height += getPaddingTop() + getPaddingBottom();

        // Respect the given measure spec
        width = resolveSizeAndState(width, widthMeasureSpec, 0);
        height = resolveSizeAndState(height, heightMeasureSpec, 0);

        setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width,
                heightMode == MeasureSpec.EXACTLY ? heightSize : height);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        // Position child views within your layout here
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();

        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (orientation == 0) { // Horizontal layout
                child.layout(childLeft, childTop,
                        childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight());
                childLeft += child.getMeasuredWidth();
            } else { // Vertical layout
                child.layout(childLeft, childTop,
                        childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight());
                childTop += child.getMeasuredHeight();
            }
        }
    }
}

递归最终的结果是这样的:

LinearLayout rootView = activity.findViewById(R.id.root);

CustomLayout view = new CustomLayout(activity);

view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

view.setOrientation(1);

view.setBackgroundColor(Color.parseColor("yellow"));

View child1 = new CustomLayout(activity);
View child2 = new CustomLayout(activity);

child1.setLayoutParams(new LayoutParams(400, 400));
child1.setBackgroundColor(Color.parseColor("red"));

child2.setLayoutParams(new LayoutParams(200, 200));
child2.setBackgroundColor(Color.parseColor("green"));

view.addView(child1);
view.addView(child2);

rootView.addView(view);

我的问题是,如何申请

top
left

这就是我想要实现的目标:

made with react native

使用 React Native 得到了想要的结果。这是代码:

function App(): React.JSX.Element {
  return (
    <View style={{backgroundColor: 'yellow'}}>
      <View style={{backgroundColor: 'red', width: 200, height: 200}}></View>
      <View
        style={{
          backgroundColor: 'green',
          top: 100,
          left: 50,
          width: 150,
          height: 150,
        }}></View>
    </View>
  );
}

如您所见,黄色包装器根据其子级获得正确的宽度和高度,并且绿色视图被移到包装器之外而不会被剪切。

React Native 也使用自己的布局扩展 ViewGroup,所以一定有办法。

android layout
1个回答
0
投票

解决方案是将这些行添加到每个父级:

setClipChildren(false);
setClipToPadding(false);

大概是这样的:

public CustomLayout(Context context) {
    super(context);

    setClipChildren(false);
    setClipToPadding(false);
}

在 onLayout 中我们有类似的东西:

int x = 30; // 30 to the left
int y = 0;

child.layout(x, y, x + childWidth, y + childHeight);
© www.soinside.com 2019 - 2024. All rights reserved.