gpt4 book ai didi

android - Invalidate() 实际上并没有重绘 child

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:11:37 24 4
gpt4 key购买 nike

所以,我有一个非常奇怪的设置,并且我从中得到了一些奇怪的视觉错误。基本上,我在相对布局中有两个 View :第一个只是一个 ImageView 背景图像;第二个是相同的背景图像,但模糊以产生一种毛玻璃后面的效果:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/profile_holder"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<!-- background -->
<ImageView
android:id="@+id/backgroundImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:scaleType="centerCrop"
android:src="@drawable/default_logo" />

<!-- blurry background -->
<com.custom.MaskedBlurredBackgroundView_
android:id="@+id/blurred_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp" />

<ScrollView
android:id="@+id/scrolly"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >

<com.custom.HalvedLinearLayout_
android:paddingTop="100dp"
android:id="@+id/profileHolder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>

<Button
android:id="@+id/profileButtonTracks"
style="@style/ProfileButtons"
android:drawableLeft="@drawable/ic_profile_menu_music"
android:text="@string/profile_button_tracks" />

...

模糊背景应该只在向上滚动的 HalvedLinearLayout_ View 后面,所以我需要模糊背景在 HalvedLinearLayout_ 上方屏蔽自己,这样非模糊背景就会显示出来:

scrolly  = ((ScrollView) rootView.findViewById(R.id.scrolly));
scrolly.setOnScrollListener(new ScrollView.OnScrollListener() {

private boolean hasScrolled = false;

@Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {

if (!hasScrolled) {
hasScrolled = true;
Logger.action(Logger.Action.BioView, band);
}

positionMask();
}
});

...

protected void positionMask() {
if (blurredBackground == null) return;

Logger.d(TAG, "positionMask() " + rootView.getId());

//blurredBackground.setMaskBottom(blurredBackground.getHeight() - profileHolder.getPaddingTop() - scrollY);
blurredBackground.setMaskBottom(profileHolder.getTop() + profileHolder.getPaddingTop() - scrolly.getScrollY());
//blurredBackground.invalidate();
//profileHolder.invalidate();
rootView.postInvalidate();
}

现在,问题是一切正常,除了一个明显的事实,即当您滚动 ScrollView 时,blurredBackground 实际上覆盖了 HalvedLinearLayout_,抹掉了其中的按钮。 (但有时只有一半。有时它会很好,有时按钮的一半会被绘制而另一半被保留......各种奇怪的故障。)

我开始调试,我注意到一些有趣的事情:在 rootView 上调用 invalidate() 实际上并没有使所有的 child 无效。我用一些日志记录覆盖了所有无效和绘制函数:

public class MaskedBlurredBackgroundView extends BlurredBackgroundView {
/***
* Sets the mask to cover everything above the given Y coordinate
* @param t Y Coordinate in pixels
*/
public void setMaskBottom(int y) {
maskBottom = y;
}

private void clipCanvas(Canvas canvas) {
Logger.d(TAG, "dispatchDraw clipping: " + maskBottom + ", " + getWidth() + "," + getHeight());
canvas.clipRect(0, maskBottom, getWidth(), getHeight(), Region.Op.REPLACE);
}

@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
clipCanvas(canvas);
super.dispatchDraw(canvas);

canvas.restore();
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
Logger.d(TAG, "drawChild: " + child + getWidth() + "," + getHeight());

return super.drawChild(canvas, child, drawingTime);
}

@Override
public void invalidate() {
Logger.d(TAG, "invalidate: " + getWidth() + "," + getHeight());
super.invalidate();
}

现在当我查看日志时,当我滚动时 rootView.invalidate() 正在触发,但 children 从不重绘:

07-23 12:36:49.328: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.348: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.348: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.368: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.368: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.378: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.398: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.418: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.448: D/BandDetailFrag(12982): positionMask() 2131165298
07-23 12:36:49.478: D/BandDetailFrag(12982): positionMask() 2131165298

我如何强制 children 以正确的顺序重画?现在我猜他们绘制的顺序是乱序的,这就是模糊背景在其他所有内容之上绘制的原因。

这是故障的屏幕截图:

screenshot of glitch: see the blurred background masked correctly, but drawing OVER the HalvedLinearLayout_

最佳答案

我在使用 invalidate() 时遇到了同样的问题,由于在 SO 的其他地方没有很好的答案,我想我应该发布我的解决方案。

这是一个递归函数,它将遍历 ViewGroup 的所有 subview 。如果子项是 ViewGroup,它将递归并搜索子项。否则,它将对 child 调用 invalidate()(这是终止情况)。

public void invalidateRecursive(ViewGroup layout) {
int count = layout.getChildCount();
View child;
for (int i = 0; i < count; i++) {
child = layout.getChildAt(i);
if(child instanceof ViewGroup)
invalidateRecursive((ViewGroup) child);
else
child.invalidate();
}
}

参数 layout 应该可以是任何类型的 ViewGroup(LinearLayoutRelativeLayout 等。 ) 使它成为一个非常通用的解决方案。

它符合我的目的,但我还没有对它进行全面测试。如果有任何错误,请评论并告诉我。

关于android - Invalidate() 实际上并没有重绘 child ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17819553/

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