• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android中View的滑动冲突——Android开发艺术探索笔记

Android中View的滑动冲突——Android开发艺术探索笔记

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android recyclerview,android scrollview,android surfaceview,android photoview,android wheelview等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android中View的滑动冲突——Android开发艺术探索笔记


介绍

相信开发Android的人都会有这种体会:从网上下载的demo运行的好好的,但是只要出现了滑动冲突,Demo就无法正常工作了。但是不用担心,解决滑动冲突有固定的模式,常见的有内部拦截和外部拦截两种,只要按照这个模式来就可以顺利解决。

常见的滑动冲突场景

常见场景

示例

示例

处理规则

对于场景1,处理规则为:当用户左右滑动时,让外部的View拦截点击事件,当用户上下滑动时,让内部的View拦截点击事件。当产生滑动时,根据滑动的起始点与终点坐标位置,如果垂直方向滑动距离大,就判断为垂直滑动,否则判断为水平滑动。其他两种情况处理方法相似,都是从业务需求上得出相应的规则。

解决方法

外部拦截发

所有的点击事件都先经过父容器拦截处理,如果父容器需要拦截就拦截,不需要就传给内部的View。伪代码如下

  public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = false;

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                intercepted = false;
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                if (满足父容器的拦截要求) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                intercepted = false;
                break;
            }
            default:
                break;
        }
        mLastXIntercept = x;
        mLastYIntercept = y;
        return intercepted;
    }

注:
ACTION_DOWN这个事件是不能拦截的,因为一旦拦截后续的事件都会由父容器处理了。

内部拦截法

父容器不拦截任何事件,所有事件都传给子元素。如果子元素需要此事件就直接消耗,否则就交给父容器进行处理。完成这个功能需要配合requestDisallowInterceptTouchEvent()方法才可。这个方法表示是否让父容器拦截事件。伪代码如下:

 public boolean dispatchTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            parent.requestDisallowInterceptTouchEvent(true);
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            if (满足父容器的拦截要求) {
                parent.requestDisallowInterceptTouchEvent(false);
            }
            break;
        }
        case MotionEvent.ACTION_UP: {
            break;
        }
        default:
            break;
        }
        mLastX = x;
        mLastY = y;
        return super.dispatchTouchEvent(event);
    }

注
父容器默认拦截除了ACTION_DOWN以外的其他事件,这样子当元素调用parent.requestDisallowInterceptTouchEvent(false)时,父元素才能拦截所需的事件。

总结

解决滑动冲突有两种方法,推荐外部拦截法,实现起来简单。 本文以场景1为例做了讲解,场景2,3的做法与1类似,都是根据业务需要制定处理规则。

示例效果的源码

Activity

public class DemoActivity_1 extends Activity {
    private static final String TAG = "DemoActivity_1";

    private HorizontalScrollViewEx mListContainer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.demo_1);
        Log.d(TAG, "onCreate");
        initView();
    }

    private void initView() {
        LayoutInflater inflater = getLayoutInflater();
        mListContainer = (HorizontalScrollViewEx) findViewById(R.id.container);
        final int screenWidth = MyUtils.getScreenMetrics(this).widthPixels;
        final int screenHeight = MyUtils.getScreenMetrics(this).heightPixels;
        for (int i = 0; i < 3; i++) {
            ViewGroup layout = (ViewGroup) inflater.inflate(
                    R.layout.content_layout, mListContainer, false);
            layout.getLayoutParams().width = screenWidth;
            TextView textView = (TextView) layout.findViewById(R.id.title);
            textView.setText("page " + (i + 1));
            layout.setBackgroundColor(Color.rgb(255 / (i + 1), 255 / (i + 1), 0));
            createList(layout);
            mListContainer.addView(layout);
        }
    }

    private void createList(ViewGroup layout) {
        ListView listView = (ListView) layout.findViewById(R.id.list);
        ArrayList datas = new ArrayList();
        for (int i = 0; i < 50; i++) {
            datas.add("name " + i);
        }

        ArrayAdapter adapter = new ArrayAdapter(this,
                R.layout.content_list_item, R.id.name, datas);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view,
                    int position, long id) {
                Toast.makeText(DemoActivity_1.this, "click item",
                        Toast.LENGTH_SHORT).show();

            }
        });
    }
}

水平滑动的View

public class HorizontalScrollViewEx extends ViewGroup {
    private static final String TAG = "HorizontalScrollViewEx";

    private int mChildrenSize;
    private int mChildWidth;
    private int mChildIndex;

    // 分别记录上次滑动的坐标
    private int mLastX = 0;
    private int mLastY = 0;
    // 分别记录上次滑动的坐标(onInterceptTouchEvent)
    private int mLastXIntercept = 0;
    private int mLastYIntercept = 0;

    private Scroller mScroller;
    private VelocityTracker mVelocityTracker;

    public HorizontalScrollViewEx(Context context) {
        super(context);
        init();
    }

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

    public HorizontalScrollViewEx(Context context, AttributeSet attrs,
                                  int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mScroller = new Scroller(getContext());
        mVelocityTracker = VelocityTracker.obtain();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = false;
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                Log.d(TAG, "onInterceptTouchEvent: ACTION_DOWN");
                intercepted = false;
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                    intercepted = true;
                }
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                Log.d(TAG, "onInterceptTouchEvent: ACTION_MOVE");
                int deltaX = x - mLastXIntercept;
                int deltaY = y - mLastYIntercept;
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                intercepted = false;
                break;
            }
            default:
                break;
        }

        Log.d(TAG, "intercepted=" + intercepted);




 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 在Kotlin编写RecyclerView适配器(KAD 16),kotlinrecyclerview
  • 深入理解 Android 之 View 的绘制流程,androidview
  • RecyclerView在软键盘弹出时自动调整内容技巧,recyclerview技巧
  • RecyclerView的五大开源项目-解决办法
  • Android View分区域点击实现方案——1.根据坐标范围
  • 【读书笔记】【Android 开发艺术探索】第3章 View 的事件体系
  • Android View体系(六)从源码解析Activity的构成
  • RecyclerView再封装,RecyclerView封装
  • Android中View的滑动冲突——Android开发艺术探索笔记
  • Android View体系(二)实现View滑动的六种方法

相关文章

  • 2017-05-228.3.5 Paint API之—— Xfermode与PorterDuff详解(二)
  • 2017-05-26WEB服务器、应用程序服务器、HTTP服务器区别
  • 2017-05-26Intent之运输大队长,Intent之运输队长
  • 2017-05-26Android 6.0 运行时权限处理完全解析,android6.0
  • 2017-05-26极其简单的搭建eclipse的android开发环境,搭建eclipseandroid
  • 2017-05-26android开发网络连接工具类(一),android工具类
  • 2017-05-26Android基础部分再学习---activity的状态保存
  • 2017-05-26android 使用AsyncHttpClient框架上传文件以及使用HttpURLConnection下载文件
  • 2017-05-26Android Studio的SVN Performing VCS Refresh/Commit 长时间不结束,androidsvn
  • 2017-05-26项目优化之热更新,项目优化

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android中自定义视图View之---进阶篇(Canvas的使用)
    • 硅谷商城4--显示购物车商品,硅谷商城4--购物车
    • 位图索引(Bitmap Index)与数据DML LOCK场景问题解析
    • Handler造成的内存泄漏(一),handler泄漏
    • Android项目使用Dagger2进行依赖注入
    • 14条Android Studio常用的的配置
    • Android 6.0 运行时权限处理完全解析,android6.0
    • Android入门——Drawable与对应的资源xml的应用
    • linux设备驱动程序之时钟管理(4)----原来是孩儿他爹娘
    • 【读书笔记】【Android 开发艺术探索】第3章 View 的事件体系

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有