Android Invalidate()不';事实上,我没有重画孩子
所以,我有一个非常奇怪的设置,我从中得到一些奇怪的视觉错误。基本上,我在一个相对的布局中有两个视图:第一个是ImageView背景图像;第二个是相同的背景图像,但模糊以产生一种磨砂玻璃后的效果:Android Invalidate()不';事实上,我没有重画孩子,android,android-layout,android-view,Android,Android Layout,Android View,所以,我有一个非常奇怪的设置,我从中得到一些奇怪的视觉错误。基本上,我在一个相对的布局中有两个视图:第一个是ImageView背景图像;第二个是相同的背景图像,但模糊以产生一种磨砂玻璃后的效果: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/pr
<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" />
...
现在的问题是,一切都正常工作,除了滚动滚动滚动视图时,模糊的背景实际上覆盖了一半的线性布局,抹去了其中的按钮。(但有时只能半途而废。有时会很好,有时按钮的一半会被拉掉,另一半会保留下来……各种奇怪的故障。)
我开始调试,我注意到了一些有趣的事情:在rootView上调用invalidate()实际上并不会使所有子项失效()。我用一些日志文件覆盖了所有的invalidate和draw函数:
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()会启动,但子项从不重新绘制:
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
我如何强制孩子们按照正确的顺序重新绘制?现在我猜他们画得很乱,这就是为什么模糊的背景画得比其他东西都好
以下是该故障的屏幕截图:
好的,我找到了解决问题的方法,至少:我所要做的就是将“Region.Op.REPLACE”改为“Region.Op.INTERSECT”,现在它可以工作了
Invalidate()仍然没有重新绘制子项,但我想现在我可以顺其自然了。我在
Invalidate()中遇到了同样的问题,因为其他地方没有好的答案,所以我想我应该发布我的解决方案
这是一个递归函数,将在视图组的所有子视图中循环。如果子对象是视图组
,它将递归并搜索子对象。否则,它将对子级调用invalidate()
(这是终止情况)
public void invalidater草书(视图组布局){
int count=layout.getChildCount();
看孩子;
for(int i=0;i
参数layout
应该可以是ViewGroup
类型的任何对象(LinearLayout
,RelativeLayout
等),这是一个非常通用的解决方案
它符合我的目的,但我还没有对它进行彻底的测试。如果有任何错误,请评论并让我知道。您是否尝试过requestLayout()?这应该也会刷新子视图。当触发滚动事件时,您可以为模糊背景设置可见性(View.INVISIBLE)。@Cata:我刚刚尝试了requestLayout()。她看起来很可爱。invalidate
不会重画任何东西。它只是将区域标记为无效,这导致Android开始在绘图管道中重新绘制。
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
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();
}
}