phr*_*ead 6 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/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" />
...
Run Code Online (Sandbox Code Playgroud)
模糊的背景应仅位于向上滚动的HalvedLinearLayout_视图后面,因此我需要模糊的背景将自己屏蔽在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();
}
Run Code Online (Sandbox Code Playgroud)
现在,问题是一切都按照它应该工作,除了巨大的明显事实,当你滚动ScrollView时,blurBackground实际上绘制了HalvedLinearLayout_,消除了它中的按钮.(但有时只有一半.有时它会很好,有时一半按钮会被拉过来,另一半会保留......各种奇怪的故障.)
我开始调试,我注意到一些有趣的事情:在rootView上调用invalidate()实际上并没有使所有的子句无效.我用一些日志记录来覆盖所有无效和绘制函数:
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();
}
Run Code Online (Sandbox Code Playgroud)
现在,当我查看日志时,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
Run Code Online (Sandbox Code Playgroud)
我如何强迫孩子重新绘制,正确的顺序?现在我猜测他们画出来的顺序,这就是为什么模糊的背景正在绘制其他一切.
这是故障的屏幕截图:

我遇到了同样的问题invalidate(),因为在其他地方没有很好的答案,所以我想我会发布我的解决方案。
这是一个递归函数,它将循环遍历 a 的所有子视图ViewGroup。如果孩子是 a ViewGroup,它将递归并搜索孩子。否则,它将调用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();
}
}
Run Code Online (Sandbox Code Playgroud)
该参数layout应能为类型的东西ViewGroup(LinearLayout,RelativeLayout使之成为一个相当普遍的解决方案,等等)。
它符合我的目的,但我还没有对其进行彻底的测试。如果有任何错误,请评论并告诉我。
好吧,我想出了如何消除故障,至少:我所要做的就是将“Region.Op.REPLACE”更改为“Region.Op.INTERSECT”,现在它可以工作了!
Invalidate() 仍然不会重新绘制子级,但我想既然它正在工作,我就会让它滑动。
| 归档时间: |
|
| 查看次数: |
4434 次 |
| 最近记录: |