Android中的view的体系总结

本文详细介绍了Android中View的体系,包括View和ViewGroup的关系。重点讲解了View坐标系的获取,如getHeight()、getWidth()等,并阐述了实现View滑动的多种方法,如scrollTo/scrollBy、动画、改变LayoutParams及使用layout方法。此外,还提到了属性动画的使用,包括ObjectAnimator和AnimatorSet,以及Scroller的工作原理。最后,讨论了自定义View和ViewGroup的过程,包括重写onMeasure()和onDraw()方法。
摘要由CSDN通过智能技术生成

一、什么是View
View是所有控件的基类,下到各种Button,TextView,ImageView,上到LinearLayout,RelateLayout,甚至你自定义的控件,都是继承View这个基类,所以说,View是代表着界面层的一个抽象控件。除了View,还有一种叫ViewGroup,也就是控件组。ViewGroup本身也继承了View,View可以理解为存放很多View的组合,例如,LinearLayout本身是一个View,它也是一个ViewGroup。ViewGroup里面有子View,这个子View也是一个ViewGroup。

二、android之View坐标系,获取坐标值,改变控件的位置
view的几个方法:
view获取自身宽高:getHeight(),getWidth()
高度=bottom-top
宽度=right - getLeft()
getTop:获取到的,是view自身的顶边到其父布局顶边的距离
getLeft:获取到的,是view自身的左边到其父布局左边的距离
getRight:获取到的,是view自身的右边到其父布局左边的距离
getBottom:获取到的,是view自身的底边到其父布局顶边的距离

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

三、能够实现View滑动的方法:

  • 使用 scrollTo/scrollBy
  • 使用动画
  • 使用LayoutParams
  • 使用Layout

1.使用scrollTo/scrollBy

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();
            }
        }
    }
public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }

2.使用动画
通过动画我们能够让一个View进行平移,而平移就是一种滑动。使用动画来移动View,主要是操作View的 translationX 和 translationY 属性,既可以采用传统的View动画,也可以采用属性动画,如果采用属性动画的话,为了能够兼容 3.0以下的版本,需要采用开源动画库 nineoldandroids (http://nineoldandroids.com/)

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:zAdjustment="normal">

    <translate
        android:duration="100"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXDelta="100"
        android:toYDelta="100"></translate>

</set>

3、改变布局参数
在这里我们将介绍第三种实现View滑动的方法,那就是改变布局参数,即改变 LayoutParams。这个就比较好理解了,比如我们想把一个 Button 向右平移100px,我们只需要将这个 Button 的 LayoutParams 里的 marginLeft 参数的值增加 100px 即可,是不是很简单呢?还有一种情形,为了达到移动 Button 的目的,我们还可以在 Button 的左边放置一个空的 View,这个空 View 的默认宽度为 0,当我们需要向右滑动 Button 时,只需要重新设置空 View 的宽度即可,当空 View 的宽度增大时(假设 Button 的父容器是水平方向的 LinearLayout),Button 就会被自动挤向右边,这样也间接的实现了 View 向右平移的效果。如何重新设置一个 View 的 LayoutParams 呢? 很简单, 如下所示:

scrollTo.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) scrollTo.getLayoutParams();
                layoutParams.leftMargin +=100;
//                scrollTo.requestLayout();
                scrollTo.setLayoutParams(layoutParams);
            }
        });

4、使用layout方法
在 View 进行绘制时,会调用 onLayout() 方法来设置显示的位置。同样我们可以通过修改 View 的 left、top、right、bottom 四个属性来控制 View 的坐标。

三、属性动画
属性动画的使用的主要方式是AnimatorSet和ObjectAnimator配合使用.ObjectAnimator控制一个对象和一个属性,多个ObjectAnimator组合到AnimatorSet可以实现丰富的动画效果.
1.ObjectAnimator单独使用

ObjectAnimator mobjectAnimator=ObjectAnimator.ofFloat(view,"translationX",200);
                mobjectAnimator.setDuration(300);
                mobjectAnimator.start();

除了设置时长以外,还可以设置插值器.其可以常用的直接使用的属性动画属性值有:
translationX,translationY//平移
rotation,rotationX,rotationX//旋转
PrivotX,PrivotY//支点
alpha//透明度
x,y//View最终位置

2.监听动画过程

mobjectAnimator.addListener(new Animator.AnimatorListener() {
   
                    @Override
                    public void onAnimationStart(Animator animation) {
   
                    }
                    @Override
                    public void onAnimationEnd(Animator animation) {
   
                    }
                    @Override
                    public void onAnimationCancel(Animator animation) {
   
                    }
                    @Override
                    public void onAnimationRepeat(Animator animation) {
   
                    }
                });

三、组合动画
并且通过以下方法插入新动画:
  after(Animator anim)
  after(long delay)//延迟指定毫秒后执行
  with(Animator anim)
  before(Animator anim)

  ObjectAnimator Animator1 = ObjectAnimator.ofFloat(view, "translationX", 200);
                ObjectAnimator Animator2 = ObjectAnimator.ofFloat(view, "ScaleX", 1.0f, 2.0f);
                ObjectAnimator Animator3 = ObjectAnimator.ofFloat(view, "rotationX", 0.0f, 90.0f);
                AnimatorSet set=new AnimatorSet();
                set.setDuration(2000);
                set.play(Animator1).with(Animator2).after(Animator3);
                set.start();

四、从源码解析Scroller
1.Scroller的构造函数

/**
  * Create a Scroller with the default duration and interpolator.
  */
 public Scroller(Context context) {
   
     this(context, null);
 }

 /**
  * Create a Scroller with the specified interpolator. If the interpolator is
  * null, the default (viscous) interpolator will be used. "Flywheel" behavior will
  * be in effect for apps targeting Honeycomb or newer.
  */
 public Scroller(Context context, Interpolator interpolator) {
   
     this(context, interpolator,
             context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB);
 }

 /**
  * Create a Scroller with the specified interpolator. If the interpolator is
  * null, the default (viscous) interpolator will be used. Specify whether or
  * not to support progressive "flywheel" behavior in flinging.
  */
 public Scroller(Context context, Interpolator interpolator, boolean flywheel) {
   
     mFinished = true;
     if (interpolator == null) {
   
         mInterpolator = new ViscousFluidInterpolator();
     } else {
   
         mInterpolator = interpolator;
     }
     mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
     mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
     mFlywheel = flywheel;

     mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
 }

Scroller有三个构造函数,通常情况我们都用第一种,第二种需要传进去一个差值器Interpolator ,如果不传则采用默认的差值器(viscous)。

2.Scroller的startScroll方法

public void startScroll(int startX, int startY, int dx, int dy, int duration) {
   
      mMode = SCROLL_MODE;
      mFinished = false;
      mDuration = duration;
      mStartTime = AnimationUtils.currentAnimationTimeMillis();
      mStartX = startX;
      mStartY = startY;
      mFinalX = startX + dx;
      mFinalY = startY + dy;
      mDeltaX = dx;
      mDeltaY = dy;
      mDurationReciprocal = 1.0f / (float) mDuration;
  }

在startScroll()方法中并没有调用类似开启滑动的方法,而是保存了传进来的各种参数:startX和startY表示滑动开始的起点,dx和dy表示滑动的距离,duration则表示滑动持续的时间。所以startScroll()方法只是用来做前期准备的并不能使View进行滑动。关键是我们在startScroll()方法后调用了 invalidate()方法,这个方法会导致View的重绘,而View的重绘会调用View的draw()方法,draw()方法又会调用View的computeScroll()方法,我们重写computeScroll()方法:

@Override
public void computeScroll() {
   
      super.computeScroll();
      if(mScroller.computeScrollOffset()){
   
          ((View) getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值