View的基本概念了解
来源:互联网 发布:java上传图片 编辑:程序博客网 时间:2024/05/22 07:58
View方面的东西,乍一眼看去,我真是满脸懵比,雾里看花般难受。
View是所有控件的基类,是一种界面层控件的抽象,代表着一个控件。连ViewGroup都是其子类。而ViewGroup可以直译为控件组,可以包含多个View。
一个View既可以表示一个控件,也可以是多个控件组成的一组控件。
一,View的基础知识
1.1 View的位置参数
一个矩形有四个点,而决定View的位置同样有四个点,分别是left,top,right,bottom。
其中left表示View的左上角距离左边的距离,top表示View的左上角距离上边的距离。
right表示View的右下角距离左边的距离,bottom表示View的右下角距离上边的距离。
当然,这些坐标相对于它的父容器而言的。
View的布局如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <asule.myview.ManualView android:background="#123456" android:layout_centerInParent="true" android:layout_width="150dp" android:layout_height="150dp" /></RelativeLayout>
下面父容器指的是RelativeLayout
那么很容易的可以获得View的宽高 int width=right-left; int height=bootom-top;而得到这个四个位置参数的值,也很简单。 通过View的getLeft,getRight,getTop,getBottom方法。
在android3.0以后,View中又提供了几个位置参数:x,y,transactionX,transactionY四个参数。
x,y表示的是当前View在父容器中左上角的位置,而transactionX和transactionY表示的是View的左上角相对于父容器的偏移量。
所以android3.0以前,左上角的位置就是(left,top),而现在有了偏移量就变为(left+transactionX,top+transactionY)。
x=left+transactionX;y=top+transactionY;
而默认情况下,transactionX和transactionY都为0。如下:
System.out.println("transactionX:" + getTranslationX());System.out.println("transactionY:" + getTranslationY());System.out: transactionX:0.0System.out: transactionY:0.0
1.2 MotionEvent和TouchSlop
MotionEvent处理一些手指在屏幕上产生的事件,如
MotionEvent.ACTION_DOWN,手指按下。
MotionEvent.ACTION_MOVE,手指在屏幕上滑动。
MotionEvent.ACTION_UP,手指松开。
MotionEvent可以监听我们手指产生事件的同时,还可以得到点击事件位置的x和y的坐标。
int x= (int) event.getX();int y= (int) event.getY();int rawX=(int)event.getRawX();int rawY= (int) event.getRawY();getx/getY和getRawX/getRawY有很大的不同。getx/getY得到的是点击事件的位置相对于这个View左上角的x,y坐标。getRawX/getRawY得到的是点击事件的位置相对于手机屏幕左上角的x,y坐标。手机屏幕的x,y为(0,0)
TouchSlop是系统能够识别的可以被滑动的最小距离,如果你滑动的记录小于这个值,那么将不会进行滑动。会认为你滑动距离太短。
它的作用就是,在处理滑动的时候,可以进行对滑动距离的过滤。
得到系统认为的最小滑动距离:int mTouchSlop=ViewConfiguration.get(getContext()).getScaledTouchSlop();
1.3 VelocityTracker,GestureDetector,Scroller
VelocityTracker的例子:
public boolean onTouchEvent(MotionEvent event) { if (velocityTracker==null){ //创建VelocityTracker对象 velocityTracker = VelocityTracker.obtain(); } //在onTouchEvent方法中追踪当前MotionEvent事件的速度 velocityTracker.addMovement(event); //units的单位是毫秒,表示在多少毫秒内来计算的速度。假如你在50毫秒内完成了滑动,那么将计算不出来速度。 velocityTracker.computeCurrentVelocity(100); /* computeCurrentVelocity另一个重载方法computeCurrentVelocity(int units, float maxVelocity) maxVelocity表示最大速率,如果速度大于了maxVelocity,显示的速度为maxVelocity。如果小于的话,那么就显示正常的速度。 velocityTracker.computeCurrentVelocity(1000, (float)20); */ xVelocity = (int) velocityTracker.getXVelocity(); yVelocity = (int) velocityTracker.getYVelocity(); /* ACTION_DOWN和ACTION_UP的事件速度一般都为0,真正需要考虑的是ACTION_MOVE时的速度。 怎么计算速度? 速度=(终点位置-起点位置)/规定的毫秒值 本例中规定的毫秒值的是100毫秒。 从左往右滑动, 滑动的方向和x的正方向相同,那么x方向上的速度就为正值 如果向下倾斜,与y的正方向相同,那么y方向的速度为正值。 (android中的正方向是水平向右和垂直向下。) */ switch (event.getAction()){ case MotionEvent.ACTION_DOWN: System.out.println("ACTION_DOWN"); System.out.println("xVelocity:" + xVelocity); System.out.println("yVelocity:" + yVelocity); break; case MotionEvent.ACTION_MOVE: System.out.println("ACTION_MOVE"); System.out.println("xVelocity:" + xVelocity); System.out.println("yVelocity:" + yVelocity); break; case MotionEvent.ACTION_UP: System.out.println("ACTION_UP"); System.out.println("xVelocity:" + xVelocity); System.out.println("yVelocity:" + yVelocity); break; } return true; }
//当不需要使用VelocityTracker时重置并回收内存velocityTracker.clear();velocityTracker.recycle();
GestureDetector:
private MyGestureDetectorListener listener; private GestureDetector detector; private void init() { //创建GestureDetector对象并实现OnGestureListener接口 listener = new MyGestureDetectorListener(); detector = new GestureDetector(listener); } /* 轻轻触碰屏幕并抬起 onDown---->onSingleTapUp 长按屏幕后抬起 onDown---->onShowPress---->onLongPress 手指在屏幕上滑动,最后松开 onDown---->onScroll(很多次调用)---->onFling */ class MyGestureDetectorListener implements GestureDetector.OnGestureListener{ //手指轻轻触碰屏幕触发一瞬间调用 @Override public boolean onDown(MotionEvent e) { System.out.println("onDown"); return true; } //手指轻轻触碰屏幕,但并没有松开或拖动 @Override public void onShowPress(MotionEvent e) { System.out.println("onShowPress"); } //手指轻轻触碰屏幕,松开。表示单击行为 @Override public boolean onSingleTapUp(MotionEvent e) { System.out.println("onSingleTapUp"); return true; } //手指在按下并滑动 @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { System.out.println("onScroll"); return true; } //手指长按 @Override public void onLongPress(MotionEvent e) { System.out.println("onLongPress"); } //手指按下屏幕快速滑动后松开 @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { System.out.println("onFling"); System.out.println("velocityX"+velocityX); System.out.println("velocityY"+velocityY); return true; } } @Override public boolean onTouchEvent(MotionEvent event) { //接管View的onTouchEvent方法 return detector.onTouchEvent(event); }
Scroller:
弹性滑动对象,scroolTo和scroolBy两种方法的滑动都是瞬间完成的,没有过渡的滑动效果在。而Scroller可以完成这个过渡效果。它本身无法让View弹性滑动,它需要和View的computeScroll方法配合才能完成这个功能。如何使用Scroller?会在下面介绍scroolTo和scroolBy时通过一个侧滑的demo来使用Scroller。
二,View的滑动
2.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);}可以看出scrollBy实际上也是调用了scrollTo的方法。并且在mScrollX ,mScrollY的基础上进行了移动。scrollBy是绝对移动,它移动时会在上一个的位置上继续移动,而scrollTo却不是,它是直接移动到那个位置。那么mScrollX和mScrollY是什么?public final int getScrollX() { return mScrollX;}public final int getScrollY() { return mScrollY;}在view中可以通过getScrollX和getScrollY来获得。mScrollX的值等于View的上边缘在水平方向上的值减去View内容的上边缘在水平方向上的值。同理mScrollY的值等于View的下边缘在竖直方向上的值减去View内容的下边缘在竖直方向上的值。单位是像素。什么是View边缘,什么又是View内容的边缘?View边缘指的是View的位置,由四个顶点组成,而View内容边缘指的是View中内容的边缘。而scrollTo和scrollBy实现滑动,只能将View的内容进行移动。一个概念的了解:android的View视图是没有边界的,也就是说,我们在手机屏幕上看到的,是因为屏幕的限制,我们只能看到这么大。既然这是前提,下面举例子来看。
public class MainActivity extends AppCompatActivity { private ManualView manual;//自定义的TextView @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); manual = (ManualView) findViewById(R.id.manual); int scrollX = manual.getScrollX(); int scrollY = manual.getScrollY(); System.out.println("默认情况下"+"ScrollX:"+scrollX + " --- ScrollY:" + scrollY); findViewById(R.id.btn_scrollby).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { manual.scrollBy(-20, 0); int scrollX = manual.getScrollX(); int scrollY = manual.getScrollY(); System.out.println("scrollby移动后" + "ScrollX:" + scrollX + " --- ScrollY:" + scrollY); } }); findViewById(R.id.btn_scrollto).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { manual.scrollTo(100,0); int scrollX = manual.getScrollX(); int scrollY = manual.getScrollY(); System.out.println("scrollto移动后" + "ScrollX:" + scrollX + " --- ScrollY:" + scrollY); } }); }}
运行后:
当scrollBy(-20, 0)后,就成为了下面这个样子:
前面提到的说每一个View的视图是没有边界的,而只是因为视图的边界超过了它的父容器(可以认为是被隐藏或覆盖),所以只会显示我们眼中看到的布局视图。
这个View没有边界的视图应该是下面这样子:
当我们scrollBy(-20,0)时,内容向右移动,滚动时不是以(0,0)作为参照,是调用scrollBy以及scrollTo方法的View自己作为参照。
为什么是向右,要知道View的布局并没有移动,移动的只是View的内容。
View布局的左上减去View内容的左上,此时此刻就是-20。
按照上面所说的View边缘和View内容边缘的值的差,可以得出此时的mScrollX为-20。
有时候在想scrollTo和scrollBy移动的只是View的内容,那么有的控件没有内容,又是怎么实现这个方法的呢?
2.2 使用动画完成滑动
使用平移动画或者属性动画。动画以后再深究。
2.3 改变布局参数
通过设置控件的LayoutParams,改变Margin值来达到View的移动。貌似这种方法也想的出来啊。RelativeLayout.LayoutParams params= (RelativeLayout.LayoutParams) manual.getLayoutParams();params.leftMargin+=100;manual.setLayoutParams(params);//或manual.requestLayout();
2.4 各种滑动方法的对比
scrollTo和scrollBy方法可以很方便的实现滑动功能,但缺点是只能滑动View的内容,不可以滑动View本身。使用动画的话,要注意属性动画只能使用到Android3.0以上,如果要向下兼容,还需要使用第三方的库。改变布局参数,操作有些复杂,适用于有交互的View。
- View的基本概念了解
- 了解J2EE的基本概念
- js基本概念的了解
- ITIL的基本概念了解
- 了解lucene的基本概念
- 了解一些FMS的基本概念
- 了解云的一些基本概念
- 了解一些FMS的基本概念
- 了解一些 FMS 的基本概念
- view加载的深入了解
- java中必须了解的基本概念
- 学习java需要了解的一些基本概念
- 了解oracle体系结构必须先了解的两个基本概念
- View的工作原理(—)View相关基本概念
- 了解Android的view,viewgroup和layout
- 关于view渲染的深入了解
- 深入了解View的绘制流程
- ios深入了解控制器view的加载
- iOS swift学习之入门详解(可选类型错误处理)
- 领导理论
- 迅雷下载Android Studio最新版本(Android Studio 2.1.2.0)
- redhat 6 root无法登陆用户图形界面
- 列变位法解密
- View的基本概念了解
- Android App从服务器请求的图片到底该用多大?
- android多媒体框架学习
- Service要点总结
- 【C语言】求数组最大值最小值以及其位置
- Elasticsearch源码分析六--调用Lucene查询接口之前缀查询(Prefix)
- 树——二叉树的中序遍历(非递归)
- TexturePacker TP:DE0D5A1A
- Java基础知识(八)