android 自定义控件学习之三 控件布局常用知识总结

1、View是什么

View是Android所有控件的基类,简单到TextView、Button,复杂到RelativeLayout,LinearLayout,其共同基类都是View。

所以,View可以理解为控件的抽象,也是一个控件。

除此之外,还有ViewGroup,字面意义上,它表示控件组,内部可以包含许多个控件。

ViewGroup也继承自View,这意味着,一个View的可以是单个控件,也可以是多个控件组成的一组控件,这就形成了View树。

下面这个图很好地体现了View的继承关系

2、View的相关参数

View的位置决定于它的四个顶点,对应View的四个属性:

Top:左上角纵坐标,通过getTop ()获得

Left:左上角横坐标,通过getLeft()获得

Right: 右下角横坐标,通过getRight ()获得

Bottom: 右下角纵坐标,通过getBottom ()获得

这些坐标都是相对于View的父容器所说的,是一种相对坐标。

下面这张图表示的是View中涉及位置参数的各个方法对应的具体含义。

最外层是手机屏幕,中间是一个ViewGroup嵌套一个View。

涉及到的其他方法请继续往下看。

此外,参数x,y表示View左上角的横纵坐标,

translationX和translationY表示View的左上角相对于父容器的偏移量。

他们都有相应的Get/Set方法

这几个参数也是相对于父容器的坐标

可以知道,这几个参数换算关系如下

x = left + translationX

y = top + translationY

利用这些参数,我们来自定义一个能随手指滑动而改变位置的View

实现如下效果:

初始位置:

手指滑动后,自定义View走到了图示位置:

代码如下:

自定义View

[java] view
plain
 copy

  1. public class DragView extends View{
  2. int lastX;
  3. int lastY;
  4. public DragView(Context context) {
  5. super(context);
  6. }
  7. public DragView(Context context, AttributeSet attrs) {
  8. super(context, attrs);
  9. }
  10. @Override
  11. protected void onDraw(Canvas canvas) {
  12. super.onDraw(canvas);
  13. }
  14. @Override
  15. public boolean onTouchEvent(MotionEvent event) {
  16. int x = (int) event.getX();
  17. int y = (int) event.getY();
  18. Log.e("触发onTouchEvent",x+"::::::"+y);
  19. switch (event.getAction()){
  20. case MotionEvent.ACTION_DOWN:{
  21. lastX = x;
  22. lastY = y;
  23. }
  24. break;
  25. case MotionEvent.ACTION_MOVE:{
  26. int offsetX = x - lastX;
  27. int offsetY = y - lastY;
  28. Log.e("触发ACTION_MOVE",offsetX+"::::::"+offsetY);
  29. layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
  30. Log.d("DragView",getLeft()+"______"+getTop()+"-------"+getBottom()+"-------"+getRight());
  31. }
  32. break;
  33. }
  34. return true;
  35. }
  36. }

布局:

[html] view
plain
 copy

  1. <RelativeLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:paddingBottom="@dimen/activity_vertical_margin"
  7. android:paddingLeft="@dimen/activity_horizontal_margin"
  8. android:paddingRight="@dimen/activity_horizontal_margin"
  9. android:paddingTop="@dimen/activity_vertical_margin"
  10. tools:context="com.lian.scrolltest.MainActivity">
  11. <com.lian.scrolltest.DragView
  12. android:layout_width="100dp"
  13. android:layout_height="100dp"
  14. android:background="#000000"
  15. />
  16. </RelativeLayout>

MainActivity直接显示布局即可

很好地实现了如上效果

3、MotionEvent和TouchSlop

(1)MotionEvent

我们在自定义View的时候,常常需要在onTouchEvent()中定义触摸行为

典型的触摸事件类型包括:

ACTION_DOWN:手指刚刚接触屏幕

ACTION_MOVE:手指在屏幕上移动

ACTION_UP:手指从屏幕离开

通过MotionEvent对象,我们可以得到点击事件的一系列位置参数

getX(),getY():触摸事件发生的位置相对于View的坐标

getRawX(),getRawY()返回返回相对于屏幕左上角的x 和 y 坐标

(2)TouchSlop

表示系统能辨识出的认为是滑动的最小距离。

若两次滑动小于此常量,判定为不属于滑动操作

这个常量的大小和手机有关。

通过如下方式获得:

[java] view
plain
 copy

  1. ViewConfiguration.get(getContext()).getScaledTouchSlop();

我们处理滑动事件时,可以用这个参数进行过滤。

4、VelocityTracker、GestureDetector、Scroller

(1)VelocityTracker

用于追踪滑动过程中的速度,包括水平和竖直方向的速度。

使用方法:

在View的onTouchEvent()中将Event托管给VelocityTracker,

采用相应API获取参数

[java] view
plain
 copy

  1. //获取对象
  2. VelocityTracker velocityTracker = VelocityTracker.obtain();
  3. //托管event
  4. velocityTracker.addMovement(event);
  5. //设置时间间隔,结果会表示为每1000毫秒经过多少像素,若设置为100,结果表示为没100毫秒经过多少像素
  6. velocityTracker.computeCurrentVelocity(1000);
  7. //获取X和Y方向上的速度
  8. int xVelicity = (int) velocityTracker.getXVelocity();
  9. int yVelicity = (int) velocityTracker.getYVelocity();

比如1秒内X方向滑动了100像素,那么参数设置为1000时,结果就为100,表示1000毫秒划过100像素

参数设置为100时,结果就为10(表示每100毫秒划过10像素)

不需要使用时,对其进行回收

[java] view
plain
 copy

  1. velocityTracker.clear();
  2. velocityTracker.recycle();

(2)GestureDetector

GestureDetector中将封装了一系列触摸行为,包括单击、滑动、长按,双击等。

使用:

在自定义View中实现onGestureDetector接口,在其中重写onSingleTapTop()-单击事件、onFiling()-快速滑动、omLongPress()-长按、onDoubleTap()-双击

等方法,定义自己的事件处理逻辑

还有,在onTouchEvent()中:

[java] view
plain
 copy

  1. //获取对象
  2. GestureDetector gestureDetector = new GestureDetector(this);
  3. //解决长按屏幕后无法拖动的问题
  4. gestureDetector.setIsLongpressEnabled(false);
  5. //托管event
  6. boolean consume = gestureDetector.onTouchEvent(event);
  7. return consume;

(3)Scroller

用于实现View的弹性滑动。

为了让View实现滑动,我们常常使用scrollTo和ScrollBy,但其过程是瞬间完成的,没有过度效果,用户体验并不好。

使用Scroller和View的computeScroll配合,可以实现有过渡效果的滑动

三、View的滑动

滑动是自定义View使用最多的效果之一,

有三种实现方式:

a、View的scrollTo/ScrollBy方法

b、使用动画为View施加平移效果

c、改变View的LayoutParams是的View重新布局实现滑动

1、使用scrollTo/ScrollBy

源码:

[java] view
plain
 copy

  1. /**
  2. * Set the scrolled position of your view. This will cause a call to
  3. * {@link #onScrollChanged(int, int, int, int)} and the view will be
  4. * invalidated.
  5. * @param x the x position to scroll to
  6. * @param y the y position to scroll to
  7. */
  8. public void scrollTo(int x, int y) {
  9. if (mScrollX != x || mScrollY != y) {
  10. int oldX = mScrollX;
  11. int oldY = mScrollY;
  12. mScrollX = x;
  13. mScrollY = y;
  14. invalidateParentCaches();
  15. onScrollChanged(mScrollX, mScrollY, oldX, oldY);
  16. if (!awakenScrollBars()) {
  17. postInvalidateOnAnimation();
  18. }
  19. }
  20. }
  21. /**
  22. * Move the scrolled position of your view. This will cause a call to
  23. * {@link #onScrollChanged(int, int, int, int)} and the view will be
  24. * invalidated.
  25. * @param x the amount of pixels to scroll by horizontally
  26. * @param y the amount of pixels to scroll by vertically
  27. */
  28. public void scrollBy(int x, int y) {
  29. scrollTo(mScrollX + x, mScrollY + y);
  30. }

scrollBy实际上也调用scrollTo方法,实现基于当前位置的滑动,scrollTo实现基于所传递参数的绝对滑动

mScrollX和mScrollY可以动过get方法得到。

mScrollX的值总是等于View的左边缘到View的内容左边缘水平方向的距离,

mScrollY的值总是等于View的上边缘和View的内容上边缘竖直方向的距离。

需要注意的是,scrollBy和scrollTo只能改变View的内容的位置而不能改变View在布局中的位置

在View的内容位置改变是,mScrollX和mScrollY值可正可负

2、使用动画

通过动画可以让一个View进行平移,主要是操作View的translationX和translationY属性,可以用View动画,也可以用属性动画。

以属性动画为例,

我们在上面例子的基础上添加一个按钮

点击按钮,View在1秒钟的时间内向右平移200像素

通过如下代码:

[java] view
plain
 copy

  1. Button button = (Button) findViewById(R.id.btn);
  2. button.setOnClickListener(new View.OnClickListener() {
  3. @Override
  4. public void onClick(View v) {
  5. dragView.animate().translationX(200).setDuration(1000).start();
  6. }
  7. });

3.改变布局参数

即改变LayoutParams,

比如我们让以上自定义View向右平移100像素

只要将此View的marginLeft参数值增加100px

同样以上为例,将自定义View的宽度增加100px,向右平移100px

[java] view
plain
 copy

  1. button.setOnClickListener(new View.OnClickListener() {
  2. @Override
  3. public void onClick(View v) {
  4. RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) dragView.getLayoutParams();
  5. layoutParams.width+=100;
  6. layoutParams.leftMargin+=100;
  7. dragView.requestLayout();
  8. //或者dragView.setLayoutParams(layoutParams);
  9. }
  10. });

点击按钮发现View向右滑动而且变胖了,但是瞬间滑动过去的,没有动画效果

时间: 2024-12-29 11:55:39

android 自定义控件学习之三 控件布局常用知识总结的相关文章

Android 控件布局常用属性

<!--单个控件经常用到android:id -- 为控件指定相应的IDandroid:text -- 指定控件当中显示的文字,需要注意的是,这里尽量使用strings.xml文件当中的字符串android:grivity -- 指定控件的基本位置,比如说居中,居右等位置android:textSize -- 指定控件当中字体的大小android:background -- 指定该控件所使用的背景色,RGB命名法 android:width -- 指定控件的宽度android:height --

Android自定义控件之日历控件

Android自定义控件之日历控件 2015-10-23 Android开发中文站 三月份学习android,至今也有半年有余,中间也做过两个项目,但是依然感觉自己做的应用不是很有新意,比不上应用市场上那些应用如此绚丽.所以自己仍需继续努力.学习至今,仍感觉自定义控件是一块硬骨头,还没修炼到身后的内功,下面就切入正题,以一次项目的需求,来实现一个自定义的日历控件.效果图先来一发. 我们分析下效果图,然后确定我们的需求. (1).绘制星期的自定义View,用于标识日期的礼拜. (2).绘制日期的自

Android 控件布局常用的属性

<!--单个控件经常用到android:id —— 为控件指定相应的IDandroid:text —— 指定控件当中显示的文字,需要注意的是,这里尽量使用strings.xml文件当中的字符串android:grivity —— 指定控件的基本位置,比如说居中,居右等位置android:textSize —— 指定控件当中字体的大小android:background —— 指定该控件所使用的背景色,RGB命名法 android:width —— 指定控件的宽度android:height ——

Android自定义控件——自定义组合控件

转载请注明出处http://blog.csdn.net/allen315410/article/details/39581055  前面几篇博文介绍了Android如何自定义控件,其实就是讲一下如何"从无到有"的自定义一个全新的控件,继承View或者继承ViewGroup,复写其相关方法,这种自定义控件的方式相对来说难度较大,而且并不是所有需要新控件的情况下,都要这样进行.有很多情况下,我们只要运用好Android给我提供好的控件,经过布局巧妙的结合在一起,就是一个新的控件,我称之为&

Android自定义控件1--自定义控件介绍

Android控件基本介绍 Android本身提供了很多控件比如我们常用的有文本控件TextView和EditText:按钮控件Button和ImageButton状态开关按钮ToggleButton单选复选按钮RadioButton和RadioGroup单选按钮和复选按钮CheckBox图片控件ImageView时钟控件AnalogClock和DigitalClock进度条ProgressBar和日期与时间选择控件DatePicker和TimePicker等. 文本控件TextView 和Ed

Android Studio 学习 - 基本控件的使用;Intent初学

Android Studio学习第三天. 今天主要学习 1. RadioButton.CheckBox.RatingBar.SeekBar等基础控件的使用. 结合Delphi中相类似的控件,在这些基本控件的理解和使用上暂时没碰到太多的问题.对比之下,各种监听事件与Delphi中也相差无几. 2. 使用Intent切换Activity (1)在不同的Activity之间跳转,首先要新建一个Activity. (2)创建一个新的Layout布局文件,布局文件的命名首字母用小写字母(Android S

Android需要学习的控件

1.Behavior 2.FloatingActionButton 3.CoordinatorLayout 4.Snackbar http://www.open-open.com/lib/view/open1437460246974.html

【Android 初学】3、控件布局初步

什么是控件布局 所谓的控件布局方法,就是指控制控件在Activity当中的位置.大小.颜色以及其他控件样式属性的方法. 控件的布局,在android中,有两种方法: 1.使用布局文件完成控件布局(相对简单) 2.在Java代码中完成控件布局(动态布局.更灵活.也相对复杂) 布局方法分类 1.Linear Layout(最容易掌握) 线性布局:可以纵向布局.也可以横向布局. 2.Ralative Layout(最常用使用.熟悉WEB开发的人就很熟悉) 3.ListView 4.Grid View

布局与控件(一)——布局与控件的常用概念

第1节 布局与控件的常用概念 界面设计中的控件,就是我们常常看到的按钮 滑动条 文字显示区等等,它们就像房间里的家具,是界面设计的最小单位. 布局是一个可以容纳别的布局(或者控件)的容器.它就像是一个大的房间,房间里面可以放各种家具(控件),也可以再隔离成更多的房间(放入别的布局). 不过,两者有很多共同的地方,例如定义它们的大小.边距等等. 1.1 尺寸单位 在使用布局或控件时,有时需要指定它们的尺寸.安卓系统提供了三种单位: px:以像素为单位进行设置,屏幕上每一个点,就是一个像素,例如一部