我正在开发一个类似家谱的应用程序。我使用力导向布局算法来计算节点将放置的位置。这些节点是我自己创建的自定义视图,称为
PersonCard
。这是我的PersonCard
的片段:
private void init(AttributeSet attrs) {
// Initialize anchors
rightAnchor = new View(getContext());
int anchorColor = ContextCompat.getColor(getContext(), R.color.tea_rose);
int anchorSize = 10;
rightAnchor.setBackgroundColor(anchorColor);
FrameLayout.LayoutParams rightAnchorParams = new FrameLayout.LayoutParams(anchorSize, anchorSize);
rightAnchorParams.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
rightAnchorParams.rightMargin = -padding;
rightAnchor.setLayoutParams(rightAnchorParams);
addView(rightAnchor);
}
因为我需要连接这些不同的
PersonCards
,所以我创建了不同的 anchors
(PersonCard
的每一侧各一个),以便有统一的点,我可以将我的 PersonCards
与 Line
视图连接起来.
算法计算出每个
PersonCard
的位置后,我得到像这样的x和y坐标,并相应地放置PersonCards
:
Node 1: (489.70685469968083, 1534.7124300016587)
Node 2: (995.1782137460826, 731.7942097127028)
Node 3: (58.578329522505925, 716.785942983157)
Node 4: (534.2392750542016, 996.037653894383)
Node 5: (43.46557962124075, 1243.6774403463626)
Node 6: (530.856915894992, 454.41864708395013)
Node 7: (978.3108846322139, 1287.7832880796614)
在我的
PersonCard
中,我创建了获取锚点位置的方法:
private int[] getAnchorPosition(ViewGroup parent, View anchor) {
int[] anchorPosition = new int[2];
int[] parentPosition = new int[2];
anchor.getLocationOnScreen(anchorPosition);
parent.getLocationOnScreen(parentPosition);
anchorPosition[0] -= parentPosition[0];
anchorPosition[1] -= parentPosition[1];
Log.d("AnchorPosition", "Anchor X: " + anchorPosition[0] + ", Y: " + anchorPosition[1]);
return anchorPosition;
}
public int[] getRightAnchorPosition(ViewGroup parent) {
return getAnchorPosition(parent, rightAnchor);
}
但是,这个方法怎么可能给我完全错误的坐标呢?当我调用它时,它会给我这样的
rightAnchor
的 Node 1
:
Node 1: X is: 200, Y is: 203
正如你所看到的,这与
Node 1
的真实坐标完全不匹配。由于某种奇怪的原因,rightAnchors
中的所有其他PersonCards
都有相同的坐标?
Node 2: X is: 200, Y is: 203
Node 3: X is: 200, Y is: 203
Node 4: X is: 200, Y is: 203
and so on...
我不确定这种奇怪的行为从何而来。至于我的布局,我只是将我的
PersonCards
添加到 FrameLayout
,它是另一个 FrameLayout
的子级。
为了不陷入某些布局计算恶作剧,我在调用
.post
之前使用 getRightAnchorPosition
来确保我的布局已完成计算:
personCard.post(new Runnable() {
@Override
public void run() {
int[] rightAnchorPos = personCard.getRightAnchorPosition(origin_frameLayout);
Log.d("RightAnchor", "X is: " + rightAnchorPos[0] + ", Y is: " + rightAnchorPos[1]);
}
});
但是,这仍然给我提供了与上面显示的相同的坐标。
为什么我会出现这种奇怪的行为,我该如何解决它?
当然这是我的 Activity 生命周期的问题。当我使用
ViewTreeObserver.OnGlobalLayoutListener
而不是 .post
时,坐标会完美返回。