View位置参数与滑动全解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 一. View位置参数与坐标分析View是Android中所有控件的基类,是一种界面层的控件的一种抽象,代表一个控件,常见的获取位置参数的方法有以下三种:1.View的getTop(),getLeft(), getRight(),getBottom()View的位置主要由它的四个顶点来决定,分别对应View的四个属性:top,left,right,bottom,其中top是左上角纵坐标 ,left是左上角横坐标,right是右下角横坐标,bottom是右下角纵坐标。

一. View位置参数与坐标分析

View是Android中所有控件的基类,是一种界面层的控件的一种抽象,代表一个控件,常见的获取位置参数的方法有以下三种:

1.View的getTop(),getLeft(), getRight(),getBottom()

View的位置主要由它的四个顶点来决定,分别对应View的四个属性:top,left,right,bottom,其中top是左上角纵坐标 ,left是左上角横坐标,right是右下角横坐标,bottom是右下角纵坐标。需要注意的是,这些坐标都是相对于View的父容器来说的,因此它是一种相对坐标。具体参数看下图:

这里写图片描述

在Android中,坐标系的原点在屏幕的左上角(不包括状态栏与标题栏的部分),x轴和y轴的正方向分别为向右和向下,这一点很重要。

这里写图片描述

线性布局竖直排列,从上到下依次为一个Button,一个包括TextView的线性布局,宽度,高度,边距的设置如图所示。看看在Activity中怎么获取它的位置参数:


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();

    }

    private void initView() {
        mainBtn = (Button) findViewById(R.id.main_btn);
        WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        int width = windowManager.getDefaultDisplay().getWidth();
        int height = windowManager.getDefaultDisplay().getHeight();
        Log.e("log", "屏幕宽度:" + width);
        Log.e("log", "屏幕高度:" + height);

    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        Log.e("log", "按钮的getTop():" + mainBtn.getTop());
        Log.e("log", "按钮的getBottom():" + mainBtn.getBottom());
        Log.e("log", "按钮的getLeft():" + mainBtn.getLeft());
        Log.e("log", "按钮的getRight():" + mainBtn.getRight());

        Log.e("log", "按钮的getWidth(px):" + mainBtn.getWidth());
        Log.e("log", "按钮的getHeight(px):" + mainBtn.getHeight());

        Log.e("log", "按钮的getWidth(dp):" + px2dp(getApplicationContext(), mainBtn.getWidth()));
        Log.e("log", "按钮的getHeight(dp):" + px2dp(getApplicationContext(), mainBtn.getHeight()));

        Log.e("log", "文字的getTop():" + mainTxt.getTop());
        Log.e("log", "文字的getBottom():" + mainTxt.getBottom());
        Log.e("log", "文字的getLeft():" + mainTxt.getLeft());
        Log.e("log", "文字的getRight():" + mainTxt.getRight());
    }

    //px转dp
    public static int px2dp(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

获取屏幕的高度与宽度,然后重写Activity的onWindowFocusChanged方法,获取View的位置参数。刚开始我把这些方法直接写在onCreate中,获取到的值都是0。后来才知道,width、height、top、left等属性值是在Measure与Layout过程完成之后才开始正确赋值的,而Measure与Layout都晚于onCreate方法执行,所以onCreate中根本就取不到值!

关于正确获取组件的宽高,可参考以下这篇博文:

http://blog.csdn.net/qq_23547831/article/details/51764304

我们一起看一下测试结果:

这里写图片描述

这里的单位默认都是px,从以上结果我们可以得到以下结论:

View的位置参数是相对于自身的父容器来说的,是相对坐标可以看到测试文字的坐标参数是相对于自己的父容器计算的。

View的宽高与坐标的关系:

width = right - left
height = bottom - top

最后我将得到的宽高单位从(px)转换成了(dp),可以看到大小与我们在xml中设置的一致,完美~

2.View的getLocationInWindow()

这个方法获取的是View在当前窗口的绝对坐标,看一下测试代码:

            int[] btnWindowInt = new int[2];
            mainTxt.getLocationInWindow(btnWindowInt);
            Log.e("log", "文字在当前窗口内的绝对横坐标:" + btnWindowInt[0]);
            Log.e("log", "文字在当前窗口内的绝对纵坐标:" + btnWindowInt[1]);


            int[] llWindowInt = new int[2];
            maniLinearLayout.getLocationInWindow(llWindowInt);
            Log.e("log", "线性布局在当前窗口内的绝对横坐标:" + llWindowInt[0]);
            Log.e("log", "线性布局在当前窗口内的绝对纵坐标:" + llWindowInt[1]);

测试结果:

这里写图片描述

打印结果里的线性布局就是父线性布局。可以看到,这个线性布局的绝对纵坐标包括了通知栏与状态栏的高度,我们在实际项目运用这个方法的过程中,一定记得减去这个高度。因为Android坐标系的原点在屏幕的左上角(不包括状态栏与标题栏的部分)。

3.MotionEvent的getX(),getY(),getRawX(),getRawY()

首先理解这四个参数的意义:

getX():获取点击事件相对控件左边的x轴坐标,即点击事件距离控件左边的距离
getY():获取点击事件相对控件顶边的y轴坐标,即点击事件距离控件顶边的距离
getRawX():获取点击事件相对整个屏幕左边的x轴坐标,即点击事件距离整个屏幕左边的距离
getRawY():获取点击事件相对整个屏幕顶边的y轴坐标,即点击事件距离整个屏幕顶边的距离

测试代码:

还是之前的布局,我们给测试文字添加一个触摸监听:

       mainTxt.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {

                int x = (int) event.getX();
                int y = (int) event.getY();
                int xRaw = (int) event.getRawX();
                int yRaw = (int) event.getRawY();
                switch (event.getAction()) {

                    case MotionEvent.ACTION_DOWN:
                        Log.e("log", "触摸事件相对控件坐标为:" + x + "," + y);
                        Log.e("log", "触摸事件相对屏幕坐标为:" + xRaw + "," + yRaw);

                        break;
                    case MotionEvent.ACTION_MOVE:

                        break;
                    case MotionEvent.ACTION_UP:

                        break;
                }
                return false;
            }
        });

然后点击测试文字,看一下打印的结果:

这里写图片描述

那么这种结果在可以滑动的控件中是怎样的呢,比如ListView,RecyclerView。其实对于这种滑动的ViewGroup,我们在获取ViewGroup的坐标值时并不需要考虑它到底滑动了多少(实际滑动的我们应该看作是ViewGroup中的View在滑动)。获取到的结果与这里还是一样的,具体应用案例可参考我之前一篇博客:

http://blog.csdn.net/tyk0910/article/details/51669205

二. View的最小滑动距离

TouchSlop是系统所能识别出的最小的滑动距离,如果两次滑动之间的距离小于这个常量,那么系统就不认为你是在进行滑动操作。

ViewConfiguration.get(getApplicationContext()).getScaledTouchSlop();

可通过以上方法获取到这个常量,打印出来大小是8dp。当我们处理滑动时,可以利用这个常量来做一些过滤,比如当两次滑动事件的距离小于这个值,我们就可以认为没有达到滑动距离的临界值,因此可以认为它们不是滑动的。这样做可以有更好的用户体验。

三.View滑动全解析

目前Android中实现View的滑动可以分为三种方式:

通过改变View的布局参数使得View重新布局从而实现滑动

通过scrollTo/scrollBy方法来实现View的滑动

通过动画给View施加平移效果来实现滑动

这里将一一解析这三种方式的用法与区别:

首先看一下我们测试的布局文件

这里写图片描述

然后就是Activity里的代码:

    private void init() {
        testBtn = (Button) findViewById(R.id.second_btn);
        textView = (TextView) findViewById(R.id.second_txt);
        testBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                Log.e("log", "测试文字的getTop():" + textView.getTop());
                Log.e("log", "测试文字的getBottom():" + textView.getBottom());
                Log.e("log", "测试文字的getLeft():" + textView.getLeft());
                Log.e("log", "测试文字的getRight():" + textView.getRight());
            }
        });

        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getApplicationContext(), "测试文字的点击事件", Toast.LENGTH_SHORT).show();
            }
        });
    }

点击按钮的时候,滑动测试文字textView,打印textView的位置参数,并且监听textView的点击事件。

测试文字的初始位置参数如下所示:

这里写图片描述

通过添加不同的方法来滑动测试文字,并且打印位置参数。所有方法的测试结果的示例图如下:

这里写图片描述

一起看看怎么实现的:

1.通过改变View的布局参数使得View重新布局从而实现滑动

1.使用layout(int l, int t, int r, int b)方法重新布局:

textView.layout(textView.getLeft() + 50, textView.getTop() + 50, textView.getRight() + 50, textView.getBottom() + 50);

测试文字位置参数改变:

这里写图片描述

测试文字点击事件有效

2.使用offsetTopAndBottom(int offset)与offsetLeftAndRight(int offset)方法进行偏移:

textView.offsetTopAndBottom(50);
textView.offsetLeftAndRight(50);

测试文字位置参数改变:

这里写图片描述

测试文字点击事件有效

3.使用LayoutParams方法动态修改布局参数:

      LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams();
                layoutParams.leftMargin = textView.getLeft() + 50;
                layoutParams.topMargin = textView.getTop() + 50;
                textView.setLayoutParams(layoutParams);

测试文字位置参数不变:

这里写图片描述

测试文字点击事件有效

2.通过scrollTo/scrollBy方法来实现View的滑动

4.使用scrollTo(int x, int y)方法进行移动:

关于view的scrollTo方法,我在 RecyclerView学习(三)—-高仿知乎的侧滑删除 这篇博客中有很详细的介绍,大家也可以参考启舰大神的ListView滑动删除实现之二——scrollTo、scrollBy详解

//布局文件
    <LinearLayout
        android:id="@+id/second_ll"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/second_txt"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:text="测试文字" />

    </LinearLayout>


linearLayout = (LinearLayout) findViewById(R.id.second_ll);
linearLayout.scrollTo(-50, -50);

之所以加上一个父布局,是因为scrollTo/scrollBy方法只能滑动view的内容,并不能滑动view本身。

测试文字位置参数不变:

这里写图片描述

测试文字点击事件有效

5.使用scrollBy(int x, int y)方法进行移动:

 linearLayout.scrollBy(-50, -50);

测试文字位置参数不变:

这里写图片描述

测试文字点击事件有效

3. 通过动画给View施加平移效果来实现滑动

6.使用补间动画实现view的移动:

                TranslateAnimation translateAnimation = new TranslateAnimation(0, 200, 0, 200);
                translateAnimation.setDuration(1000);
                translateAnimation.setFillAfter(true);
                textView.startAnimation(translateAnimation);

测试文字位置参数不变:

这里写图片描述

使用补间动画实现的测试文字滑动,会导致测试文字的点击事件无效,只有点击原区域,事件才会有效!!!

7.使用属性动画实现view的移动:


                AnimatorSet set = new AnimatorSet();
                set.playTogether(
                        ObjectAnimator.ofFloat(textView, "translationX", 0, 200),
                        ObjectAnimator.ofFloat(textView, "translationY", 0, 200)

                );
                set.start();

测试文字位置参数不变:

这里写图片描述

使用属性动画实现的测试文字滑动,点击事件依然有效!!!

那么综合对比这三种方式,各自的特点是什么呢:

通过改变View的布局参数使得View重新布局从而实现滑动 ,操作稍微复杂,适用于有交互的View

通过scrollTo/scrollBy方法来实现View的滑动,操作简单,适合对View内容的滑动

通过动画给View施加平移效果来实现滑动,操作简单,主要适用于没有交互的View和实现复杂的动画效果

目录
相关文章
|
5月前
|
Java
解析Java线程池:参数详解与执行流程
解析Java线程池:参数详解与执行流程
58 1
|
6月前
|
SQL 存储 NoSQL
实时计算 Flink版产品使用合集之使用ParameterTool.fromArgs(args)解析参数为null,该怎么处理
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
2月前
|
JSON API 数据格式
requests库中json参数与data参数使用方法的深入解析
选择 `data`或 `json`取决于你的具体需求,以及服务器端期望接收的数据格式。
167 2
|
24天前
|
存储 缓存 并行计算
yolov5的train.py的参数信息解析
这篇文章解析了YOLOv5的`train.py`脚本中的参数信息,详细介绍了每个参数的功能和默认值,包括权重路径、模型配置、数据源、超参数、训练轮数、批量大小、图像尺寸、训练选项、设备选择、优化器设置等,以便用户可以根据需要自定义训练过程。
23 0
|
3月前
|
前端开发
背景滑动,动感加倍:CSS动画对角线效果全解析!
背景滑动,动感加倍:CSS动画对角线效果全解析!
|
3月前
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
234 0
|
3月前
|
存储 Go UED
精通Go语言的命令行参数解析
【8月更文挑战第31天】
37 0
|
4月前
|
JSON API 数据处理
深度解析京东商品列表数据接口:功能、参数与实战技巧
京东商品列表数据接口让开发者通过HTTP请求获取京东商品详尽列表信息,包括ID、名称、价格等。接口支持参数化搜索(关键词、价格区间等),返回JSON格式数据,便于处理与分析。开发者需注册账号并创建应用以获取访问权限。应用场景涵盖市场调研、商品管理和营销策略制定等,有效提升数据驱动决策能力。
|
3月前
|
安全 数据安全/隐私保护
|
3月前
|
运维 监控 Java
【JVM 调优秘籍】实战指南:JVM 调优参数全解析,让 Java 应用程序性能飙升!
【8月更文挑战第24天】本文通过一个大型在线零售平台的例子,深入探讨了Java虚拟机(JVM)性能调优的关键技术。面对应用响应延迟的问题,文章详细介绍了几种常用的JVM参数调整策略,包括堆内存大小、年轻代配置、垃圾回收器的选择及日志记录等。通过具体实践(如设置`-Xms`, `-Xmx`, `-XX:NewRatio`, `-XX:+UseParallelGC`等),成功降低了高峰期的响应时间,提高了系统的整体性能与稳定性。案例展示了合理配置JVM参数的重要性及其对解决实际问题的有效性。
92 0

推荐镜像

更多