目前我面临着非常丑陋的问题。
我有几个半透明孩子的 ViewFlipper。ViewFlipper 的 In 和 Out 动画是这样制作的,以便这些孩子相互叠加(即它们的 alpha 值混合在一起)。孩子们被制作成半透明的,这样他们下面的背景就可以看到了,所以我不能为每个孩子设置背景。
问题是我现在确实希望那些孩子相交 - 稍后绘制的孩子应该被剪裁。基于这种需要,我重写了 ViewFlipper.drawChild 方法,并将动画变换矩阵应用于视图边界。接下来,我使用对先前计算的边界的补充来剪辑画布绘图区域。然而,无论我做什么,似乎仍然有一个小矩形覆盖。有什么办法可以解决吗?
我的代码如下:
public class ChartsTabsLayout extends ViewFlipper {
private Rect[] mDrawTMPParent;
private Rect mDrawTMPChild;
private Rect mDrawTMP;
private RectF mDrawTMPRectF;
public ChartsTabsLayout(final Context aContext) {
super(aContext);
initialize(aContext, null);
}
public ChartsTabsLayout(final Context aContext, final AttributeSet aAttributes) {
super(aContext, aAttributes);
initialize(aContext, aAttributes);
}
private void initialize(final Context aContext, final AttributeSet aAttributes) {
mDrawTMPParent = new Rect[] { new Rect(), new Rect(), new Rect(), new Rect() };
mDrawTMPChild = new Rect();
mDrawTMP = new Rect();
mDrawTMPRectF = new RectF();
}
@Override
protected void dispatchDraw(final Canvas aCanvas) {
getDrawingRect(mDrawTMP);
mDrawTMPParent[0].set(mDrawTMP);
for(int i = 1; i < 4; i++) {
mDrawTMPParent[i].setEmpty();
}
super.dispatchDraw(aCanvas);
}
private void countRectCompliment(final Rect aInside, final Rect aOutside, final Rect[] aOut) {
for(int i = 0; i < 4; i++) {
aOut[i].set(aOutside);
}
aOut[0].right = aInside.left;
aOut[0].top = aInside.top;
aOut[0].bottom = aInside.bottom;
aOut[1].left = aInside.right;
aOut[1].top = aInside.top;
aOut[1].bottom = aInside.bottom;
aOut[2].top = aInside.bottom;
aOut[3].bottom = aInside.top;
for(int i = 0; i < 4; i++) {
if(aOut[i].left >= aOut[i].right || aOut[i].top >= aOut[i].bottom) {
aOut[i].setEmpty();
}
}
}
@Override
protected boolean drawChild(final Canvas aCanvas, final View aChild, final long aDrawingTime) {
final Transformation transformation = new Transformation();
aChild.getDrawingRect(mDrawTMPChild);
mDrawTMPRectF.set(mDrawTMPChild);
final Animation animation = aChild.getAnimation();
if(animation != null) {
if(animation.willChangeTransformationMatrix()) {
//if I change aDrawingTime to aDrawingTime-50
//animations seems to look ok, but it is "magic number"
//solution I would like to avoid by any means
animation.getTransformation(aDrawingTime, transformation);
transformation.getMatrix().mapRect(mDrawTMPRectF);
}
}
mDrawTMPRectF.round(mDrawTMPChild);
boolean ret = true;
for(int i = 0; i < 4; i++) {
if(!mDrawTMPParent[i].isEmpty()) {
aCanvas.save();
aCanvas.clipRect(mDrawTMPParent[i].left, mDrawTMPParent[i].top, mDrawTMPParent[i].right, mDrawTMPParent[i].bottom);
ret |= super.drawChild(aCanvas, aChild, aDrawingTime);
aCanvas.restore();
}
}
countRectCompliment(mDrawTMPChild, mDrawTMPParent[0], mDrawTMPParent);
return ret;
}
}