So, I have a rather strange setting, and I get some strange visual errors from it. Basically, I have two views in relative layout: the first is just an ImageView background image; the second is the same background image, but blurry to give the appearance of a frozen glass effect:
<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" > <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" /> <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" /> ...
The blurry background should only be watching the HalvedLinearLayout_, which scrolls up, so I need a blurry background to mask myself above HalvedLinearLayout_ so that the non-blurry background is shown through:
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());
Now the problem is that everything works as it should, EXCEPTION for the huge egregious fact that when scrolling through the ScrollView, blurredBackground actually draws on HalvedLinearLayout_, erasing the buttons in it. (but only half, sometimes. Sometimes it will be fine, sometimes half of the button will be drawn and the other half saved ... all kinds of weird crashes.)
I started debugging, and I noticed something interesting: calling invalidate () on the root directory does not actually cancel () all the children. I tried all the invalidate and draw functions with some registration materials:
public class MaskedBlurredBackgroundView extends BlurredBackgroundView { 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(); }
And now, when I look at the log, rootView.invalidate () is triggered when scrolling, but children never redraw:
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
How to force children to redraw, in the RIGHT ORDER? Right now I assume that they are out of order and why the blurry background rests on everything else.
Here is a glitch screenshot:
