Fragment叠加点击穿透的解决方案

本文探讨了Fragment叠加时出现的点击穿透问题及三种解决方案:通过设置clickable属性、为View添加触摸监听并返回true以及为View设置点击监听。这些方法能够有效避免点击事件穿透到下方Fragment的问题。

Fragment叠加出现点击穿透的解决方案

参考文档:
https://blog.youkuaiyun.com/dong19870625/article/details/50550147
https://blog.youkuaiyun.com/joye123/article/details/77075274

Fragment在开发中很常见,经常会有Fragment叠加的需求,最近在开发中遇到一个现象,在Fragment中add 多个Fragment的时候,当最上方的Fragment点击空白处时,会发生点击穿透,下层在所点击处对应的控件的点击事件就会被触发,怎么解决呢?

出现问题的原因

原因:Fragment的本质就是一个View布局的管理器,当Fragment attach到Activity时,其实就是把Fragment#onCreateView()返回的View,替换掉(如果是用replace)FragmentTransaction#replace中指定的View,或者添加到(如果是add)FragmentTransaction#add()中指定的ViewGroup里面。
当我们以层叠方式显示多个Fragment时,通常的做法就是弄一个FrameLayout,然后每次把Fragment add到此布局。因此,这时Activity的页面布局树实际上就是一个FrameLayout里面包含几个View。
所以,当点击上面Fragment的空白区域时,如果事件没被吃掉,就会向下传递。

解决方案

方式一:在根布局中添加属性android:clickable=”true”

或者在代码中设置:

缺点:需要在每一个Fragment的根布局处添加,Fragment较多的时候,工作量大。

方式二:创建Fragment的基类,在基类中为View添加触摸监听,并返回true

这种方式避免了多处添加clickable的麻烦,但是同时带来一个问题,如果Fragment的根布局使用的是ScrollView,那么就无法滚动了,因为触摸事件已经消费掉了,但如果根布局不是ScrollView的话,就可以用此方式。

方式三:在基类中为 View设置点击监听,而不是触摸监听

此方式可以解决事件穿透,同时不影响根布局是ScrollView的情况。

简单验证Demo:https://github.com/gqq519/FragmentClickIssue

// 保存为 TechBlackTransparent.shader Shader “Custom/TechBlackTransparent” { Properties { [Header(Base Settings)] _MainColor(“主颜色”, Color) = (0,0,0,0.5) _Smoothness(“光滑度”, Range(0,1)) = 0.8 _Metallic(“金属度”, Range(0,1)) = 0.5 [Header(Edge Glow)] _FresnelColor("边缘光颜色", Color) = (0,1,1,1) _FresnelPower("边缘衰减", Range(1,5)) = 3 _FresnelIntensity("边缘强度", Range(0,5)) = 2 [Header(Scan Line)] _ScanTex("扫描线贴图", 2D) = "white" {} _ScanTiling("贴图平铺", Float) = 5 _ScanSpeed("移动速度", Float) = 1 _ScanIntensity("扫描强度", Range(0,1)) = 0.3 } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" "RenderPipeline"="UniversalPipeline" } Pass { Blend SrcAlpha OneMinusSrcAlpha ZWrite Off HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionHCS : SV_POSITION; float3 worldNormal : TEXCOORD1; float3 viewDir : TEXCOORD2; float2 uv : TEXCOORD0; float3 worldPos : TEXCOORD3; }; // 材质属性 CBUFFER_START(UnityPerMaterial) float4 _MainColor; float _Smoothness; float _Metallic; float4 _FresnelColor; float _FresnelPower; float _FresnelIntensity; sampler2D _ScanTex; float4 _ScanTex_ST; float _ScanTiling; float _ScanSpeed; float _ScanIntensity; CBUFFER_END Varyings vert(Attributes IN) { Varyings OUT; OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); OUT.worldNormal = TransformObjectToWorldNormal(IN.normalOS); OUT.viewDir = GetWorldSpaceViewDir(TransformObjectToWorld(IN.positionOS.xyz)); OUT.uv = TRANSFORM_TEX(IN.uv, _ScanTex); OUT.worldPos = TransformObjectToWorld(IN.positionOS.xyz); return OUT; } half4 frag(Varyings IN) : SV_Target { // 基础材质 half4 color = _MainColor; // 边缘光计算 float3 N = normalize(IN.worldNormal); float3 V = normalize(IN.viewDir); float fresnel = pow(1.0 - saturate(dot(N, V)), _FresnelPower); half3 edgeGlow = _FresnelColor.rgb * fresnel * _FresnelIntensity; // 扫描线效果 float2 scanUV = IN.uv * _ScanTiling + float2(0, _Time.y * _ScanSpeed); float scan = tex2D(_ScanTex, scanUV).r * _ScanIntensity; // 最终合成 color.rgb += edgeGlow + scan; color.a = _MainColor.a; // 物理渲染参数 color.a *= 1 - fresnel * 0.3; // 边缘透明变化 return half4(color.rgb, color.a); } ENDHLSL } } }我复制之后材质变透明了,怎么办
03-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值