一.关于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 }