2013-07-23 27 views
6

Vì vậy, tôi có một thiết lập khá lạ, và tôi đang nhận được một số lỗi hình ảnh lạ trên nó. Về cơ bản, tôi có hai chế độ xem trong bố cục tương đối: Thứ nhất chỉ là hình nền của ImageView; thứ hai là hình nền tương tự nhưng mờ để đưa ra một loại có hiệu lực đằng sau-mờ kính:Invalidate() không thực sự vẽ lại trẻ em

<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" /> 

... 

Nền mờ chỉ cần được đằng sau quan điểm HalvedLinearLayout_, mà cuộn lên, vì vậy tôi cần nền mờ để mặt nạ tự trên HalvedLinearLayout_ nên nền phi mờ thể hiện qua:

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(); 
} 

Bây giờ, vấn đề là mọi thứ hoạt động như mong muốn, ngoại trừ một thực tế rõ ràng rất lớn rằng khi bạn di chuyển các scrollview, các blurredBackground thực sự thu hút hơn HalvedLinearLayout_, xóa các nút trong đó. (nhưng chỉ nửa chừng, đôi khi. Đôi khi nó sẽ ổn, đôi khi một nửa nút sẽ được kéo lên và nửa còn lại được bảo quản ... tất cả các loại ổn định kỳ lạ.)

Tôi bắt đầu gỡ lỗi và nhận thấy điều gì đó thú vị: gọi invalidate() trên rootView không thực sự làm mất hiệu lực() tất cả các con. Tôi gạt tất cả các lệnh vô hiệu và vẽ chức năng với một số công cụ logging:

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(); 
    } 

Và bây giờ khi tôi nhìn vào các bản ghi, các rootView.invalidate() được bắn khi tôi di chuyển, nhưng những đứa trẻ không bao giờ vẽ lại:

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 

Làm cách nào để buộc trẻ em vẽ lại, TRONG LỆNH ĐÚNG? Ngay bây giờ tôi đoán họ rút ra khỏi trật tự và đó là lý do tại sao nền mờ đang vẽ trên đầu trang của tất cả mọi thứ khác.

Dưới đây là một ảnh chụp màn hình của trục trặc:

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

+0

Bạn đã thử requestLayout() chưa? Điều đó cũng sẽ làm mới chế độ xem con. – Cata

+0

bạn có thể setVisibility (View.INVISIBLE) cho blurredBackground khi sự kiện cuộn được kích hoạt. – droideckar

+0

@Cata: Tôi vừa thử requestLayout(). Nó vẫn làm điều tương tự. – phreakhead

Trả lời

1

Ok, tôi đã tìm ra cách để thoát khỏi sự glitching, ít nhất là: tất cả những gì phải làm là thay đổi "Region.Op.REPLACE" với "Region.Op.INTERSECT" và bây giờ nó hoạt động!

Invalidate() vẫn không vẽ lại con, nhưng tôi đoán tôi sẽ để trang trình bày đó ngay bây giờ khi nó hoạt động.

+1

'invalidate' không vẽ lại bất kỳ thứ gì. Nó chỉ là khu vực đánh dấu là không hợp lệ, khiến Android bắt đầu vẽ lại trong đường ống vẽ. –

2

Tôi đã gặp phải vấn đề tương tự này với invalidate() và vì không có câu trả lời hay ở nơi khác trên SO, tôi đã tìm ra giải pháp của mình.

Đây là chức năng đệ quy sẽ lặp qua tất cả các chế độ xem con của một số ViewGroup. Nếu đứa trẻ là một số ViewGroup, nó sẽ tái chế và tìm kiếm đứa trẻ. Nếu không, nó sẽ gọi số invalidate() trên đứa trẻ (đây là trường hợp chấm dứt).

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(); 
    } 
} 

Tham số layout sẽ có thể được bất cứ điều gì của loại ViewGroup (LinearLayout, RelativeLayout, vv) làm cho một giải pháp khá chung.

Nó hoạt động cho mục đích của tôi, nhưng tôi chưa thử nghiệm kỹ lưỡng. Nếu có bất kỳ sai lầm nào, hãy bình luận và cho tôi biết.

Các vấn đề liên quan