解决冲突的两种解决套路

/**

  • https://blog.youkuaiyun.com/caifengyao/article/details/65437695?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight
  • http://cache.baiducontent.com/c?m=mvBtrNWuT6MbBxyIL8-bLvI8F1CAmzvl_L1TBw2WalAHli8MrEIZIlGN9g_WLZ31DRgzaOZs2CkLSQDAFB15C5CqlO0uzorHN3eQqihiXmaFaF1FXBw9wegAnHWx_QHnpzA5RsxGHPghxXbPrNeOsMAygGTWk0WLbPw2LGKm8eqcgvRQ3Kz1tyGwTpI5ELZX&p=8179de5ece904ead08e2977e065295&newp=8679cd0495934eac58e6852d021483231610db2151d6d2146b82c825d7331b001c3bbfb423281a04d3cf7a6d03ad425ee8f73d75330923a3dda5c91d9fb4c5747999&s=c9f0f895fb98ab91&user=baidu&fm=sc&query=requestdisallowintercept++%CA%B9%D3%C3%B7%BD%CA%BD&qid=f1f9d2db0004ca4d&p1=3
    */

滑动冲突的两种解决套路

   前面我们将滑动冲突分为了3种场景,并根据每一种场景提供了解决冲突的思路。但是这些思路解决的是判断条件问题,即什么情况下事件交给谁的问题。这一节将抛开前面的场景分类,介绍对所有场景适用的两种通用解决方法,
   可以通俗地理解为处理滑动冲突的“套路”。这两种解决滑动冲突的方式为:外部拦截法和内部拦截法。

1、外部拦截法

   顾名思义,就是在外部滑动控件中处理拦截逻辑。这需要外部控件重写父类的onInterceptTouchEvent方法,在其中判断什么时候需要拦截事件由自身处理,什么时候需要放行将事件传给内层控件处理,内部控件不需要做任何处理。
   这个“套路”的伪代码表示所示:

复制代码

1 @Override
2 public boolean onInterceptTouchEvent(MotionEvent ev) {
3 boolean intercepted = false;
4 switch (ev.getAction()){
5 case MotionEvent.ACTION_DOWN:
6 intercepted = false;
7 break;
8 case MotionEvent.ACTION_MOVE:
9 if(父容器需要自己处理改事件){
10 intercepted = true;
11 }else {
12 intercepted = false;
13 }
14 break;
15 case MotionEvent.ACTION_UP:
16 intercepted = false;
17 break;
18 default:
19 break;
20 }
21 return intercepted;
22 }
复制代码

前面对滑动处理的场景分类,并对不同场景给了分析思路,它们的作用就是在这里的第9行来做判断条件的。所以,不论什么场景,都可以在这个套路的基础上,修改判断是否拦截事件的条件语句即可。另外,需要说明一下的是,第6行和第16行,
这里都赋值为false,因为ACTION_DOWN如果被拦截了,该动作序列的其它事件就都无法传递到子View中了,ListView也就永远不能滑动了;而ACTION_UP如果被拦截,那子View就无法被点击了,这两点我们前面的文章都讲过,这里再强调一下。

2、内部拦截法

   顾名思义,就是将事件是否需要拦截的逻辑,放到内层控件中来处理。这种方式需要结合requestDisllowInterceptTouchEvent(boolean),在内层控件的重写方法dispatchTouchEvent中,根据逻辑来决定外层控件何时需要拦截事件,
   何时需要放行。伪代码如下:

复制代码

1 @Override
2 public boolean dispatchTouchEvent(MotionEvent ev) {
3 switch (ev.getAction()){
4 case MotionEvent.ACTION_DOWN:
5 getParent().requestDisallowInterceptTouchEvent(true);
6 break;
7 case MotionEvent.ACTION_MOVE:
8 if (父容器需要处理改事件) {
9 //允许外层控件拦截事件
10 getParent().requestDisallowInterceptTouchEvent(false);
11 } else {
12 //需要内部控件处理该事件,不允许上层viewGroup拦截
13 getParent().requestDisallowInterceptTouchEvent(true);
14 }
15 break;
16 case MotionEvent.ACTION_UP:
17 break;
18 default:
19 break;
20 }
21 return super.dispatchTouchEvent(ev);
22 }
复制代码

除此之外,还需要外层控件在onInterceptTouchEvent中做一点处理:

复制代码

1 @Override
2 public boolean onInterceptTouchEvent(MotionEvent ev) {
3 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
4 return false;
5 } else {
6 return true;
7 }
8 }
复制代码

ACTION_DOWN事件仍然不能拦截,上一篇文章分析源码的时候讲过,ACTION_DOWN时会初始化一些状态和标志位等变量,requestDisllowInterceptTouchEvent(boolean)作用会失效。这里再顺便强调一下,不明白的可以去上一篇文章中阅读这部分内容。

   这种方式比“外部拦截法”稍微复杂一些,所以一般推荐使用前者。同前者一样,这也是一个套路用法,无论是之前提到的何种场景,只要根据实际判断条件修改上述if语句即可。对于requestDisllowInterceptTouchEvent(boolean)的相关信息,在前面的文章中介绍过,这里不再赘述了。

修改 dispatchTouchEvent方法 来处理事件冲突
PagerIndicator把事件给拦截了 我修改了他的 dispatchTouchEvent方法 请求他爹和他祖宗不要拦截我的事件

根据事件分发机制 dispatchTouchEvent->interceptTouchEvent->onTouchEvent

具体参看

http://www.cnblogs.com/AceIsSunshineRain/p/5187118.html

TabPagerIndicator.java

   @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
       // 请求父控件及祖宗控件不要拦截当前控件的时间
       getParent().requestDisallowInterceptTouchEvent(true);
       return super.dispatchTouchEvent(ev);
<think>好的,我现在需要回答用户关于在Android项目中是否为手机和平板分别创建不同的AndroidManifest文件的问题。首先,我需要确认Android项目结构是否支持这样的配置。根据我的了解,Android使用Gradle构建系统,允许通过不同的构建变体来配置不同的资源,包括清单文件。 接下来,我应该检查用户提供的引用内容。引用[2]提到了在AndroidManifest中使用<meta-data>标签指定设计稿尺寸,而引用[3]讨论了AndroidManifest.xml中的<uses-library>和<supports-screens>标签。虽然这些引用没有直接回答用户的问题,但可以推测用户可能希望根据不同设备类型调整配置。 然后,我需要回忆Android开发中的资源目录结构。通常,main目录包含默认资源,而构建变体如src/main、src/demo、src/full等可以覆盖或添加特定配置。不过,设备类型(手机或平板)通常通过屏幕尺寸或密度来区分,而不是构建变体。因此,正确的做法可能是使用资源限定符,例如为不同的屏幕尺寸创建不同的资源目录,如res/layout-sw600dp用于平板。 关于AndroidManifest.xml,默认情况下每个构建变体可以有自己的清单文件,但主清单会被合并。因此,用户无法直接为手机和平板创建完全独立的清单文件,但可以通过合并规则或条件配置来调整内容。例如,使用<uses-feature>或<supports-screens>标签来声明设备支持,或者通过Gradle配置在构建时注入不同的元数据。 需要验证是否可以通过product flavors在Gradle中为不同设备类型指定不同的清单文件。查阅资料发现,Gradle的productFlavors允许为每个flavor指定自己的src/flavorName目录,其中可以包含特定的AndroidManifest.xml。这样,用户可以为手机和平板创建不同的flavor,各自拥有独立的清单文件,并在构建时合并到主清单中。 但需要注意的是,清单文件的合并可能会有冲突,需要确保主清单和flavor清单中的组件和配置正确合并。此外,如果用户希望根据设备类型自动选择配置,而不是构建不同的APK,可能需要使用资源限定符或在代码中动态判断设备类型。 总结来说,直接为手机和平板创建完全独立的清单文件可能不太符合标准做法,但通过Gradle的构建变体和清单合并功能,可以实现不同配置的需求。需要指导用户如何设置product flavors,并说明如何管理清单合并的潜在问题。</think>在Android项目中,可以通过以下两种方式为手机和Pad设备分别配置独立的清单文件: ### 一、通过Gradle的Product Flavors实现 1. **创建产品风味(Product Flavors)** 在`build.gradle`中定义两种风味: ```groovy android { productFlavors { phone { // 手机专属配置 manifest.srcFile "src/phone/AndroidManifest.xml" } pad { // Pad专属配置 manifest.srcFile "src/pad/AndroidManifest.xml" } } } ``` 在`src/phone`和`src/pad`目录下分别放置独立的`AndroidManifest.xml`文件[^2]。 2. **清单文件合并规则** 主模块的`AndroidManifest.xml`会与风味清单文件自动合并。需注意: - 若组件(如Activity)重复,需使用`tools:replace`处理属性冲突 - 差异化配置(如权限、屏幕支持)应在各自风味清单中声明 ### 二、通过资源限定符动态配置 1. **条件化配置元素** 在**主清单文件**中使用资源限定符: ```xml <!-- 手机专属配置 --> <uses-feature android:name="android.hardware.telephony" android:required="true" tools:node="merge" /> <!-- 平板专属配置 --> <supports-screens android:requiresSmallestWidthDp="600" android:name="android.screen.tablet" tools:node="merge" /> ``` 通过`android:required`和屏幕尺寸限定符实现条件配置[^3]。 ### 三、最佳实践建议 1. **差异化场景** - **完全不同的组件结构** → 选择Product Flavors方案 - **部分配置调整** → 使用清单合并+资源限定符 2. **构建管理** ```bash # 生成手机版APK ./gradlew assemblePhoneRelease # 生成Pad版APK ./gradlew assemblePadRelease ``` 3. **动态检测设备类型** 在代码中通过屏幕尺寸判断: ```java boolean isTablet = getResources().getBoolean(R.bool.isTablet); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值