`
king_tt
  • 浏览: 2259914 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

android中如何使用ViewRootImpl这个类

 
阅读更多

尊重原创作者,转载请注明出处:

http://blog.csdn.net/gemmem/article/details/9967295

ViewRootImpl是一个和系统相关的类,一般程序开发可能不需要使用它,但是有时候为了实现一些高级功能,我们可以考虑使用ViewRootImpl这个类。

举一个例子:

在一般程序开发过程中,如果想得到当前View的touch事件的坐标x,y,我们一般会借助onTouch等回调函数,因为这些函数里面会带有系统传上来的MotionEvent参数,但是有些情况下,我们是无法依赖这种onTouch函数的,比如下面这种情况。


我们想实现View的拖拽功能,希望ImageView随着手指移动而移动,android给程序员提供了drag and drop框架,我们可以直接使用android的drag and drop API来实现这个功能。


框架已经帮我们实现了drag shadow的移动和事件分发,只需要我们调用startDrag即可。

而drag shadow的UI需要我们自己定义,关键函数如下:

onProvideShadowMetrics()
The system calls this method immediately after you callstartDrag(). Use it to send to the system the dimensions and touch point of the drag shadow. The method has two arguments:
dimensions
APointobject. The drag shadow width goes inxand its height goes iny.
touch_point
APointobject. The touch point is the location within the drag shadow that should be under the user's finger during the drag. Its X position goes inxand its Y position goes iny
这个函数有2个参数,都是Point类型。

第一个是用来指定drag shadow的宽和高, point.x表示宽,point.y表示高;

第二个Point参数是指定drag shadow的位置,这里解释一下API定义shadow位置的方法:point.x表示在拖到过程中shadow的左上角在水平方向上到手指触摸点的距离,point.y表示在拖动过程中shadow的左上角在竖直方向上到手指触摸点的距离。

考虑一个实际问题,我们的ImageView是有大小的,它的尺寸是不能忽略的,我们可以长按ImageView的正中心来拖拽它,也可能长按ImageView左上角、右上角或者下边缘等地方来发起拖拽行为,很明显,在这些情形下,我们的手指触摸点到ImageView的左上角距离是不一样的,但是,我们希望在拖拽的过程中drag shadow的左上角和手指触摸点保持这种距离,因为这样显得比较自然,那么在onProvideShadowMetrics里面,我们的touch_point参数就需要动态计算,而不能写死,所以,我们需要得到手指触摸点坐标和ImageView左上角坐标,ImageView的位置坐标非常容易获得(view.getLocationOnScreen),难点在于我们怎么得到手指触摸点坐标,这里ViewRootImpl就派上用场了,ViewRootImpl有 个函数getLastTouchPoint(),它可以获得手机屏幕上最近一次触摸行为的触摸点坐标,有了ImageView左上角坐标和手指触摸点坐标,我就可以计算出手指触摸点和ImageView左上角的相对位置。

那么如何获得ViewRootImpl实例,这个很关键,请看代码:

            View root = getRootView(); //getRootView是View.java中的public函数
            if (root == null)
                return;

            final ViewRootImpl viewRoot = (ViewRootImpl)root.getParent();

    

上面的代码即可获得ViewRootImpl实例。


下面是构建drag shadow UI的完整代码:

private class SwitchDragShadowBuilder extends View.DragShadowBuilder
    {

        public SwitchDragShadowBuilder(View v)
        {

            super(v);
        }

        @Override
        public void onProvideShadowMetrics (Point size, Point touch)
        {
            int width;
            int height;

            width = getView().getWidth();
            height = getView().getHeight();
            size.set(width, height);

            View root = getRootView();
            if (root == null)
                return;

            final ViewRootImpl viewRoot = (ViewRootImpl)root.getParent();

            Point lastPoint = new Point();
            viewRoot.getLastTouchPoint(lastPoint); //获得触摸点的坐标,相对于屏幕左上角
			int pos = new int[2];
	    mImage.getLocationOnScreen(pos); //获得ImageView的坐标,相对于屏幕左上角
            
            mTouchOffsetX = lastPoint.x - pos[0];
            mTouchOffsetY = lastPoint.y - pos[1] + DRAG_OFFSET; //y方向加一个DRAG_OFFSET,表示长按后,我们希望drag shadow往上跳一段距离

            touch.set(mTouchOffsetX, mTouchOffsetY); //set position between drag shadow and finger touch point
        }
        @Override
        public void onDrawShadow(Canvas canvas)
        {
            getView().draw(canvas);
        }
    }


ViewRootImpl这个类里面有很多高级的public API,大家可以自己去研究,上面的这个例子只是抛砖引玉,期待大家的更多发现。




分享到:
评论

相关推荐

    问题:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original

    在Android开发中,`android.view.ViewRootImpl$CalledFromWrongThreadException` 是一个常见的异常,它通常发生在尝试在非UI线程(主线程)中修改用户界面元素时。这个异常表明,只有创建视图的原始线程(即主线程)...

    Android5.0中hwui中RenderThread工作流程.docx

    这要从 Choreographer 这个类说起了,Choreographer 是 Android 系统中一个非常重要的组件,负责管理应用程序的绘制和动画。Choreographer 的 drawFrame 方法会调用到 ViewRootImpl 的 performTraversals 方法,而 ...

    字节跳动2018校招Android方向(第三批).pdf

    这几个类都是Android系统架构中的重要组件。Activity是Android应用程序的入口,Window是Android系统中的一种窗口对象,WindowManager是Android系统中的一种窗口管理器,View是Android系统中的视图对象,ViewRootImpl...

    android service toast 01

    在Service中使用Log类记录关键步骤,可以帮助调试和理解代码执行流程。 总之,Service和Toast在Android开发中都有其独特的应用场景。理解它们的使用方法和注意事项,对于构建高效、稳定的应用至关重要。通过...

    深入解析Android中的事件传递

    事件分发不是直接到Activity或View,而是通过ViewRootImpl这个特殊类进行。ViewRootImpl作为Activity与视图树之间的接口,它在Activity的启动和恢复过程中初始化。当InputDispatcherThread接收到事件后,会通过...

    ANDROID中设计模式的采用[汇编].pdf

    以下是针对Android中使用的一些设计模式的详细说明: 1. **职责链模式**:在Android的输入管理系统中,职责链模式用于处理输入事件。例如,ViewRootImpl类内部的几个阶段处理类(如EarlyPostImeInputStage、...

    android envent 事件派发机制 源代码

    事件进入Android应用层后,会通过`WindowManager`服务的`ViewRootImpl`类进行分发。`ViewRootImpl`是连接应用程序和系统服务的关键组件,它负责将事件从系统层面传递到应用程序的视图树。在`ViewRootImpl`中,`...

    Android View源码解读 DecorView与ViewRootImpl浅谈

    mWindow是一个抽象类Window的实例,具体实现在PhoneWindow类中。PhoneWindow的setContentView()方法执行时,会进行一系列操作,包括初始化DecorView和安装布局。 DecorView是Activity的顶级视图,它通常包含一个...

    Android屏幕获取英文单词

    - 使用`ViewRootImpl.java`中的`findViewByTouchPoint()`方法或自定义方案,根据触摸点获取最顶层的可触摸View。 3. **判断是英文单词**: - 获取到的文本可能包含多个单词,需要使用正则表达式检查每个单词是否...

    Android例子源码ClipPicture(仿微信截图相似度99%)

    在Android开发中,实现类似微信的截图功能是一项常见的需求,而“ClipPicture”项目正是一个实现了这一功能的优秀示例,其模仿微信截图的相似度高达99%。这个开源项目提供了一套完整的解决方案,帮助开发者了解并...

    免root实现截屏Android例子源码

    这个"免root实现截屏Android例子源码"就是针对这种需求提供的解决方案。 首先,我们需要理解Android系统的权限机制。在Android 6.0(API级别23)及以上版本,应用需要在运行时请求权限,包括读写存储权限(READ_...

    Android之Input子系统事件分发流程 - CSDN博客1

    总的来说,Android Input子系统的事件分发流程涉及了从硬件驱动到应用程序的多个层级,包括InputDispatcher、InputManagerService、InputChannel、ViewRootImpl以及View层次结构。理解这一流程对于优化用户交互和...

    android的倒计时功能

    Android UI操作必须在主线程(UI线程)中执行,否则会抛出`android.view.ViewRootImpl$CalledFromWrongThreadException`异常。因此,在子线程中进行倒计时计算后,我们需要使用`Handler`或`runOnUiThread`来更新UI。...

    android demo,test印_handle_message_obtainMessage,消息处理和函数名和行号的打

    `handle_message_obtainMessage`这个主题涉及到的是Android中的Handler机制,它允许开发者在不同线程之间传递消息,并在特定线程(通常是UI线程)中执行回调。下面我们将深入探讨这个知识点。 首先,`Handler`是...

    基于Android的联想Android开发工程师面试题.zip

    在Android开发领域,面试是检验一个开发者技能的重要环节。针对"基于Android的联想Android开发工程师面试题",我们可以深入探讨一些关键知识点,这些知识点对于学习Android的同学和毕业生来说至关重要。以下是一些...

    在Android上创建一个PopupWindow

    这个“在Android上创建一个PopupWindow”的主题将深入探讨如何使用PopupWindow类,以及在实际应用中的一些关键知识点。 首先,PopupWindow是android.widget 패키지中定义的一个类,它提供了弹出窗口的功能。创建一...

    android 性能优化-Systrace分析UI性能demo

    在实际优化过程中,SystraceTest这个示例项目可能包含了一些用于演示和学习的场景,开发者可以参考该项目,实践使用Systrace工具,理解其分析结果,并从中学习如何改进UI性能。 总之,Systrace是Android性能优化的...

    Android事件分发机制

    ViewRootImpl是Android视图系统的入口,它负责将事件传递给DecorView,这是每个Activity的顶级View。DecorView进一步将事件分发给Activity设置的ContentView。在这个过程中,事件的分发遵循“自顶向下”的原则,即从...

    android中的Handler(2)

    - 不要在非UI线程中更新UI,这将抛出` android.view.ViewRootImpl$CalledFromWrongThreadException`异常。 8. **源码分析**: 对于进阶学习,了解`Handler`、`Looper`和`MessageQueue`的源码有助于深入理解它们的...

Global site tag (gtag.js) - Google Analytics