2013-07-23 23 views
6

私は非常に奇妙な設定をしていますが、奇妙な視覚的なバグがあります。基本的に、私は相対レイアウトで2つのビューを持っています:最初はImageViewの背景イメージです。ぼやけた背景が唯一のアップスクロールHalvedLinearLayout_ビュー、後ろにする必要がありますので、私はにぼやけた背景を必要とするInvalidate()は実際に子を再描画しません

<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_の上に自分自身を隠す:

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が実際OVER描くという巨大な明白な事実を除いて、それが必要として動作することですHalvedLinearLayout_、ボタンを削除します。 (しかし、時にはそれはうまくいくかもしれませんが、ボタンの半分が引かれ、残りの半分が保存されています...)

私はデバッグを始めました。 rootViewでinvalidate()を呼び出しても、実際にはすべての子が無効になるわけではありません。私はすべての無効化をオーバーライドして、いくつかのログもので関数を描く:私は、ログ、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(); 
    } 

そして今)私はスクロールすると発火が、子どもたちが再描画されることはありません:

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 

子どもたちに正しい順序で強制的に再描画させるにはどうすればよいですか?今、私は彼らが順不同を描いていると推測しています。そのため、ぼんやりした背景が他のすべての上に描かれています。ここで

はグリッチのスクリーンショットです:

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

+0

requestLayout()を試しましたか?子ビューも更新する必要があります。 – Cata

+0

スクロールイベントが発生したときに、blurredBackgroundのvisibility(View.INVISIBLE)を設定できます。 – droideckar

+0

@Cata:私はrequestLayout()を試しました。それでも同じことが起こります。 – phreakhead

答えて

1

[OK]を、私は、少なくとも、グリッチを取り除く方法を考え出し:私がしなければならなかったすべての変更「Region.Op.REPLACE」でした"Region.Op.INTERSECT"を使って、今すぐ動作します!

Invalidate()はまだ子を再描画しませんが、そのスライドが動作していると思います。

+1

'invalidate'は何も再描画しません。これはリージョンを無効とマークするだけで、Androidは描画パイプライン内で再描画を開始します。 –

2

invalidate()と同じ問題が発生しましたが、SOの別の場所ではうまく答えられなかったため、私は解決策を投稿したいと考えました。

これは、ViewGroupのすべての子ビューをループする再帰関数です。子供が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(); 
    } 
} 

パラメータlayoutはこのかなり一般的なソリューション作るタイプViewGroupLinearLayoutRelativeLayoutなど)の何もすることができるはずです。

私の目的のために働いていますが、徹底的なテストには入れていません。間違いがある場合は、コメントしてお知らせください。

関連する問題