美文网首页
Android 事件冲突处理

Android 事件冲突处理

作者: 我要离开浪浪山 | 来源:发表于2023-05-04 23:40 被阅读0次

1、处理冲突:

1.内部拦截法(由子View根据条件来让事件由谁处理),一定要想办法让子View拿到事件;
2.外部拦截法(由父容器处理)

ViewPage和ListView事件冲突.png

2、公共类

package com.leo.dispatch;

import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private int[] iv = new int[]{R.mipmap.iv_0, R.mipmap.iv_1, R.mipmap.iv_2,
            R.mipmap.iv_3, R.mipmap.iv_4, R.mipmap.iv_5,
            R.mipmap.iv_6, R.mipmap.iv_7, R.mipmap.iv_8};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_viewpager);
        BadViewPager pager = findViewById(R.id.viewpager);

        List<Map<String, Integer>> strings = new ArrayList<>();

        Map<String, Integer> map;

        for (int i = 0; i < 20; i++) {
            map = new HashMap<>();
            map.put("key", iv[i % 9]);
            strings.add(map);
        }

        MyPagerAdapter adapter = new MyPagerAdapter(this, strings);
        pager.setAdapter(adapter);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.leo.dispatch.BadViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
package com.leo.dispatch;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import androidx.viewpager.widget.PagerAdapter;

import java.util.List;
import java.util.Map;

public class MyPagerAdapter extends PagerAdapter {

    private Context mContext;
    private List<Map<String, Integer>> mData;


    public MyPagerAdapter(Context context, List<Map<String, Integer>> list) {
        mContext = context;
        mData = list;
    }

    @Override
    public int getCount() {
        return 5;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = View.inflate(mContext, R.layout.item_list, null);
        ListView list = view.findViewById(R.id.list);
        list.setAdapter(new SimpleAdapter(container.getContext(), mData, R.layout.item_base, new String[]{"key"}, new int[]{R.id.iv}));
        container.addView(view);
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}

3、内部拦截法

1、MyListView

package com.leo.dispatch;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;

// 子View -- 容器 -- ViewGroup.dispatchTouchEvent --> super.dispatchTouchEvent
public class MyListView extends ListView {

    public MyListView(Context context) {
        super(context);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private int mLastX, mLastY;

    /**
     * 内部拦截处理
     *
     * @param event
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                //请求父容器不拦截
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                // deltaX>deltaY,让父容器拦截,执行父容器的左右滑动
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    //请求父容器拦截
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                break;

            }
            default:
                break;
        }

        mLastX = x;
        mLastY = y;
        return super.dispatchTouchEvent(event);
    }
}

2、BadViewPager

package com.leo.dispatch;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.ViewPager;

// 父容器
public class BadViewPager extends ViewPager {

    private int mLastX, mLastY;

    public BadViewPager(@NonNull Context context) {
        super(context);
    }

    public BadViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    // 内部拦截法
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        // down事件的时候不能拦截,因为这个时候 requestDisallowInterceptTouchEvent 无效
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            super.onInterceptTouchEvent(event);
            return false;
        }
        return true;
    }
}

4、外部拦截法

package com.leo.dispatch;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.ViewPager;

// 父容器
public class BadViewPager extends ViewPager {

    private int mLastX, mLastY;

    public BadViewPager(@NonNull Context context) {
        super(context);
    }

    public BadViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    // 外部拦截法:一般只需要在父容器处理,根据业务需求,返回true或者false
    public boolean onInterceptTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                mLastX = (int) event.getX();
                mLastY = (int) event.getY();
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    return true;
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                break;
            }
            default:
                break;
        }

        return super.onInterceptTouchEvent(event);
    }
}

5、Kotlin 中Math.abs的用法

Kotlin中的Math.abs()函数用于返回一个数的绝对值。它接受一个参数,可以是任何数字类型,包括整数、浮点数等。
例如,以下代码将返回-5的绝对值:

val num = -5
val absNum = Math.abs(num)
println(absNum) // 输出:5

如果参数是正数,则返回该数本身。如果参数是负数,则返回该数的相反数。

相关文章

  • Android 事件冲突处理

    概述 本文主要分享Android常见的事件冲突处理,处理方式有两种: 外部拦截:父容器处理冲突 内部拦截:子控件处...

  • android事件分发机制

    android中的事件处理,以及解决滑动冲突问题都离不开事件分发机制,android中的事件流,即MotionEv...

  • Android事件分发|事件冲突处理

    android的事件分发在面试时算是高频问题,工作中也能用到,这里将事件分发、事件冲突,和NestedScroll...

  • Android触摸事件机制

    在Android开发中经常会遇到事件冲突(如滑动事件),要处理这类问题需要了解事件传递机制,一次完整的事件主要包括...

  • android 事件分发以及滑动冲突

    android 事件分发以及滑动冲突 Android Activity 页面布局如下: view 的事件分发机制 ...

  • android 事件分发原理

    事件分发在 android 中实在是太重要了,滑动冲突的前置基础知识,滑动冲突不会处理,那么大部分页面效果是写不出...

  • android点击事件与触摸冲突

    Android ontouch 拖动与点击事件冲突解决方式

  • Android-解决事件冲突和处理滑动事件

    1.解决事件冲突的主要思路 1.down事件首先会传递到onInterceptTouchEvent()方法 2.如...

  • 二十二、事件处理

    Android提供了强大的事件处理机制,包含两套事件处理机制:基于监听的事件处理:为Android界面组件绑定特定...

  • Android 事件冲突

    单点的Down 事件 dispatchTouchEvent(MotionEvent ev) 来处理事件分发(Vie...

网友评论

      本文标题:Android 事件冲突处理

      本文链接:https://www.haomeiwen.com/subject/rssfsdtx.html