![](/img/trans.png)
[英]How can I prevent my custom view drawing from being clipped by the view bounds?
[英]When drawing outside the view clip bounds with Android: how do I prevent underling views from drawing on top of my custom view?
我寫了一個自定義Android視圖,需要在其剪切邊界之外繪制。
這就是我所擁有的:
這是當我點擊一個按鈕時發生的情況,例如右鍵:
如何防止下面的視圖在我的“句柄”上繪制?
我項目中的一些相關偽代碼如下。
我的自定義視圖MyHandleView如下所示:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Path p = mPath;
int handleWidth = mHandleWidth;
int handleHeight = mHandleHeight;
int left = (getWidth() >> 1) - handleWidth;
canvas.save();
// allow drawing out of bounds vertically
Rect clipBounds = canvas.getClipBounds();
clipBounds.inset(0, -handleHeight);
canvas.clipRect(clipBounds, Region.Op.REPLACE);
// translate up to draw the handle
canvas.translate(left, -handleHeight);
// draw my background shape
canvas.drawPath(p, mPaint);
canvas.restore();
}
布局是這樣的(我簡化了一點):
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Main content of the SlidingUpPanel -->
<fragment
android:above=@+id/panel"
class="com.neosperience.projects.percassi.android.home.HomeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"
tools:layout="@layout/fragment_home" />
<!-- The Sliding Panel -->
<LinearLayout
android:id="@id/panel"
android:layout_width="match_parent"
android:layout_height="@dimen/myFixedSize"
android:alignParentBottom="true"
android:orientation="vertical"
android:clipChildren="false">
<MyHandleView xmlns:custom="http://schemas.android.com/apk/res-auto.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp"
custom:handleHeight="@dimen/card_panel_handle_height"
custom:handleWidthRatio="@dimen/card_panel_handle_width_ratio"
custom:handleBackgroundColor="#000"/>
<TextView
android:id="@+id/loyaltyCardPanelTitle"
android:layout_width="match_parent"
android:layout_height="@dimen/card_panel_height"
android:background="#000"
android:gravity="center"
android:textStyle="bold"
android:textSize="24sp"
android:textColor="#fff"
android:text="My TEXT"/>
</LinearLayout>
</RelativeLayout>
您可以將片段視為包含底部兩個按鈕的視圖,位於LinearLayout中。
代替外部RelativeLayout,我實際上正在使用庫中的視圖:SlidingUpPanelLayout( https://github.com/umano/AndroidSlidingUpPanel )。 但我測試了這個RelativeLayout的行為:同樣的事情,意味着庫沒有關系。
我這樣說只是為了讓你知道我不能只在那里放置一個FrameLayout並避免在剪切邊界之外繪制 。
我懷疑這與以下事實有關:當我觸摸按鈕時它重繪自己,但我的另一個視圖(在層次結構中的其他位置)不會被重新繪制(這是一個優化,我懷疑它可以是禁用)。
我希望能夠在任何其他“近”(或任何)視圖失效時使我的自定義視圖無效,因此我需要某種關於視圖失效的監聽器,但我不知道任何。
有人可以幫忙嗎?
我自己找到了解決方案,即使這不是表演的最佳選擇。
只需添加:
android:clipChildren="false"
到RelativeLayout(或你有的任何布局)。
這有2個效果(可能更多,這是我感興趣的兩個): - ViewGroup不剪切他的孩子的繪圖(顯而易見) - ViewGroup在考慮時不檢查與臟區域的交集(無效)哪些孩子要重繪
我挖掘了有關無效的View代碼。
這個過程更像或更喜歡這樣:
在第4步中,涉及剪切:僅當clipChildren為true時,ViewGroup檢查其子項的視圖邊界:這意味着如果將其置於false,則當它們中的任何一個無效時,它總是重繪其所有子項 。
所以,我的View層次結構是這樣的:
ViewGroup A
|
|----- fragment subtree (containing buttons, map,
| whatever element that I don't want to draw
| on top of my handle)
|
|----- ViewGroup B
|
|---- my handle (which draw outside its clip bounds)
在我的情況下,“句柄”繪制它的束縛,在通常由片段子樹的某個元素繪制的東西之上。
當片段內的任何視圖無效時,它會在視圖樹中向上傳遞其“臟區域”,並且每個視圖組都會檢查是否有其他子項要在該區域中重繪。
如果我沒有在其上設置clipBounds =“false” ,ViewGroup B會剪切我在剪輯邊界外繪制的內容。
如果片段子樹中的任何內容無效,則ViewGroup A將看到ViewGroup B臟區域未與片段子樹區域相交,並將跳過重繪ViewGroup B.
但是,如果我還告訴ViewGroup A不剪輯子節點,它仍然會給ViewGroup B一個無效命令,這將導致重新繪制我的句柄。
所以解決方案是確保設置
android:clipChildren="false"
在視圖上方的層次結構中的任何ViewGroup上繪制出內容可能落在您正在繪制的越界區域“下方”的邊界。
這種明顯的副作用是,每當我使ViewGroup A中的任何視圖無效時,無效區域將被轉發到其中的所有視圖。
但是,將跳過任何與使用clipChildren =“true”(默認值)的ViewGroup內的臟區域不相交的視圖。
因此,為避免在執行此操作時出現性能問題,請確保具有clipChildren =“true”的視圖組沒有多少“標准”直接子項。 而對於“標准”,我的意思是他們不會超出他們的視角。
因此,例如,如果在我的示例中,ViewGroup B包含許多視圖,請考慮使用clipChildren =“true”將所有這些視圖包裝在ViewGroup中,並且只將此視圖組和在其區域之外繪制的視圖作為ViewGroup B的直接子項保留。同樣如此對於ViewGroup A.
這個簡單的事實將確保沒有其他View將重繪,如果它們不在無效的臟區域中,最小化所需的重繪。
如果有人有話,我仍然願意再聽一次;)
所以我會等一下,然后將其標記為已接受的答案。
編輯:許多設備在處理clipChildren =“false”時做了一些不同的事情。 我發現我必須在我的自定義窗口小部件的所有父視圖上設置clipChildren =“false”,這些視圖可能包含其層次結構中應該繪制窗口小部件的“越界區域”的元素,或者您可能會看到自定義繪圖顯示應該覆蓋它的另一個視圖的TOP。 例如,在我的布局中,我有一個導航抽屜,應該覆蓋我的“手柄”。 如果我沒有在NavigationDrawer布局上設置clipChildren =“false”,我有時會看到我的手柄彈出打開的抽屜前面。
編輯2:我的自定義小部件有0高度,並繪制自己“頂部”。 在Nexus設備上工作得很好,但其他許多設備都有一些“優化”,可以完全跳過繪制高度為0或寬度為0的視圖。 因此,如果您想要編寫一個從其界限中繪制的組件,請注意這一點:您必須為其指定至少1個像素的高度/寬度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.