android自定义组件

 

android系统本身提供了相当丰富的组件如: ButtonTextViewEditTextListViewCheckBoxRadioButtonGallerySpinner 等

如果系统中提供的组件不能满足你的需求,你可以自己定义一个组件,如果你只是想对现有的widget做一些小的调整,你之需要继承这些子类然后重载其中的一些方法即可。

你也可以完全定义自己的组件,基本步骤如下:

1、你定义的组件类(CustomClass)继承系统的View类

2、你需提供相应的构造函数,来解析XML中的属性和参数

3、你可以定义自己的监听事件

4、重载OnDraw()和OnMeasure()方法

5、可以根据需要重载基类中的其他的以on...开头的方法


Custom View Example:

在android的源码中有一个很好的例子,我们可以参考一下,就是模拟时钟的源码:

  1. /*  
  2.  * Copyright (C) 2006 The Android Open Source Project  
  3.  *  
  4.  * Licensed under the Apache License, Version 2.0 (the "License");  
  5.  * you may not use this file except in compliance with the License.  
  6.  * You may obtain a copy of the License at  
  7.  *  
  8.  *      http://www.apache.org/licenses/LICENSE-2.0  
  9.  *  
  10.  * Unless required by applicable law or agreed to in writing, software  
  11.  * distributed under the License is distributed on an "AS IS" BASIS,  
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  13.  * See the License for the specific language governing permissions and  
  14.  * limitations under the License.  
  15.  */  
  16.   
  17. package android.widget;  
  18.   
  19. import android.content.Context;  
  20. import android.content.Intent;  
  21. import android.content.IntentFilter;  
  22. import android.content.BroadcastReceiver;  
  23. import android.content.res.Resources;  
  24. import android.content.res.TypedArray;  
  25. import android.graphics.Canvas;  
  26. import android.graphics.drawable.Drawable;  
  27. import android.os.Handler;  
  28. import android.text.format.Time;  
  29. import android.util.AttributeSet;  
  30. import android.view.View;  
  31. import android.widget.RemoteViews.RemoteView;  
  32.   
  33. import java.util.TimeZone;  
  34.   
  35. /**  
  36.  * This widget display an analogic clock with two hands for hours and  
  37.  * minutes.  
  38.  */  
  39. @RemoteView  
  40. public class AnalogClock extends View { //继承自View  
  41.     private Time mCalendar;  
  42.   
  43.     private Drawable mHourHand;  
  44.     private Drawable mMinuteHand;  
  45.     private Drawable mDial;  
  46.   
  47.     private int mDialWidth;  
  48.     private int mDialHeight;  
  49.   
  50.     private boolean mAttached;  
  51.   
  52.     private final Handler mHandler = new Handler();  
  53.     private float mMinutes;  
  54.     private float mHour;  
  55.     private boolean mChanged;  
  56.     //提供相应的构造函数  
  57.     public AnalogClock(Context context) {  
  58.         this(context, null);  
  59.     }  
  60.   
  61.     public AnalogClock(Context context, AttributeSet attrs) {  
  62.         this(context, attrs, 0);  
  63.     }  
  64.     //在这个构造函数中加载了一些资源  
  65.     public AnalogClock(Context context, AttributeSet attrs,  
  66.                        int defStyle) {  
  67.         super(context, attrs, defStyle);  
  68.         Resources r = mContext.getResources();  
  69.         TypedArray a =  
  70.                 context.obtainStyledAttributes(  
  71.                         attrs, com.android.internal.R.styleable.AnalogClock, defStyle, 0);  
  72.   
  73.         mDial = a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial);  
  74.         if (mDial == null) {  
  75.             mDial = r.getDrawable(com.android.internal.R.drawable.clock_dial);  
  76.         }  
  77.   
  78.         mHourHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);  
  79.         if (mHourHand == null) {  
  80.             mHourHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_hour);  
  81.         }  
  82.   
  83.         mMinuteHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);  
  84.         if (mMinuteHand == null) {  
  85.             mMinuteHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_minute);  
  86.         }  
  87.   
  88.         mCalendar = new Time();  
  89.   
  90.         mDialmDialWidth = mDial.getIntrinsicWidth();  
  91.         mDialmDialHeight = mDial.getIntrinsicHeight();  
  92.     }  
  93.    //重载某些方法  
  94.     @Override  
  95.     protected void onAttachedToWindow() {  
  96.         super.onAttachedToWindow();  
  97.   
  98.         if (!mAttached) {  
  99.             mAttached = true;  
  100.             IntentFilter filter = new IntentFilter();  
  101.   
  102.             filter.addAction(Intent.ACTION_TIME_TICK);  
  103.             filter.addAction(Intent.ACTION_TIME_CHANGED);  
  104.             filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);  
  105.   
  106.             getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);  
  107.         }  
  108.   
  109.         // NOTE: It's safe to do these after registering the receiver since the receiver always runs  
  110.         // in the main thread, therefore the receiver can't run before this method returns.  
  111.   
  112.         // The time zone may have changed while the receiver wasn't registered, so update the Time  
  113.         mCalendar = new Time();  
  114.   
  115.         // Make sure we update to the current time  
  116.         onTimeChanged();  
  117.     }  
  118.   
  119.     @Override  
  120.     protected void onDetachedFromWindow() {  
  121.         super.onDetachedFromWindow();  
  122.         if (mAttached) {  
  123.             getContext().unregisterReceiver(mIntentReceiver);  
  124.             mAttached = false;  
  125.         }  
  126.     }  
  127.   
  128.     @Override  
  129.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  130.   
  131.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
  132.         int widthSize =  MeasureSpec.getSize(widthMeasureSpec);  
  133.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  134.         int heightSize =  MeasureSpec.getSize(heightMeasureSpec);  
  135.   
  136.         float hScale = 1.0f;  
  137.         float vScale = 1.0f;  
  138.   
  139.         if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {  
  140.             hScale = (float) widthSize / (float) mDialWidth;  
  141.         }  
  142.   
  143.         if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {  
  144.             vScale = (float )heightSize / (float) mDialHeight;  
  145.         }  
  146.   
  147.         float scale = Math.min(hScale, vScale);  
  148.   
  149.         setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),  
  150.                 resolveSize((int) (mDialHeight * scale), heightMeasureSpec));  
  151.     }  
  152.   
  153.     @Override  
  154.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  155.         super.onSizeChanged(w, h, oldw, oldh);  
  156.         mChanged = true;  
  157.     }  
  158.   
  159.     @Override  
  160.     protected void onDraw(Canvas canvas) {  
  161.         super.onDraw(canvas);  
  162.   
  163.         boolean changed = mChanged;  
  164.         if (changed) {  
  165.             mChanged = false;  
  166.         }  
  167.   
  168.         int availableWidth = mRight - mLeft;  
  169.         int availableHeight = mBottom - mTop;  
  170.   
  171.         int x = availableWidth / 2;  
  172.         int y = availableHeight / 2;  
  173.   
  174.         final Drawable dial = mDial;  
  175.         int w = dial.getIntrinsicWidth();  
  176.         int h = dial.getIntrinsicHeight();  
  177.   
  178.         boolean scaled = false;  
  179.   
  180.         if (availableWidth < w || availableHeight < h) {  
  181.             scaled = true;  
  182.             float scale = Math.min((float) availableWidth / (float) w,  
  183.                                    (float) availableHeight / (float) h);  
  184.             canvas.save();  
  185.             canvas.scale(scale, scale, x, y);  
  186.         }  
  187.   
  188.         if (changed) {  
  189.             dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));  
  190.         }  
  191.         dial.draw(canvas);  
  192.   
  193.         canvas.save();  
  194.         canvas.rotate(mHour / 12.0f * 360.0f, x, y);  
  195.         final Drawable hourHand = mHourHand;  
  196.         if (changed) {  
  197.             w = hourHand.getIntrinsicWidth();  
  198.             h = hourHand.getIntrinsicHeight();  
  199.             hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));  
  200.         }  
  201.         hourHand.draw(canvas);  
  202.         canvas.restore();  
  203.   
  204.         canvas.save();  
  205.         canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);  
  206.   
  207.         final Drawable minuteHand = mMinuteHand;  
  208.         if (changed) {  
  209.             w = minuteHand.getIntrinsicWidth();  
  210.             h = minuteHand.getIntrinsicHeight();  
  211.             minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));  
  212.         }  
  213.         minuteHand.draw(canvas);  
  214.         canvas.restore();  
  215.   
  216.         if (scaled) {  
  217.             canvas.restore();  
  218.         }  
  219.     }  
  220.   
  221.     private void onTimeChanged() {  
  222.         mCalendar.setToNow();  
  223.   
  224.         int hour = mCalendar.hour;  
  225.         int minute = mCalendar.minute;  
  226.         int second = mCalendar.second;  
  227.   
  228.         mMinutes = minute + second / 60.0f;  
  229.         mHour = hour + mMinutes / 60.0f;  
  230.         mChanged = true;  
  231.     }  
  232.   
  233.     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {  
  234.         @Override  
  235.         public void onReceive(Context context, Intent intent) {  
  236.             if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {  
  237.                 String tz = intent.getStringExtra("time-zone");  
  238.                 mCalendar = new Time(TimeZone.getTimeZone(tz).getID());  
  239.             }  
  240.   
  241.             onTimeChanged();  
  242.               
  243.             invalidate();  
  244.         }  
  245.     };  
  246. }  

使用自定义的组件,在XML文件中像使用系统预定义的组件一样使用

  1. <com.android.example.CustomView  
  2.                 android:id="@+id/customView" android:layout_height="fill_parent"  
  3.                 android:layout_width="fill_parent" />  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值