真正了解view-入门篇(view的属性,滑动...)-基于-Android开发艺术探索


1.简单的了解view

  1.1什么是view

    view在我们的日常开发中可以说是我们的常客了,view也是我们android中所有控件的基类,不管是我们的button还是各种的布局控件他们共同的基类都是view。

    除了view,还有我们的viewgroup,从名字上可以看出他表示空间组,也可以说是我们的控件集合,想象一下我们的的布局就是这样一种体系,他可以包含多个view组合形成了一个viewgroup。

    viewgroup也是view的子类,也即是说view本身可以是单个的控件也可以是多个控件组合而成。

                                        

  从图中我们可也看出button是继承自textview,textview最终还是继承自view。


1.2 view的位置参数

   view的位置主要是由四个顶点决定的,对应着我们的top,left,right,和bottom,注意这里的四个方位坐标是相对于父容器来说的。这里顺便介绍其他几个位置参数的概念,x和y,表示view控件左上角的坐标,translationX,translationY表示view的偏移量,当我们为view指定滑动(动画)等效果后,我们的top,left 等四个属性是不会发生变化的,他表示的使我们的view初始时的四个位置。通过改变我们的magin可以改变我们的top,left等。同样也可以改变我们的x,y,当view发生动画平移效果的时候我们通过动画改变view的translationX,translationY而view的top,left等是不会发生改变的。

   上述的这些属性都可以同通过getXxx方法的到对应的值,不过我们要注意的是view的创建测量显示等程序和我们的activty的创建不是同步的,所以我们在activtity的生命周期中可能不能准确的得到我们view的位置参数,这里建议大家使用view.post(线程),这样的方法,在post方法中就可以获取准确的view位置参数了,可以暂时的理解为post方法会知道activity完全加载成功之后才会调用,此时view的参数位置就有对应的值了,对于其中的原理我们会在后面的博客中在进行详细的介绍。

       对比1.我们制定一个button的宽度高度为50dp在本人所使用的虚拟机上是1.5比例的显示效果,也就是说1dp =1.5px

          我们制定一个button没有任何的margin和

                         --->

    从图中我们可以看出,我们指定的宽度和高度以及top,left对应的值,

             这里我们可以得出这样的一个公式  height = bottom -top; width  = right-left;

   对比2:我们制定10dp的margin

    ------>

        可以看到此时的x,y有了相应的值,我们的top等也有了对应的值,

        这里我们暂且记住一个结论 x = left + translationX; y = top +translationY;

  我们前面说过做动画平移操作的时候,我们不会改变top,left等改变的是translation和对应x,y;至于动画我们会在今后的章节中介绍。


1.3 view中的MotionEvent和TouchSlop

       1.MotionEvent 执意为我们的动作事件,可以理解为作用在view之上的事件,包括,点击,滑动,抬起等。

        典型的事件有一下几种

            ACTION_DOWN    表示手指感刚刚接触屏幕

            ACTION_MOVE    表示手指在屏幕上移动

            ACTION_UP   表示手指松开屏幕的一瞬间

  如何监听MotionEvent呢 每一个view包括我们的activtiy都有

boolean onTouchEvent(MotionEvent event)  这样一个方法,由于我们无法直接复写sdk中button,等控件的这个
方法。我们可以采取接听事件的方法,这样也可以监听到事件的方法。

    思考如下的场景,一个button在一个线性布局上,此时发生了一个触屏的事件,到底是我们的activity接收到还是
button,还是我们的layout,这将是我们下一篇本章主要讨论的内容,目前我们暂且的可以认为。
事件是由底部一层层的
往上传递的,监听事件的方法优先于onTouchEvent方法接受到事件,有关这个问题的详细最佳答案我们会在后边中进行
讲解。

如果我们单独使用setOnTouchListener的话此处应该返回ture不然会只会监听一次的事件,也就是只会间听到down
事件。有关这里返回值的详细介绍我们后续会介绍此处了解即可。
大家可以仿照这样然后点击相应的view观察效果,注意:MotionEvent事件有很多,这里只是列举了比较基本的三个。

2.TouchSlop 可以理解为系统滑动的最小的距离。

  基于不同的设备而言,touchSlop的值也可能不同。
int scaledTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
可以获取这个常量,name这个常量有什么意义呢,当我们在做滑动的时候,
可以利用这一常量来做一些过滤。

1.4VelocityTracker,GestureDetector和Scroller

1.VelocityTracker速度追踪
作用:用于追踪view滑动过程中的速度,包括水平速度和垂直方向上的速度

他的用法非常的简单:
    VelocityTracker obtain = VelocityTracker.obtain();
    obtain.addMovement(event);
    obtain.computeCurrentVelocity(1000);
    float xVelocity = obtain.getXVelocity();
    float yVelocity = obtain.getYVelocity();
在不需要他的地方可以调用clear(),recycle()方法进行回收。

我们只需要在onTouchEvent或者OnTouch监听方法中实现上述代码即可。速度=(终点位置-起点位置)/时间段
这个VelocityTracker速度追踪 也不是什么重点内容这里就不多做分析了。、

2.GestureDetector
 手势检测用于辅助检测用户的单机,滑动,长按等。
使用步骤:
  1.初始化GestureDetector对象
GestureDetector g = new 
GestureDetector(this, new GestureDetector.OnGestureListener(...))

  2.在初始化时我们就可以传入监听,或者说初始化以后再设置 OnGestureListener()和OnDoubleTapListener

 3.向GestureDetector对象传入MotionEvent事件
        gestureDetector.onTouchEvent(event) 这里我们可以在重写TouchEvent或者说是OnTouch方法中注册

 
        方法名  描述 所属接口
       onDown 表示手指下落触摸屏幕的一瞬间此时会触发一个ACTION_DOWN事件 OnGestureListener
      onShowPress 手指轻触屏幕还没有松开,也会触发ACTION_DOWN注意这里和onDown相比更加强调是没有松开 OnGestureListener
     onSingleTapUp 手指从屏幕上离开伴随一个一个ACTION_UP事件发生 OnGestureListener
     onScroll 表示手指按下后进行拖动,由一个ACTION_DOWN和多个ACTION_MOVE组成是拖动行为 OnGestureListener
      onLongPress 用户长久的按着屏幕不放,即长按 OnGestureListener
        onFing 用户按下后快速滑动并且松开,可以理解为用户快速的滑动由一个ACTION_DOWN多个MOVE和一个UP组成 OnGestureListener
   onDoubleTap   双击,由两次单击组合而成 OnDoubleTapListener
onSingleTapConfirmed  严格的单击行为,如果此事件触发,后面不可能紧跟着一个单击行为,即这次单击不可能组合成双击也就是说他和onDoubleTap不可能共存 OnDoubleTapListener
 onDoubleTapEvent  表示发生了双击行(不多做研究) OnDoubleTapListener
读者可以设置设置相应的监听事件后,测试不同的点击效果对应的点击事件。 问题探究: 1.首先我们可以看出Gesture的中所监听和种种事件,其实也就是多种MotionEvent事件的组合,可以说我们在onTouch中也可以监听这种种的事件。那么究竟该如何选择呢,这里笔者给大家一个建议,如果涉及到滑动相关的监听事件大家可以在OnTouch() 或者OnTouchEvent方法中监听,如果是双击的事件,大家可以通过Gesture的OnDoubleTapListener()方法监听。 2.长按屏幕后无法触发拖动事件的现象。 大家可能会发现,如果长时间按住屏幕的话,我们的拖动事件可能不会发生, 针对这一问题通过以下的代码即可解决。 gestureDetector.setIsLongPressEnabled(false);//取消长按事件
3.Scroller
  这是个为了实现view弹性滑动的所用的类,
  view的弹性滑动,笔者大多是通过动画的方式来实现的,这里大家只需要了解到
  我们可以通过scroller + computeScroll方法 来实现view弹性滑动。

  有人可能会问什么是弹性滑动呢?
  说起来这个次很高大上,其实可理解起来相当的简单,在不使用动画或者是延迟的情况下,如果我们希望view发生
滑动(可以理解为平移操作)可以使用系统的scrollTo和scrollBy方法。
  但是这样的滑动过程是瞬时的,也就是说在一瞬间就完成了,所谓的弹性滑动其实就是让他在一定的时间完成,
这样view的滑动效果才会体现的淋漓尽致,
   回头想想看我们的动画其实就是一种弹性滑动,所以这里我们对scroller就不做详细的介绍了,有兴趣的小伙伴
可以自己查阅相关资料。



2.view的滑动。


    在andorid设备上空间的滑动可以说是十分的普遍了,大部分的效果都可以通过动画来实现,属性动画似乎无所
不能,这也不意味着我们不需要了解其他的滑动方式。

1.使用ScrollTo/ScrollBy


  为了实现view的滑动view专门为我提了这两个方法,那么这两个方法有什么区别呢,我们可以通过原码来分析
   public void scrollTo(int x, int y) {
        if (mScrollX != x || mScrollY != y) {
            int oldX = mScrollX;
            int oldY = mScrollY;
            mScrollX = x;
            mScrollY = y;
            invalidateParentCaches();
            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
            if (!awakenScrollBars()) {
                postInvalidateOnAnimation();
            }
        }
    }
通过代码可以看出scrollTo实际上就是改变了mScrollX和mScrollY,传入的两个参数就是即将要移动的距离

 public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }
scrollBy方法实际上是调用to方法,传入的两个参数实际上是,在原来的位置上继续加上一定的距离。

可以看出无论是scrollTo 还是scrollBy方法,他们最终都是改变了控件的mScrollX和mScrollY这两个属性
那么这两个属性到底表示什么意思呢:
首先这两个属性都可以通过相应的get方法得到,他们的值的单位都是像素。
mScrollX:就是view左边缘和view内左边缘在水平方向的距离。
mScrollY:就是view的上边缘和view内容上边缘在view垂直方向上的距离。

说道这里或许大家已经云里雾里的了,在这里我用通俗的一句话来解释吧。
其实这两个值所改变的就是view中内容的位置,和view控件的位置无关。

在这里需要注意,如果由左边向右边滑动,那么mscrollx为负值,反之为正值,如果从上下向下滑动那么
mscrolly为负值,反之为正值。

这里推荐大家设置一个button为它设置背景颜色,使用这两个方法,观察button的位置和button中文字的位置
变化情况。具体的演示,这里笔者就不带大家一起演示了。


2.使用动画:


  要想完全的解析动画可能我们在写上几万字也写不完,有关动画的介绍大家可以参考鸿洋大神或者郭霖的博客,
笔者也会在今后的对动画进行整理写成博客分享给大家。

  在这里我们只做简单的介绍纸上谈一下兵。

   我们都知道andorid中动画的分类分为view动画,帧动画,和属性动画,严格上说帧动画也是view动画,
无论是view动画还是属性动画都可以使用xml文件的方式或者是代码的方式写入。相比于view动画属性动画
更加的强大,接下俩我们就以属性动画为例子,谈一谈view的滑动。

   使用动画是view滑动,也可以说是平移,无非是改变view的translationX和translationY属性

  最简单的方式使控件在x方向和y方向移动一定的距离
 
   xml文件:
  
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">
    <translate
        android:duration="100"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="100"
        android:toYDelta="100"
        />
</set>
java代码:

 ObjectAnimator.ofFloat(button,"translationX",0,100).setDuration(100).start();
//此处只是简单的移动了一个方向,大家要也可以通过set动画集合的方式同时在代码中指定多种动画。

    动画我们就简单说道这里,喜欢动画的小伙伴可以多多参考鸿洋大神和郭霖的博客


3.改变布局参数

    还有一种方式可以实现view的滑动,就是改变view的布局参数,可以设置他的margin属性,

    那么如何重新设置一个view的LayoutParams呢

   其实很简单代码如下所示

   ViewGroup.MarginLayoutParams marginLayoutParamsCompat= (ViewGroup.MarginLayoutParams) button.getLayoutParams();
        marginLayoutParamsCompat.leftMargin += 100;
        button.requestLayout();
        //button.setLayoutParams(params);
        三种方式的对比:

滑动方式 优缺点
scrollTo/scrollBy

操作十分简单,但是只适合view内容的滑动。

动画

没有根本上的缺点,编写代码相对复杂

属性动画功能强大,创意性很高,推荐使用

改变布局参数 操作简单,适用于有交互view

    外传:实现弹性滑动的方式:

      弹性滑动的共同思想:实现渐进式滑动,讲一次大的滑动分割为几次小的滑动,并且在一个时间段内完成。

      由于动画就可以实现弹性滑动这里我们只对这几种方式做一个简单的了解即可。


 方式1:scroller 这里我们之前提到过

             其实内部就是讲大滑动分割,然后不断的scrollTo

方式2:动画:

           动画其实已经满足了我们的弹性滑动思想,所以说是动画是显示弹性滑动的最佳方式。

            不过我们还可以利用动画有优点ValueAnimator结合ScrollTo 实现我们的弹性滑动。其实原理很简单,使用valueAnimator对时间进行分割,相应时间段内利用scrollTo改变视图的位置,思想还是不变的。

方式3:使用延迟策略

        这就更好理解了,使用一定的延迟来模拟弹性滑动这一效果。

         主要是通过Handler或view的postDelayed  也可以结合线程的sleep方法。


    好了第一节的内容到这里就结束了,首先感谢你的阅读。这也是笔者在csdn上的第一篇博客,笔者不是什么大牛,只是一个普普通通的学生,博客中的大多只是都是参考android开发艺术探究艺术所写,这篇文章也算是笔者的学习笔记,由于写的比较仓促,文章中难免会出现错别字,希望大家能够体谅。文章中可能有很多的不足,大家可以留言告诉笔者,有错误请指出,笔者和大家一起学习。好了,再次感谢你的阅读,谢谢。




 

发布了5 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_37328871/article/details/79334480