Android view相关与自定义View

一.关于view的机制的问答

   1.gesturedetector和ontouchevent的区别

       gesturedetector指的是手势检测器,根据动态手势的运动特性,提出了速率边沿检测算法来分割手势的起止过程,通过跟踪图像平面内的手势运动,得到表征手势的一系列离散轨迹点。

       ontouchevent指的是触摸事件。

       只有滑动需求的时候 就用gesturedetector,如果有双击等这种行为的时候 就用ontouchevent

   2.ScrollTo和ScrollBy,Scroller特性      

       前者是绝对滑动,后者是相对滑动。滑动的是view的内容 而不是view本身。这很重要。比如textview 调用这2个方法  滑动的就是显示出来的字的内容。一般而言 我们用scrollBy会比较  多一些。传值的话 其实 记住几个法则就可以了。 右-左 x为正 否则x为负  上-下 y为负,否则y为正。

       view的scrollTo和scrollBy 滑动效果太差了,是瞬间完成。而scroller可以配合view的computeScroll 来完成 渐变的滑动效果。

  3.view的事件传递机制 如何用伪代码来表示?

     

 1 /**
 2      * 对于一个root viewgroup来说,如果接受了一个点击事件,那么首先会调用他的dispatchTouchEvent方法。
 3      * 如果这个viewgroup的onInterceptTouchEvent 返回true,那就代表要拦截这个事件。接下来这个事件就
 4      * 给viewgroup自己处理了,从而viewgroup的onTouchEvent方法就会被调用。如果如果这个viewgroup的onInterceptTouchEvent
 5      * 返回false就代表我不拦截这个事件,然后就把这个事件传递给自己的子元素,然后子元素的dispatchTouchEvent
 6      * 就会被调用,就是这样一个循环直到 事件被处理。
 7      *
 8      */
 9 public boolean dispatchTouchEvent(MotionEvent ev)
10 {
11     boolean consume=false;
12     if (onInterceptTouchEvent(ev)) {
13         consume=onTouchEvent(ev);
14     }else
15     {
16         consume=child.dispatchTouchEvent(ev);
17     }
18     return consume;
19 }

   4.滑动冲突问题如何解决 思路是什么?

     要解决滑动冲突 其实最主要的就是有一个核心思想。你到底想在一个事件序列中,让哪个view 来响应你的滑动?比如 从上到下滑,是哪个view来处理这个事件,从左到右呢?用业务需求 来想明白以后 剩下的 其实就很好做了。核心的方法 就是2个 外部拦截也就是父亲拦截,另外就是内部拦截,也就是子view拦截法。 学会这2种 基本上所有的滑动冲突都是这2种的变种,而且核心代码思想都一样。外部拦截法:思路就是重写父容器的onInterceptTouchEvent即可。子元素一般不需要管。可以很容易理解,因为这和android自身的事件处理机制 逻辑是一模一样的。内部拦截法:内部拦截法稍微复杂一点,就是事件到来的时候,父容器不管,让子元素自己来决定是否处理。如果消耗了 就最好,没消耗 自然就转给父容器处理了。

二.自定义View

1、自定义View的属性,首先在res/values/  下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。

 1     <?xml version="1.0" encoding="utf-8"?>  
 2     <resources>  
 3       
 4         <attr name="titleText" format="string" />  
 5         <attr name="titleTextColor" format="color" />  
 6         <attr name="titleTextSize" format="dimension" />  
 7       
 8         <declare-styleable name="CustomTitleView">  
 9             <attr name="titleText" />  
10             <attr name="titleTextColor" />  
11             <attr name="titleTextSize" />  
12         </declare-styleable>  
13       
14     </resources>  

2.然后在布局中声明我们的自定义View

 1 RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
 2     xmlns:tools="http://schemas.android.com/tools"  
 3     xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"  
 4     android:layout_width="match_parent"  
 5     android:layout_height="match_parent" >  
 6   
 7     <com.example.customview01.view.CustomTitleView  
 8         android:layout_width="200dp"  
 9         android:layout_height="100dp"  
10         custom:titleText="3712"  
11         custom:titleTextColor="#ff0000"  
12         custom:titleTextSize="40sp" />  
13   
14 </RelativeLayout>  

3.在View的构造方法中,获得我们的自定义的样式

 1     /** 
 2          * 文本 
 3          */  
 4         private String mTitleText;  
 5         /** 
 6          * 文本的颜色 
 7          */  
 8         private int mTitleTextColor;  
 9         /** 
10          * 文本的大小 
11          */  
12         private int mTitleTextSize;  
13       
14         /** 
15          * 绘制时控制文本绘制的范围 
16          */  
17         private Rect mBound;  
18         private Paint mPaint;  
19       
20         public CustomTitleView(Context context, AttributeSet attrs)  
21         {  
22             this(context, attrs, 0);  
23         }  
24       
25         public CustomTitleView(Context context)  
26         {  
27             this(context, null);  
28         }  
29       
30         /** 
31          * 获得我自定义的样式属性 
32          *  
33          * @param context 
34          * @param attrs 
35          * @param defStyle 
36          */  
37         public CustomTitleView(Context context, AttributeSet attrs, int defStyle)  
38         {  
39             super(context, attrs, defStyle);  
40             /** 
41              * 获得我们所定义的自定义样式属性 
42              */  
43             TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);  
44             int n = a.getIndexCount();  
45             for (int i = 0; i < n; i++)  
46             {  
47                 int attr = a.getIndex(i);  
48                 switch (attr)  
49                 {  
50                 case R.styleable.CustomTitleView_titleText:  
51                     mTitleText = a.getString(attr);  
52                     break;  
53                 case R.styleable.CustomTitleView_titleTextColor:  
54                     // 默认颜色设置为黑色  
55                     mTitleTextColor = a.getColor(attr, Color.BLACK);  
56                     break;  
57                 case R.styleable.CustomTitleView_titleTextSize:  
58                     // 默认设置为16sp,TypeValue也可以把sp转化为px  
59                     mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(  
60                             TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));  
61                     break;  
62       
63                 }  
64       
65             }  
66             a.recycle();  
67       
68             /** 
69              * 获得绘制文本的宽和高 
70              */  
71             mPaint = new Paint();  
72             mPaint.setTextSize(mTitleTextSize);  
73             // mPaint.setColor(mTitleTextColor);  
74             mBound = new Rect();  
75             mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);  
76       
77         }  

4.我们重写onDraw,onMesure调用系统提供的:

 1     @Override  
 2         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
 3         {  
 4             super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
 5         }  
 6       
 7         @Override  
 8         protected void onDraw(Canvas canvas)  
 9         {  
10             mPaint.setColor(Color.YELLOW);  
11             canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);  
12       
13             mPaint.setColor(mTitleTextColor);  
14             canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);  
15         }  

   

 

原文地址:https://www.cnblogs.com/yoyohong/p/6274343.html