Fragment防穿透

当Fragment在Activity中使用时,可能会出现点击Fragment空白区域却触发了Activity或其它Fragment的事件。本文介绍了三种防止Fragment穿透的方法:1. 自定义Fragment基类处理onTouch事件;2. 设置Fragment最外层布局背景非透明;3. 设置Fragment最外层布局clickable属性为true。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Fragment防穿透

Fragment使用时,以碎片的形式存在于activity中,有时会出现这样的情况:明明点击的是fragment的空白处,却触发了Activity里面或其他Fragment的点击事件,再或者自己写的某个局部页面覆盖在其他元素之上,或者FrameLayout,也会出现类似的[穿透][6]现象,为避免这种情况,有以下方法可以尝试:

  • 自定义Fragment基类,处理onTouch事件
  • layout.xml中设置Fragment最外层布局背景非透明(且非默认)
  • layout.xml中设置Fragment最外层布局clickable=true

方法一:自定义Fragment基类

public abstract class BaseAidlFragment extends Fragment implements  OnTouchListener {
    protected View mView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        mView = inflater.inflate(getLayoutId(), container, false);
        mView.setOnTouchListener(this);
        return mView;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // 防Fragment穿透现象
        return true;
    }
}
//据说此方法可能会跟自定义onTouch事件有冲突,不过我认为此处应该不影响,合理理由逻辑关系控制事件传递即可

方法二:设置布局背景

此方法应该设置的是最外层布局的背景或者防穿透部分的布局
android:background=”@color/xxxxx”
此方法未亲测,不清楚,据说有效~~

方法三:设置父布局clickable=true

此方法应该设置的是最外层布局的背景或者防穿透部分的布局
android:clickable=”true”
此方法经测有效。

最近遇到相关问题,综合网络各前辈知识,记述于此,以备温习。

private void generateIPv4FilterLocked(ApfV4GeneratorBase<?> gen) throws IllegalInstructionException { // Here's a basic summary of what the IPv4 filter program does: // // if the network is IPv6 only network: // if the packet is fragmented: // drop // if the packet is a dhcp packet comes from server: // pass // else // drop // if filtering multicast (i.e. multicast lock not held): // if it's DHCP destined to our MAC: // pass // if it's L2 broadcast: // drop // if it's IPv4 multicast: // drop // if it's IPv4 broadcast: // drop // if keepalive ack // drop // pass if (mHasClat) { // Check 1) it's not a fragment. 2) it's UDP. // Load 16 bit frag flags/offset field, 8 bit ttl, 8 bit protocol gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); gen.addCountAndDropIfR0NotEquals(0xFF11, Counter.DROPPED_IPV4_NON_DHCP4); // Check it's addressed to DHCP client port. gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad32Indexed(R0, TCP_UDP_SOURCE_PORT_OFFSET); gen.addCountAndDropIfR0NotEquals(DHCP_SERVER_PORT << 16 | DHCP_CLIENT_PORT, Counter.DROPPED_IPV4_NON_DHCP4); gen.addCountAndPass(Counter.PASSED_IPV4_FROM_DHCPV4_SERVER); return; } if (mMulticastFilter) { final String skipDhcpv4Filter = gen.getUniqueLabel(); // MIUI ADD:NETWORK_BugFixUpstream final String skipIcmpEchoFilter = "skip_icmp_echo_filter"; final String skipNbnsAndDhcpv4Filter = "skip_nbns_and_dhcp_v4_filter"; // END NETWORK_BugFixUpstream // MIUI ADD: WIFI_PowerSave final String dropIcmpUnreachedPort = "dropIcmpUnreachedPort"; final String skipIcmpUnreachedFilter = "skipIcmpUnreachedFilter"; gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); String mifstr = ""; for (Pair<UnreachedPortInfo, ServerSocket> pair: icmpUnreachedPortOccupied) { gen.addJumpIfR0Equals(pair.first.port, dropIcmpUnreachedPort); mifstr += pair.first.toString(); } Log.d(mTAG, "add port:" + mifstr); gen.addJump(skipIcmpUnreachedFilter); gen.defineLabel(dropIcmpUnreachedPort); gen.addCountAndDrop(Counter.DROPPED_ICMP_UNREACHED); gen.defineLabel(skipIcmpUnreachedFilter); // END WIFI_PowerSave // Pass DHCP addressed to us. // Check it's UDP. gen.addLoad32(R0, IPV4_FRAGMENT_OFFSET_OFFSET); gen.addOr(0xFF00); // MIUI MOD:NETWORK_BugFixUpstream // gen.addJumpIfR0NotEquals(IPPROTO_UDP, skipDhcpv4Filter); gen.addJumpIfR0NotEquals(0xFF11, skipNbnsAndDhcpv4Filter); // END NETWORK_BugFixUpstream // Check it's not a fragment or is the initial fragment. // Check it's addressed to DHCP client port. gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET); gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, skipDhcpv4Filter); // Check it's DHCP to our MAC address. gen.addLoadImmediate(R0, DHCP_CLIENT_MAC_OFFSET); // NOTE: Relies on R1 containing IPv4 header offset. gen.addAddR1ToR0(); // MIUI MOD:NETWORK_BugFixUpstream // gen.addJumpIfBytesAtR0NotEqual(mHardwareAddress, skipDhcpv4Filter); gen.addJumpIfBytesAtR0NotEqual(mHardwareAddress, skipNbnsAndDhcpv4Filter); // END NETWORK_BugFixUpstream gen.addCountAndPass(Counter.PASSED_DHCP); // Drop all multicasts/broadcasts. // MIUI ADD:NETWORK_BugFixUpstream // Then it'll be checking if it's NBNS packet. // END NETWORK_BugFixUpstream gen.defineLabel(skipDhcpv4Filter); // MIUI ADD: NETWORK_BugFixUpstream // For NBNS Filtering. // Check if it's Nbns packet. gen.addCountAndDropIfR0Equals(NBNS_CLIENT_PORT, Counter.DROPPED_NBNS); // It's not "DHCP to our MAC addr" or "NBNS". Then to Drop all multicasts/broadcasts. gen.defineLabel(skipNbnsAndDhcpv4Filter); // END NETWORK_BugFixUpstream // MIUI ADD:NETWORK_BugFixUpstream String isFactoryBuild = SystemProperties.get("ro.boot.factorybuild", "0"); if (!SystemProperties.get(PROPERTY_APF_DROP_IGNORE, "").contains("icmp_echo") && !TextUtils.equals(isFactoryBuild,"1")) { // Check if it's Icmp. gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET); gen.addJumpIfR0NotEquals(IPPROTO_ICMP, skipIcmpEchoFilter); // Check if it's Icmp Echo gen.addLoad8(R0, IPV4_TYPE_ICMP_ECHO_OFFSET); gen.addCountAndDropIfR0Equals(ICMP_ECHO, Counter.DROPPED_ICMP_ECHO); gen.defineLabel(skipIcmpEchoFilter); } // END NETWORK_BugFixUpstream // If IPv4 destination address is in multicast range, drop. gen.addLoad8(R0, IPV4_DEST_ADDR_OFFSET); gen.addAnd(0xf0); gen.addCountAndDropIfR0Equals(0xe0, Counter.DROPPED_IPV4_MULTICAST); // If IPv4 broadcast packet, drop regardless of L2 (b/30231088). gen.addLoad32(R0, IPV4_DEST_ADDR_OFFSET); gen.addCountAndDropIfR0Equals(IPV4_BROADCAST_ADDRESS, Counter.DROPPED_IPV4_BROADCAST_ADDR); if (mIPv4Address != null && mIPv4PrefixLength < 31) { int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength); gen.addCountAndDropIfR0Equals(broadcastAddr, Counter.DROPPED_IPV4_BROADCAST_NET); } } // If any TCP keepalive filter matches, drop generateV4KeepaliveFilters(gen); // If any NAT-T keepalive filter matches, drop generateV4NattKeepaliveFilters(gen); // If TCP unicast on port 7, drop generateV4TcpPort7FilterLocked(gen); if (mMulticastFilter) { // Otherwise, this is an IPv4 unicast, pass // If L2 broadcast packet, drop. // TODO: can we invert this condition to fall through to the common pass case below? gen.addLoadImmediate(R0, ETH_DEST_ADDR_OFFSET); gen.addCountAndPassIfBytesAtR0NotEqual(ETHER_BROADCAST, Counter.PASSED_IPV4_UNICAST); gen.addCountAndDrop(Counter.DROPPED_IPV4_L2_BROADCAST); } // Otherwise, pass gen.addCountAndPass(Counter.PASSED_IPV4); } 详细分析一下这段Java代码
最新发布
06-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值