好的,这就是我正在做的......我有两个自定义布局:
HandedLayout extends ViewGroup
和
HandedPathLayout extends HandedLayout
所以在根布局中,我有一个自定义的 LayoutParameters 来接受一个布局属性,叫做 handed。这是布局参数类
public static class LayoutParams extends ViewGroup.LayoutParams {
public int handed;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray a =
c.obtainStyledAttributes(attrs, R.styleable.HandedLayout_LayoutParams);
handed = a.getInt(R.styleable.HandedLayout_LayoutParams_layout_handed,
HandedLayout.RIGHT_HANDED);
a.recycle();
}
public LayoutParams(int width, int height) {
super(width, height);
}
}
据我了解(似乎摇摇晃晃),我还需要覆盖 HandedLayout 中的 3 个类。他们来了:
@Override
public HandedLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new HandedLayout.LayoutParams(getContext(), attrs);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
@Override
protected HandedLayout.LayoutParams generateDefaultLayoutParams() {
return new HandedLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
所以在内部自定义布局(HandedPathLayout)中,我需要很多布局参数,所以我做的完全一样!这是 HandedPathLayout 内部的 LayoutParameters 类:
public static class LayoutParams extends HandedLayout.LayoutParams {
public int[] endSides;
public int[] endPositions;
public int[] anchorSides;
public int[] anchorPositions;
public int controlPointDistance;
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
endSides = new int[2];
endPositions = new int[2];
anchorSides = new int[2];
anchorPositions = new int[2];
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.HandedPathLayout_LayoutParams);;
try {
//this is the second place that the default handedness is set, watch out!
//handed = a.getInteger(R.styleable.HandedLayout_LayoutParams_layout_handed, HandedLayout.RIGHT_HANDED);
endSides[0] = a.getInteger(R.styleable.HandedPathLayout_LayoutParams_layout_from_side, HandedLayout.BOTTOM_SIDE);
endSides[1] = a.getInteger(R.styleable.HandedPathLayout_LayoutParams_layout_to_side, HandedLayout.PINKIE_SIDE);
endPositions[0] = a.getDimensionPixelSize(R.styleable.HandedPathLayout_LayoutParams_layout_from_position, 0);
endPositions[1] = a.getDimensionPixelSize(R.styleable.HandedPathLayout_LayoutParams_layout_to_position, 0);
anchorSides[0] = a.getInteger(R.styleable.HandedPathLayout_LayoutParams_layout_anchor_up_side, HandedLayout.TOP_SIDE);
anchorSides[1] = a.getInteger(R.styleable.HandedPathLayout_LayoutParams_layout_anchor_down_side, HandedLayout.BOTTOM_SIDE);
//todo: should these positions be set relative to handedness? which direction is zero?
anchorPositions[0] = a.getDimensionPixelSize(R.styleable.HandedPathLayout_LayoutParams_layout_anchor_up_position, 0);
anchorPositions[1] = a.getDimensionPixelSize(R.styleable.HandedPathLayout_LayoutParams_layout_anchor_down_position, 0);
controlPointDistance = a.getInteger(R.styleable.HandedPathLayout_LayoutParams_layout_control_point_position, HandedLayout.BOTTOM_SIDE);
} finally {
a.recycle();
}
}
}
再一次,在 HandedPathLayout 类中,三个函数确保我们得到正确的 LayoutParams:
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof HandedPathLayout.LayoutParams;
}
@Override
public HandedPathLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new HandedPathLayout.LayoutParams(getContext(), attrs);
}
@Override
protected HandedPathLayout.LayoutParams generateDefaultLayoutParams() {
return new HandedPathLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
我已经尝试过使用和不使用完全限定的 LayoutParams 类名。
所以,现在一切都在那里并且编译好了,然后在根 ViewGroup 的 onMeasure 中,HandedLayout,我循环遍历孩子并尝试获取他们的 getLayoutParams(),这样我就可以弄清楚将它们放在哪里以及如何测量它们,我得到了这个 ClassCastException!
05-29 18:16:35.061 9391-9391/com.codesolutions.onehandkeyboard E/AndroidRuntime:致命异常:主进程:com.codesolutions.onehandkeyboard,PID:9391 java.lang.ClassCastException:com.codesolutions.pathlayout.HandedLayout$ LayoutParams 无法在 com.codesolutions.pathlayout.HandedLayout.onMeasure(HandedLayout.java:90) 处转换为 com.codesolutions.pathlayout.HandedPathLayout$LayoutParams
这个演员抛出了这个异常,看起来它应该得到正确的类型,在调试器中我已经确认孩子确实是一个 HandedPathLayout,并且所有迹象都表明 LayoutParams 是正确的类型!
HandedPathLayout.LayoutParams lp =
(HandedPathLayout.LayoutParams)child.getLayoutParams();
我只是不明白为什么 LayoutParams 的类型不正确!
我不明白的另一件事是关于我想放入我的 HandedPathLayout 的自定义视图(扩展 TextView)。它需要一个自定义的 layout_rows XML 属性,所以我需要让它成为自己的 LayoutParams 吗?这些仅适用于 ViewGroup,对吗?但是,需要应用该属性的是视图,而不是 ViewGroup。
更新:
因此,当我运行调试器并在我的演员失败之前停止时,在 HandedLayout 的 onMeasure 中......我发现,事实上,LayoutParams 对象都不是我期望的类型!父级(HandedLayout)的 getLayoutParams 返回一个 FrameLayout.LayoutParams(这对我来说根本没有意义),而子级(它是一个 HandedPathLayout)有一个 HandedLayout.LayoutParams!为什么?!我在这里不明白什么?
谢谢!