自定义控件一
来源:互联网 发布:舆情指数算法 编辑:程序博客网 时间:2024/05/22 15:52
自定义控件主要分成三种,1.完全自定义的控件;2.对当前的控件进行扩展;3.对当前的控件组合。
首先看第一种,完全自定义控件。以MyCircleImageView为例来说明自定义控件的创建方法。
先来看看MyCircleImageView 的效果,如下图所示,将一幅图片显示为圆形,并可以在边缘加上自己设定的颜色。
创建的过程大致分为以下几步:
1)创建MyCircleImageView类继承自View,并提供初始化函数
public class MyCircleImageView extends View{ public MyCircleImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public MyCircleImageView(Context context, AttributeSet attrs) { super(context, attrs); //初始化 } public MyCircleImageView(Context context) { super(context); }}
2)自定义属性
在MyCircleView当中,设置了三个自定义的属性,分别是图片资源、边缘宽度、边缘颜色。
自定义属性写在attr.xml文件当中。
<declare-styleable name="MyCircleImageView"> <attr name="imageSrc" format="reference"/> <attr name="borderWidth" format="dimension"/> <attr name="borderColor" format="color"/> </declare-styleable>
3)在XML布局文件当中引入自定义属性
引入自定义属性的时候还必须加入自定义属性的命名空间,如下图所示
xmlns:custom="http://schemas.android.com/apk/res-auto"
然后就可以在view当中加入自定义属性了
<com.example.a.circleimage.MyCircleImageView android:id="@+id/top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" custom:imageSrc="@drawable/mycatch" custom:borderColor="@color/yellow" custom:borderWidth="10dp"/>
4)在代码当中读取XML文件当中的属性,初始化View
private void initAttrs(AttributeSet attrs){ if(attrs!=null){ TypedArray array = null; try{ //读取属性 array = getContext().obtainStyledAttributes(attrs,R.styleable.MyCircleImageView); this.mDrawable = array.getDrawable(R.styleable.MyCircleImageView_imageSrc); this.mBorderWidth = array.getDimension(R.styleable.MyCircleImageView_borderWidth,0); this.mBorderColor = array.getInt(R.styleable.MyCircleImageView_borderColor, 0); this.mesureDrawable(); }catch (Exception e){ e.printStackTrace(); } } }
5)测量View的尺寸
首先看一下设置View尺寸的三种模式,如下表所示
模式类型
说明
EXACTLY
对应于match_parent或者具体的数值AT_MOST
对应于wrap_contentUNSPECIFIED
开发人员可以按照自己的意愿设置成任何大小,应用比较少复写父类的onMeasure()方法,并且只有当模式为EXACTLY时,宽高才从MeasureSpec当中取,其他模式则宽高设置成图片的宽高。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //获取宽度的模式和大小 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); //获取高度的模式和大小 int heightMode = MeasureSpec.getMode(heightMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); //设置view的宽和高 this.setMeasuredDimension(this.measureWidth(widthMode,width),this.measureHeight(heightMode,height)); } private int measureWidth(int mode ,int width){ switch (mode){ case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: break; case MeasureSpec.EXACTLY: this.mWidth = width; break; } return mWidth; } private int measureHeight(int mode , int height){ switch (mode){ case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: break; case MeasureSpec.EXACTLY: this.mHeight = height; break; } return mHeight; }
6)绘制View
复写ondraw()函数,将所得到的图片绘制成为圆形,并在外层添加颜色边缘。
@Override protected void onDraw(Canvas canvas) { if(mBitmap == null){ mBitmap = Bitmap.createScaledBitmap(drawableToBitmap(mDrawable), getMeasuredWidth(), getMeasuredHeight(), true); } BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); this.mPaint.setShader(bitmapShader); this.mPaint.setStyle(Paint.Style.FILL); float x = mBitmap.getWidth()/2.0f; float y = mBitmap.getHeight()/2.0f; float radiu = Math.min(x,y); canvas.drawCircle(x,y,radiu,mPaint); if(this.mBorderColor!=0 && this.mBorderWidth!=0){ Paint borderPaint = new Paint(); borderPaint.setColor(this.mBorderColor); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeWidth(mBorderWidth); borderPaint.setAntiAlias(true); canvas.drawCircle(x,y,radiu+1-mBorderWidth/2.0f,borderPaint); } }
完整的源码如下:
public class MyCircleImageView extends View { private Paint mPaint;//画笔 private Drawable mDrawable;//图片 private int mWidth;//宽度 private int mHeight;//高度 private Bitmap mBitmap; private int mBorderColor;//边框颜色 private float mBorderWidth;//边框宽度 public MyCircleImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public MyCircleImageView(Context context, AttributeSet attrs) { super(context, attrs); this.initAttrs(attrs); this.mPaint = new Paint(); this.mPaint.setAntiAlias(true);//抗锯齿 } public MyCircleImageView(Context context) { super(context); } private void initAttrs(AttributeSet attrs){ if(attrs!=null){ TypedArray array = null; try{ //读取属性 array = getContext().obtainStyledAttributes(attrs,R.styleable.MyCircleImageView); this.mDrawable = array.getDrawable(R.styleable.MyCircleImageView_imageSrc); this.mBorderWidth = array.getDimension(R.styleable.MyCircleImageView_borderWidth,0); this.mBorderColor = array.getInt(R.styleable.MyCircleImageView_borderColor, 0); this.mesureDrawable(); }catch (Exception e){ e.printStackTrace(); } } } //测量控件的大小 public void mesureDrawable(){ if(this.mDrawable!=null){ this.mHeight = this.mDrawable.getIntrinsicHeight(); this.mWidth = this.mDrawable.getIntrinsicWidth(); } } @Override protected void onDraw(Canvas canvas) { if(mBitmap == null){ mBitmap = Bitmap.createScaledBitmap(drawableToBitmap(mDrawable), getMeasuredWidth(), getMeasuredHeight(), true); } BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); this.mPaint.setShader(bitmapShader); this.mPaint.setStyle(Paint.Style.FILL); float x = mBitmap.getWidth()/2.0f; float y = mBitmap.getHeight()/2.0f; float radiu = Math.min(x,y); canvas.drawCircle(x,y,radiu,mPaint); if(this.mBorderColor!=0 && this.mBorderWidth!=0){ Paint borderPaint = new Paint(); borderPaint.setColor(this.mBorderColor); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeWidth(mBorderWidth); borderPaint.setAntiAlias(true); canvas.drawCircle(x,y,radiu+1-mBorderWidth/2.0f,borderPaint); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //获取宽度的模式和大小 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); //获取高度的模式和大小 int heightMode = MeasureSpec.getMode(heightMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); //设置view的宽和高 this.setMeasuredDimension(this.measureWidth(widthMode,width),this.measureHeight(heightMode,height)); } private int measureWidth(int mode ,int width){ switch (mode){ case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: break; case MeasureSpec.EXACTLY: this.mWidth = width; break; } return mWidth; } private int measureHeight(int mode , int height){ switch (mode){ case MeasureSpec.UNSPECIFIED: break; case MeasureSpec.AT_MOST: break; case MeasureSpec.EXACTLY: this.mHeight = height; break; } return mHeight; } //将drawable转换成bitmap public Bitmap drawableToBitmap(Drawable drawable) { Bitmap bitmap = Bitmap.createBitmap( drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); Canvas canvas = new Canvas(bitmap); canvas.setBitmap(bitmap); drawable.setBounds(0, 0, drawable.getIntrinsicWidth() ,drawable.getIntrinsicHeight()); drawable.draw(canvas); return bitmap; }}
0 0
- 自定义控件(一)
- 自定义控件(一)
- 自定义UIPageControl 控件(一)
- 自定义UIPageControl 控件(一)
- 自定义控件(一)
- 自定义控件一
- 自定义控件(一)
- Android自定义控件(一)
- 自定义控件(一)
- 自定义控件(一)
- 自定义控件(一)【Android】
- android自定义控件(一)
- 自定义控件一
- 自定义组合控件一
- 自定义控件(一)
- 自定义控件(一)
- 自定义控件(一)
- 自定义控件(一)
- C++外观模式
- 16-Oracle入门之数据库事务
- Android——NDK开发(一)
- linux磁盘浅析
- Codeforces Round #390 (Div. 2)-DFedor and coupons(优先队列)
- 自定义控件一
- Reactor模式详解
- oracle学习之:DG中物理备库、快照备库的相互转换
- 练习
- javaWEB总结(14):请求的转发和重定向
- tolua 学习笔记 UI监听事件
- 关于交换机trunk的疑问 : 引用别人的
- 漫反射
- 中介者模式