android.view.View及android.view.ViewGroup

来源:互联网 发布:传奇霸业装备炼体数据 编辑:程序博客网 时间:2024/05/28 15:40

本文摸索了View的几个特性,measure、layout、draw及event处理,包括它们的功能、步骤及调用栈。

首先measure获得View的大小,即width和height;其次由layout获得View的位置,及left、top、right、bottom;最后由draw来绘制内容。

由event来处理触屏事件,如单击、双击、滑动等。

1、下面用一个自定义View来演示具体功能。

public class MyView extends View {private static final String TAG = MyView.class.getSimpleName();GestureDetector mGestureDetector;public MyView(Context context){this(context, null);}public MyView(final Context context, AttributeSet attrs) {super(context, attrs);Log.println(Log.DEBUG, TAG, "MyView");mGestureDetector = new GestureDetector(context, mSimpleOnGestureListener,null);}@Overrideprotected void onDraw(Canvas canvas) {Log.println(Log.DEBUG, TAG, "onDraw-"+getWidth()+"-"+getHeight());//do your drawing//ViewGroup.drawChild->View.draw->View.onDrawsuper.onDraw(canvas);canvas.drawColor(Color.RED);}@Overridepublic void draw(Canvas canvas) {Log.d(TAG, "draw");super.draw(canvas);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {//ViewGroup.onLayout->View.layout->View.onLayoutLog.println(Log.DEBUG, TAG, "onLayout-"+changed+"-"+left+"-"+top+"-"+right+"-"+bottom);}@Overridepublic void layout(int l, int t, int r, int b) {Log.d(TAG, "layout-"+l+"-"+t+"-"+r+"-"+b);super.layout(l, t, r, b);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//ViewGroup.onMeasure->View.measure->View.onMeasureint widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);Log.println(Log.DEBUG, TAG, "onMeasure-"+widthMode+"-"+heightMode+"-"+widthSize+"-"+heightSize);//在这里设置自定义视图的大小setMeasuredDimension(widthSize/2, widthSize/2+100);}@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouchEvent(MotionEvent event) {//接受并在这里处理触摸事件//MyView->MyLinearLayout->MyScrollView->MainActivityLog.println(Log.DEBUG, TAG, "onTouchEvent");//return super.onTouchEvent(event);return mGestureDetector.onTouchEvent(event);}//implements OnGestureListener, OnDoubleTapListenerprivate SimpleOnGestureListener mSimpleOnGestureListener = new GestureDetector.SimpleOnGestureListener(){public boolean onDown(MotionEvent e) {Log.d(TAG, "onDown-"+e.getX()+"-"+e.getY()+"-"+e.hashCode());//起点return true;};public boolean onDoubleTap(MotionEvent e) {Log.d(TAG, "onDoubleTap-"+e.getX()+"-"+e.getY()+"-"+e.hashCode());return true;};public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {Log.d(TAG, "onFling-"+e1.getX()+"-"+e1.getY()+"-"+e1.hashCode());return true;};public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {Log.d(TAG, "onScroll-"+e1.getX()+"-"+e1.getY()+"-"+e1.hashCode());return true;};public boolean onSingleTapConfirmed(MotionEvent e) {Log.d(TAG, "onSingleTapConfirmed-"+e.getX()+"-"+e.getY()+"-"+e.hashCode());return true;};public boolean onDoubleTapEvent(MotionEvent e) {Log.d(TAG, "onDoubleTapEvent-"+e.getX()+"-"+e.getY()+"-"+e.hashCode());return true;};public boolean onSingleTapUp(MotionEvent e) {Log.d(TAG, "onSingleTapUp-"+e.getX()+"-"+e.getY()+"-"+e.hashCode());return true;};};}

public class MyLinearLayout extends LinearLayout {private static final String TAG = MyLinearLayout.class.getSimpleName();public MyLinearLayout(Context context){this(context, null);}public MyLinearLayout(Context context, AttributeSet attrs) {super(context, attrs);Log.d(TAG, "MyLinearLayout");}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {Log.d(TAG, "onMeasure");super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {Log.d(TAG, "onLayout-"+changed+"-"+l+"-"+t+"-"+r+"-"+b);View view = getChildAt(0);Log.d(TAG, view.getWidth()+"|"+view.getHeight()+"|"+view.getMeasuredWidth()+"|"+view.getMeasuredHeight());view.layout(100, 100, view.getMeasuredWidth()+100, view.getMeasuredHeight()+100);}@Overrideprotected void onDraw(Canvas canvas) {Log.d(TAG, "onDraw");super.onDraw(canvas);}@Overridepublic void draw(Canvas canvas) {Log.d(TAG, "draw");super.draw(canvas);}@Overrideprotected boolean drawChild(Canvas canvas, View child, long drawingTime) {Log.d(TAG, "drawChild");return super.drawChild(canvas, child, drawingTime);}@Overrideprotected void dispatchDraw(Canvas canvas) {Log.d(TAG, "dispatchDraw");super.dispatchDraw(canvas);}@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.d(TAG, "onTouchEvent");//View.onTouchEventreturn super.onTouchEvent(event);}}

public class MyScrollView extends ScrollView {private static final String TAG = MyScrollView.class.getSimpleName();public MyScrollView(Context context){this(context, null);}public MyScrollView(Context context, AttributeSet attrs) {super(context, attrs);Log.d(TAG, "MyScrollView");}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {Log.d(TAG, "onMeasure");super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {Log.d(TAG, "onLayout-"+changed+"-"+l+"-"+t+"-"+r+"-"+b);super.onLayout(changed, l, t, r, b);}@Overrideprotected void onDraw(Canvas canvas) {//draw->onDraw->dispatchDraw->drawChildLog.d(TAG, "onDraw");super.onDraw(canvas);}@Overridepublic void draw(Canvas canvas) {Log.d(TAG, "draw");super.draw(canvas);}@Overrideprotected boolean drawChild(Canvas canvas, View child, long drawingTime) {Log.d(TAG, "drawChild");return super.drawChild(canvas, child, drawingTime);}@Overrideprotected void dispatchDraw(Canvas canvas) {Log.d(TAG, "dispatchDraw");super.dispatchDraw(canvas);}@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.d(TAG, "onTouchEvent");//ScrollView.onTouchEventreturn super.onTouchEvent(event);}}

public class MainActivity extends Activity {private static final String TAG = MainActivity.class.getSimpleName();@Overrideprotected void onCreate(Bundle savedInstanceState) {Log.println(Log.DEBUG, TAG, "onCreate");super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.d(TAG, "onTouchEvent");return super.onTouchEvent(event);}}

<?xml version="1.0" encoding="utf-8"?><com.qinuli.customviewtest.MyScrollView     android:layout_width="match_parent"    android:layout_height="300dp"    xmlns:android="http://schemas.android.com/apk/res/android"    android:background="#00ff00">    <com.qinuli.customviewtest.MyLinearLayout    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical"    android:background="#0000ff">    <com.qinuli.customviewtest.MyView         android:id="@+id/myView"        android:layout_width="match_parent"        android:layout_height="wrap_content"/></com.qinuli.customviewtest.MyLinearLayout></com.qinuli.customviewtest.MyScrollView>

2、分析

onTouchEvent的触发顺序为MyView->MyLinearLayout->MyScrollLayout->MainActivity

1)写一个扩展SimpleOnGestureListener的类。SimpleOnGestureListener是OnGestureListener, OnDoubleTapListener两个接口的缺省适配,GestureDetector的嵌套类。OnGestureListener, OnDoubleTapListener是GestureDetector的嵌套接口。

2)通过GestureDetector构造传参封装SimpleOnGestureListener,即new GestureDetector(Context,OnGestureListener)

3)在View.onTouchEvent方法调用实现触摸事件捕捉,即return mGestureDetector.onTouchEvent(event)

3、View自定义属性

1)在res/values/attrs.xml文件resources标签下添加子标签,format类型可以是string、integer、boolean等

<declare-styleable name="trendchart">    <attr name="showPrompt" format="boolean"/></declare-styleable>
2)在使用该属性的xml文件设置值

3)在自定义View类中取值

private void init(AttributeSet attrs){TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.trendchart);showPrompt = ta.getBoolean(R.styleable.trendchart_showPrompt, false);ta.recycle();}

4、实现视图缩放

mScaleGestureDetector = new ScaleGestureDetector(this, mScaleGestureListener);//注册

@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {//先Log.d(TAG, "dispatchTouchEvent-"+ev.getAction());return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {//后Log.d(TAG, "onTouchEvent-"+event.getAction());if(mScaleGestureDetector!=null){mScaleGestureDetector.onTouchEvent(event);}return super.onTouchEvent(event);}SimpleOnScaleGestureListener mScaleGestureListener = new SimpleOnScaleGestureListener(){@Overridepublic boolean onScale(ScaleGestureDetector detector) {Log.d(TAG, detector.getCurrentSpan()+"/"+detector.getPreviousSpan());return super.onScale(detector);}public boolean onScaleBegin(ScaleGestureDetector detector) {return super.onScaleBegin(detector);};public void onScaleEnd(ScaleGestureDetector detector) {};};

0 0
原创粉丝点击