即使设置为 false,clipChildren 也无法正常工作?

Posted

技术标签:

【中文标题】即使设置为 false,clipChildren 也无法正常工作?【英文标题】:clipChildren is not working even though set to false? 【发布时间】:2014-04-08 07:41:34 【问题描述】:

在我的应用程序中,我尝试使用动画来移动图像。 即使我在每个 xml 块中使用 clipChildren false ,当我尝试对图像进行动画处理时,图像也会被剪切

    <RelativeLayout
        android:id="@+id/baselayout"
        android:layout_
        android:layout_
        android:layout_alignParentRight="true"
        android:layout_below="@+id/imageView1"
        android:clipChildren="false"
        android:clipToPadding="false" >

【问题讨论】:

对于在此处使用谷歌搜索的任何人,请注意 roflharrison 已经解决了问题,但是 roflharrison 给出的代码示例中存在错误。正确代码:***.com/a/53654808/294884 【参考方案1】:

RelativeLayout 的父级之一可能正在裁剪子级(有时兼容性库会添加一个神秘的 ViewGroup,例如 NoSaveStateFrameLayout)。我过去曾成功地使用过类似的方法来禁用视图的所有父级上的剪辑:

public void disableClipOnParents(View v) 
    if (v.getParent() == null) 
        return;
    

    if (v instanceof ViewGroup) 
        ((ViewGroup) v).setClipChildren(false);
    

    if (v.getParent() instanceof View) 
        disableClipOnParents((View) v.getParent());
    

【讨论】:

它对我有用,谢谢你的回答!显然,当您包含布局时会添加一些视图,这对我来说是个问题。 更新:我使用的是支持库 21.0.3。更新到 22.0.0 为我解决了这个问题! 它对我有用。但是遇到一个问题。条件是:假设 ListView_1 有 RelativeLayout_1 父级。 ListView_1 是RelativeLayout_2 的父级。 ImageView_1 的 RelativeLayout_2 父级。我需要为孩子“ImageView_1”设置动画并将其移到父母之外,而不是我使用你的方法。它工作得很好,但是在滚动列表时,ListView_1 也出现了 RelativeLayout_1。是否可以只对一个孩子应用剪辑? 对于未来的读者:以编程方式设置可能不适用于在 android 4.x 设备上留下对话框片段的动画视图。但是通过 XML 为所有ViewGroups 设置clipChildrenclipToPadding + 在onAnimationUpdate 事件上使fragment root view 无效就可以了。由于某些原因,我真的不明白,以编程方式设置剪辑设置 + 使 4x 设备上的根视图无效does not work。在 5x 设备上,它可以在没有 XML 和手动失效的情况下工作。 系统将您的视图包装到辅助视图组中并不明显。如果您想查看它的实际效果,请打开 Layout Inspector 以查看您遇到 clipChildren="false" 无法正常工作的情况,您可能会在您的层次结构中找到一个神秘的 ViewGroup。【参考方案2】:

我知道已经晚了,但这是最简单的完整答案:

只需放置每个布局:

    android:clipChildren="false"
    android:clipToPadding="false"

注意@roflharrison 提到: 这在操作系统将您的视图包装/注入不在您的布局中的 ViewGroup 中的情况下不起作用

【讨论】:

正如我在回答中所解释的,这在操作系统将您的视图包装/注入不在您的布局中的 ViewGroup 中的情况下不起作用。 是的,没错【参考方案3】:

最后一个原因是“RelativeLayout”。 所以要解决它,不要使用 RelativeLayout 作为大于父控件的父控件。取而代之的是 FrameLayout,例如:

<!-- it's ok as grand parent -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_
                android:layout_
                android:clipChildren="false">

    <!-- parent must not be a RelativeLayout -->
    <FrameLayout
        android:layout_
        android:layout_
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="9dp">

        <!-- Your Larger-than-parent View -->
        <View
            android:layout_
            android:layout_
            android:layout_gravity="center"
            android:background="@android:color/black" />

    </FrameLayout>

</RelativeLayout>

【讨论】:

【参考方案4】:

@roflharrison 的想法很好,但是代码有一些问题: 这里我们递归地禁用了clipChildren,但是当我们到达根视图时,它的v.getParents()会为null,方法立即返回,并且它的ClipChildren属性不会被禁用。

更重要的是,对于以下行:

if (v.getParent() instanceof View)

??视图的父级不应该是 ViewGroup 吗?我们不应该禁用 ViewGroup 的剪辑属性,而不是 View 的吗?于是我把代码改成下面这样,效果还不错:

public void disableClipOnParents(View v) 
    if (v == null) 
        return;
    
    if (v instanceof ViewGroup) 
        ((ViewGroup) v).setClipChildren(false);
    
    disableClipOnParents((View) v.getParent());

【讨论】:

正确答案谢谢!! 请注意,您可能还希望设置setClipToPadding(false) 这也不适用于所有设备。在将其转换为 View 之前,您应该检查 v.getParent() instanceof View。你最终可能会得到ClassCastException: android.view.ViewRootImpl cannot be cast to android.view.View 或类似的东西。有多种情况会发生这种情况 (see search results)。【参考方案5】:

您好~如果您的布局包含“paddingXXX”标签,您可以删除它们并重试。对我有用~

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:clipChildren="false"
    android:gravity="center_vertical"
    android:padding="8dp"
    android:orientation="horizontal">

上面的代码会裁剪 childView 而下一个不会:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:clipChildren="false"
    android:gravity="center_vertical"
    android:orientation="horizontal">

【讨论】:

【参考方案6】:

在我的情况下,clipChildren=false 不起作用,因为我还在代码中的父级上设置了 clipToOutline = true。这个属性导致孩子被剪裁在父母的轮廓中,在我的例子中是父母背景的轮廓。似乎clipToOutline 的优先级高于clipChildren=false

如果clipChildren=false 不适合您,请确保您没有在代码中设置clipToOutline=true

【讨论】:

以上是关于即使设置为 false,clipChildren 也无法正常工作?的主要内容,如果未能解决你的问题,请参考以下文章

ViewGroup中clipChildren属性的用法

clipChildren属性

clipChildren属性

android:clipchildren属性

Android开发实战(二十一):浅谈android:clipChildren属性

仿淘宝Android实现底部导航栏图标溢出效果-clipChildren属性