zoukankan      html  css  js  c++  java
  • 开发自定义View

        View组件的作用类似于一个矩形的空白区域,View组件没有任何内容。对于Android应用的其他UI组件来说,它们都继承了View组件,然后在View组件提供的空白区域上绘制外观。

        基于Android UI组件的实现原理,开发者完全可以开发出项目定制的组件——当Android系统提供的UI组件不足以满足项目需要时,开发者可以通过继承View来派生自定义组件。

        当开发者打算派生自己的UI组件时,首先定义一个继承View基类的子类,然后重写View类的一个或多个方法,通常可以被用户重写的方法如下。

        构造器:重写构造器是定制View的最基本方式,当Java代码创建一个View实例,或根据XML布局文件加载并构建界面时将需要调用构造器。

    • onFinishInflate():这是一个回调方法,当应用从XML布局文件加载该组件并利用它来构建界面之后,该方法将会被回调。  
    • onMeasure(int,int):调用该方法来检测View组件及它所包含的所有子组件的大小。  
    • onLayout(boolean,int,int,int,int):当该组件需要分配其子组件的位置、大小时,该方法就会被回调。
    • onSizeChanged(int,int,int,int):当该组件的大小被改变时回调该方法。
    • onDraw(Canvas):当该组件将要绘制它的内容时回调该方法进行绘制。
    • onKeyDown(int,KeyEvent):当某个键按下时触发该方法。
    • onKeyUp(int,KeyEvent):当松开某个键时触发该方法。
    • onTrackballEvent(MotionEvent):当发生轨迹事件时触发该方法。
    • onTouchEvent(MotionEvent):当发生触摸屏事件时触发该方法。
    • onWindowFocusChanged(boolean):当该组件得到、失去焦点时触发该方法。
    • onAttachedToWindow():当把该组件放入某个窗口时触发该方法。
    • onDetachedFromWindow():当把该组件从某个窗口上分离时触发该方法。
    • onWindowVisibilityChanged(int):当包含该组件的窗口的可见性发生改变时触发该方法。

        当需要开发自定义View时,开发者并不需要重写上面列出的所有方法,而是可以根据业务需要重写上面的部分方法,例如下面的示例程序就只重写onDraw(Canvas)方法。

        实例:跟随手指的小球

        为了实现一个跟随手指的小球,我们考虑开发自定义的UI组件,这个UI组件将会在指定位置绘制一个小球,这个位置可以动态改变。当用户通过手指在屏幕上拖动时,程序监听到这个手机动作,并把手指动作的位置传入自定义UI组件,并通知该组件重绘即可。

       下面是自定义的代码:

      

    package org.crazyit.helloworld;
    
    import android.content.Context;
    import android.graphics.*;
    import android.util.*;
    import android.view.*;
    
    public class DrawView extends View {
      
        public float currentX=40;
        public float currentY=50;
        //定义并创建画笔
        Paint p=new Paint();
        
        public DrawView(Context context) {
            super(context);
            // TODO Auto-generated constructor stub
        }
        
        public DrawView(Context context,AttributeSet set)
        {
            super(context,set);
        }
        //重写onDraw方法
        @Override
        public void onDraw(Canvas canvas)
        {
           super.onDraw(canvas);
            //设置画笔的颜色 
            p.setColor(Color.RED);
            //绘制一个小圆(作为小球)
            canvas.drawCircle(currentX, currentY, 15, p);
        }
        
        //为该组件的触碰事件重写事件处理方法
        @Override
        public boolean onTouchEvent(MotionEvent event)
        {
            //修改currentX、currentY两个属性
            currentX=event.getX();
            currentY=event.getY();
            //通知当前组件重绘自己
            invalidate();
            //返回true表明该处理方法已经处理该事件
            return true;
        }
    }

          上面的DrawView组件继承了View基类,并重写了onDraw方法——该方法负责在该组件的指定位置绘制一个小球。除此之外,该组件还重写了onTouchEvent(MotionEvent event)方法,该方法用于处理该组件的触碰事件,当用户手指碰撞该组件时将会激发该方法。当手指在触摸屏上移动时,将会不断地触发触摸屏事件,事件监听器中负责触发事件的坐标将被传入DrawView组件,并通知该组件重绘——这样即可保证DrawView上小球跟随手指移动而移动。

          有了这个自定义组件之后,接下来可以通过Java代码把该组件添加到指定容器中,这样就可以看到该组件的运行效果。下面是该应用的Activity类。

    package org.crazyit.helloworld;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    
    
    public class CustomView extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.custom_view);
            /*
            //获取布局文件中的LinearLayout容器
            LinearLayout root=(LinearLayout)findViewById(R.id.root);
            //创建DrawView组件
            final DrawView draw=new DrawView(this);
            //设置自定义组件的最小宽度、高度
            draw.setMinimumWidth(300);
            draw.setMinimumHeight(500);
            root.addView(draw);
            */
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.custom_view, menu);
            return true;
        }
    
    }

         上面的程序中先创建了自定义组件(DrawVew)的实例,然后程序将该组件添加到LinearLayot容器中。

         该实例依然在Java代码中创建了DrawView组件的实例,并将它添加到LinearLayout容器中,实际上完全可以在XML布局文件中管理该组件,如果我们使用如下布局文件:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/root"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <org.crazyit.helloworld.DrawView
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>

        上面的布局文件已经添加了自定义组件,因此Java代码中只需要加载该界面布局文件即可,无须通过Java代码来添加该自定义组件,因此Actvity的代码可以简化为如下形式;

    package org.crazyit.helloworld;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    
    
    public class CustomView extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.custom_view);
            /*
            //获取布局文件中的LinearLayout容器
            LinearLayout root=(LinearLayout)findViewById(R.id.root);
            //创建DrawView组件
            final DrawView draw=new DrawView(this);
            //设置自定义组件的最小宽度、高度
            draw.setMinimumWidth(300);
            draw.setMinimumHeight(500);
            root.addView(draw);
            */
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.custom_view, menu);
            return true;
        }
    
    }

       

  • 相关阅读:
    第一个MIPS汇编
    选你所爱,爱你所选
    海明码(汉明码)的工作机制
    第一个x86汇编程序
    机器学习 coursera【week1-3】
    描述符应用与类的装饰器
    多态,封装,反射,类内置attr属性,os操作复习
    面向对象操作
    类属性的增删改查,类属性和实例属性
    os常用模块,json,pickle,shelve模块,正则表达式(实现运算符分离),logging模块,配置模块,路径叠加,哈希算法
  • 原文地址:https://www.cnblogs.com/wolipengbo/p/3338386.html
Copyright © 2011-2022 走看看