• Android自定义控件


    Android自定义控件

    安卓在使用中大多数使用已有的一些控件,用法比较简单,还有一部分是比较复杂的、用户自己想的控件,这些就需要进行自定义控件,今天就来简单说一下自定义控件。

    1、绘制过程

    • 创建一个类,继承View类
    • onMeasure()方法,测量计算视图的大小
    • onLayout()方法,设置视图在屏幕中显示的位置
    • onDraw()方法,绘制视图

    以上就是自定义控件的绘制过程。

    2、主要内容解释

    • measure操作

      用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数:

         (1)onMeasure(),确定视图大小,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。

      (2)关于MeasureSpec:

         UPSPECIFIED:父容器对于子容器没有任何限制,子容器想要多大就多大.

         EXACTLY:父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.

         AT_MOST:子容器可以是声明大小内的任意大小.

    • layout操作 

           用于设置视图在屏幕中显示的位置。在view中定义为final类型,要求子类不能修改。layout()函数中有两个基本操作:

         (1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来;

         (2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的;

    • draw操作

           利用前两部得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。其内部定义了绘图的基本操作:

         (1)绘制背景;

         (2)如果要视图显示渐变框,这里会做一些前期工作;

         (3)绘制视图本身,即调用onDraw()函数。在view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的显示。

         (4)绘制子视图,即dispatchDraw()函数。在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法;

         (5)应用程序调用了setVerticalFadingEdge或者setHorizontalFadingEdge,如果需要可以开始绘制渐变框;

         (6)绘制滚动条;

    从上面可以看出自定义View需要最少覆写onMeasure()和onDraw()两个方法。

    • 自定义View的方法
    1. onFinishInflate(): 回调方法,当应用从XML加载该组件并用它构建界面之后调用的方法
    2. onMeasure():检测View组件及其子组件的大小
    3. onLayout(): 当该组件需要分配其子组件的位置、大小时
    4. onSizeChange():当该组件的大小被改变时
    5. onDraw(): 当组件将要绘制它的内容时
    6. onKeyDown: 当按下某个键盘时
    7. onKeyUp:  当松开某个键盘时
    8. onTrackballEvent: 当发生轨迹球事件时
    9. onTouchEvent: 当发生触屏事件时
    10. onWindowFocusChanged(boolean):当该组件得到、失去焦点时
    11. onAtrrachedToWindow():当把该组件放入到某个窗口时
    12. onDetachedFromWindow():当把该组件从某个窗口上分离时触发的方法
    13. onWindowVisibilityChanged(int):当包含该组件的窗口的可见性发生改变时触发的方法

     3、效果图展示

    4、代码展示

    在java代码中我加了很多注释,方便进行理解、学习。

    布局文件

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     android:id="@+id/container"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="vertical">
     6 
     7     <sample.sdk.qy.com.androiddemo.Customize
     8         android:layout_width="match_parent"
     9         android:layout_height="match_parent"
    10         android:layout_margin="20dp"
    11         />
    12 
    13 </LinearLayout>

    自定义控件类

     1 public class Customize extends View {
     2     private final static String TAG = Customize.class.getSimpleName();
     3     private Paint mPaint;
     4     private RectF oval;
     5 
     6     public Customize(Context context) {
     7         super(context);
     8         init();
     9     }
    10 
    11     public Customize(Context context, AttributeSet attrs) {
    12         super(context, attrs);
    13         init();
    14     }
    15 
    16     public Customize(Context context, AttributeSet attrs, int defStyleAttr) {
    17         super(context, attrs, defStyleAttr);
    18         init();
    19     }
    20 
    21     private void init(){
    22         mPaint = new Paint();
    23         mPaint.setAntiAlias(true);
    24         oval=new RectF();
    25     }
    26     @Override
    27     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    28         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    29         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    30         int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    31         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    32         int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    33         switch (widthMode) {
    34             case MeasureSpec.EXACTLY:
    35                 break;
    36             case MeasureSpec.AT_MOST:
    37                 break;
    38             case MeasureSpec.UNSPECIFIED:
    39                 break;
    40         }
    41     }
    42 
    43     @Override
    44     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    45         super.onLayout(changed, left, top, right, bottom);
    46 
    47     }
    48 
    49     @Override
    50     protected void onDraw(Canvas canvas) {
    51         super.onDraw(canvas);
    52         //设置演颜色
    53         mPaint.setColor(Color.GREEN);
    54         // FILL填充, STROKE描边,FILL_AND_STROKE填充和描边
    55         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    56         //获取控件的宽度和高度
    57         int with = getWidth();
    58         int height = getHeight();
    59         //设置圆的半径
    60         float radius = with / 4;
    61         //画圆,设置颜色
    62         canvas.drawCircle(with / 2, with / 2, radius, mPaint);
    63         mPaint.setColor(Color.BLUE);
    64         //用于定义的圆弧的形状和大小的界限
    65         oval.set(with / 2 - radius, with / 2 - radius, with / 2
    66                 + radius, with / 2 + radius);
    67         //根据进度画圆弧
    68         canvas.drawArc(oval, 270, 90, true, mPaint);
    69         //画出另一个圆弧
    70         mPaint.setColor(Color.YELLOW);
    71         canvas.drawArc(oval, 360, 120, true, mPaint);
    72     }
    73 }

    MainActivity类

     1 public class MainActivity extends Activity {
     2 
     3     @Override
     4     protected void onCreate(Bundle savedInstanceState) {
     5         super.onCreate(savedInstanceState);
     6         setContentView(R.layout.activity_main);
     7 
     8     }
     9 
    10 }
  • 相关阅读:
    WordPress 常用的动作钩子
    wordpress的过滤器
    实战haslayout(实战篇)!
    wordpress函数描述之一——WordPress add_theme_support() 函数
    一些闲言碎语,好记星不如烂笔头(一)
    实战haslayout(理论篇)!
    WordPress的钩子函数之一——do_action()
    IE6变态bug总结非常好!没有错误
    Javascript参考博客
    SilverLight遍历父子控件的通用方法
  • 原文地址:https://www.cnblogs.com/QY-admin/p/10021735.html
Copyright © 2020-2023  润新知