gpt4 book ai didi

c++ - 在父 View 中使用任意 anchor 定位 subview

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:07:52 25 4
gpt4 key购买 nike

我很难找出合适的算法。我有一个 super View (绿色)和一个 subview (黄色)。在这个 subview (红色)中有一个任意 anchor (只是一个选择点,不与图层的 anchor 属性混合)我必须按照放置这个红点的方式放置 subview 并调整其大小在 super View 的中心, subview 在需要时按比例调整大小(如果移动后其框架超出 super View 的边界)。没有使用自动布局。看图片我想要得到什么。

所以基本上我写了一个 C++ 测试例程,在给定新点的“周围”计算一个新的比例矩形(所以这个点成为这个新矩形的中心),但我不知道接下来要做什么来处理一个点不在 subview 的中心。 Rect 基本上是一个包含 x, y, width, height 成员的结构。

    Rect
calculateRectInBounds(const Rect &boundingRect, const Rect &initialRect, const Point &translationPoint)
{
double boundsWidth = boundingRect.getWidth();
double boundsHeight = boundingRect.getHeight();
double distanceX, distanceY;
Size sizeByWidth, sizeByHeight;

// detect part where point is

/*
* UL | UR
* ---C---
* LL | LR
*/

// -- upper left - check left & top borders

if (translationPoint.x <= boundsWidth / 2 && translationPoint.y < boundsHeight / 2) {
distanceX = translationPoint.x;
distanceY = translationPoint.y;

sizeByWidth = scaleSizeToWidth(initialRect.getSize(), distanceX);
sizeByHeight = scaleSizeToHeight(initialRect.getSize(), distanceY);

if (sizeByWidth.height > distanceY) {
return {translationPoint.x - sizeByHeight.width,
0,
sizeByHeight.width * 2,
sizeByHeight.height * 2};
}

return {0,
translationPoint.y - sizeByWidth.height,
sizeByWidth.width * 2,
sizeByWidth.height * 2};
}

// -- upper right - check top & right borders

if (translationPoint.x > boundsWidth / 2 && translationPoint.y <= boundsHeight / 2) {
distanceX = boundsWidth - translationPoint.x;
distanceY = translationPoint.y;

sizeByWidth = scaleSizeToWidth(initialRect.getSize(), distanceX);
sizeByHeight = scaleSizeToHeight(initialRect.getSize(), distanceY);

if (sizeByWidth.height > distanceY) {
return {translationPoint.x - sizeByHeight.width,
0,
sizeByHeight.width * 2,
sizeByHeight.height * 2};
}

return {translationPoint.x - sizeByWidth.width,
translationPoint.y - sizeByWidth.height,
sizeByWidth.width * 2,
sizeByWidth.height * 2};
}

// -- lower right - check right & bottom borders

if (translationPoint.x >= boundsWidth / 2 && translationPoint.y > boundsHeight / 2) {
distanceX = boundsWidth - translationPoint.x;
distanceY = boundsHeight - translationPoint.y;

sizeByWidth = scaleSizeToWidth(initialRect.getSize(), distanceX);
sizeByHeight = scaleSizeToHeight(initialRect.getSize(), distanceY);

if (sizeByWidth.height > distanceY) {
return {translationPoint.x - sizeByHeight.width,
translationPoint.y - sizeByHeight.height,
sizeByHeight.width * 2,
sizeByHeight.height * 2};
}

return {translationPoint.x - sizeByWidth.width,
translationPoint.y - sizeByWidth.height,
sizeByWidth.width * 2,
sizeByWidth.height * 2};
}

// -- lower left - check bottom & left borders

if (translationPoint.x < boundsWidth / 2 && translationPoint.y >= boundsHeight / 2) {
distanceX = translationPoint.x;
distanceY = boundsHeight - translationPoint.y;

sizeByWidth = scaleSizeToWidth(initialRect.getSize(), distanceX);
sizeByHeight = scaleSizeToHeight(initialRect.getSize(), distanceY);

if (sizeByWidth.height > distanceY) {
return {translationPoint.x - sizeByHeight.width,
translationPoint.y - sizeByHeight.height,
sizeByHeight.width * 2,
sizeByHeight.height * 2};
}

return {0,
translationPoint.y - sizeByWidth.height,
sizeByWidth.width * 2,
sizeByWidth.height * 2};
}

// -- center

return initialRect;
}

Size
scaleSizeToWidth(Size size, double newWidth)
{
return {newWidth, (std::min(size.width, newWidth) / std::max(size.width, newWidth)) * size.height};
}

Size
scaleSizeToHeight(Size size, double newHeight)
{
return {(std::min(size.height, newHeight) / std::max(size.height, newHeight)) * size.width, newHeight};
}

enter image description here

编辑

感谢@MBo正确套路的回答

    Rect
calculateRectInBounds(const Rect &boundingRect, const Rect &initialRect, const Point &anchorPoint)
{
auto lDist = anchorPoint.x - initialRect.getX();
auto rDist = initialRect.getWidth() - lDist;
auto tDist = anchorPoint.y - initialRect.getY();
auto bDist = initialRect.getHeight() - tDist;

auto lRatio = (lDist * 2) / boundingRect.getWidth();
auto rRatio = (rDist * 2) / boundingRect.getWidth();
auto tRatio = (tDist * 2) / boundingRect.getHeight();
auto bRatio = (bDist * 2) / boundingRect.getHeight();

auto scale = 1 / std::max({lRatio, rRatio, tRatio, bRatio});

auto x = initialRect.getWidth() / 2 - lDist * scale + initialRect.getX();
auto y = initialRect.getHeight() / 2 - tDist * scale + initialRect.getY();
auto width = initialRect.getWidth() * scale;
auto height = initialRect.getHeight() * scale;

return {x, y, width, height};
}

最佳答案

获取从红点到 subview 矩形所有边的距离

RedX, YellowWidth-RedX, RedY, YellowHeight - RedY

并计算 4 个与父 View 大小的比率

L = (2 * RedX) / GreenWidth
R = (2 * (YellowWidth-RedX)) / GreenWidth
T = (2 * RedY) / GreenHeight
B = (2 * (YellowHeight-RedY)) / GreenHeight

然后找出其中的最大值

Mx = Max(L,R,T,B)

现在确定比例:

Scale = 1 / Mx 

新的 subview 坐标:

X =  YellowWidth / 2  - (RedX * Scale)
Y = YellowHeight / 2 - (RedY * Scale)

关于c++ - 在父 View 中使用任意 anchor 定位 subview ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54199461/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com