Android 自定义View (二) 进阶

来源:互联网 发布:方形的风管知乎 编辑:程序博客网 时间:2024/05/09 15:23

转自:http://blog.csdn.NET/lmj623565791/article/details/24300125

继续自定义View之旅,前面已经介绍过一个自定义View的基础的例子,Android 自定义View (一),如果你还对自定义View不了解可以去看看。今天给大家带来一个稍微复杂点的例子。

自定义View显示一张图片,下面包含图片的文本介绍,类似相片介绍什么的,不过不重要,主要是学习自定义View的用法么。

还记得上一篇讲的4个步骤么:

1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
[ 3、重写onMesure ]
4、重写onDraw

直接切入正题:

1、在res/values/attr.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <attr name="titleText" format="string" />  
  5.     <attr name="titleTextSize" format="dimension" />  
  6.     <attr name="titleTextColor" format="color" />  
  7.     <attr name="image" format="reference" />  
  8.     <attr name="imageScaleType">  
  9.         <enum name="fillXY" value="0" />  
  10.         <enum name="center" value="1" />  
  11.     </attr>  
  12.   
  13.     <declare-styleable name="CustomImageView">  
  14.         <attr name="titleText" />  
  15.         <attr name="titleTextSize" />  
  16.         <attr name="titleTextColor" />  
  17.         <attr name="image" />  
  18.         <attr name="imageScaleType" />  
  19.     </declare-styleable>  
  20.   
  21. </resources>  


2、在构造中获得我们的自定义属性:

  1. /** 
  2.      * 初始化所特有自定义类型 
  3.      *  
  4.      * @param context 
  5.      * @param attrs 
  6.      * @param defStyle 
  7.      */  
  8.     public CustomImageView(Context context, AttributeSet attrs, int defStyle)  
  9.     {  
  10.         super(context, attrs, defStyle);  
  11.   
  12.         TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyle, 0);  
  13.   
  14.         int n = a.getIndexCount();  
  15.   
  16.         for (int i = 0; i < n; i++)  
  17.         {  
  18.             int attr = a.getIndex(i);  
  19.   
  20.             switch (attr)  
  21.             {  
  22.             case R.styleable.CustomImageView_image:  
  23.                 mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));  
  24.                 break;  
  25.             case R.styleable.CustomImageView_imageScaleType:  
  26.                 mImageScale = a.getInt(attr, 0);  
  27.                 break;  
  28.             case R.styleable.CustomImageView_titleText:  
  29.                 mTitle = a.getString(attr);  
  30.                 break;  
  31.             case R.styleable.CustomImageView_titleTextColor:  
  32.                 mTextColor = a.getColor(attr, Color.BLACK);  
  33.                 break;  
  34.             case R.styleable.CustomImageView_titleTextSize:  
  35.                 mTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,  
  36.                         16, getResources().getDisplayMetrics()));  
  37.                 break;  
  38.   
  39.             }  
  40.         }  
  41.         a.recycle();  
  42.         rect = new Rect();  
  43.         mPaint = new Paint();  
  44.         mTextBound = new Rect();  
  45.         mPaint.setTextSize(mTextSize);  
  46.         // 计算了描绘字体需要的范围  
  47.         mPaint.getTextBounds(mTitle, 0, mTitle.length(), mTextBound);  
  48.   
  49.     }  


3、重写onMeasure

  1. @Override  
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
  3. {  
  4.     // super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  5.   
  6.     /** 
  7.      * 设置宽度 
  8.      */  
  9.     int specMode = MeasureSpec.getMode(widthMeasureSpec);  
  10.     int specSize = MeasureSpec.getSize(widthMeasureSpec);  
  11.   
  12.     if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate  
  13.     {  
  14.         Log.e("xxx""EXACTLY");  
  15.         mWidth = specSize;  
  16.     } else  
  17.     {  
  18.         // 由图片决定的宽  
  19.         int desireByImg = getPaddingLeft() + getPaddingRight() + mImage.getWidth();  
  20.         // 由字体决定的宽  
  21.         int desireByTitle = getPaddingLeft() + getPaddingRight() + mTextBound.width();  
  22.   
  23.         if (specMode == MeasureSpec.AT_MOST)// wrap_content  
  24.         {  
  25.             int desire = Math.max(desireByImg, desireByTitle);  
  26.             mWidth = Math.min(desire, specSize);  
  27.             Log.e("xxx""AT_MOST");  
  28.         }  
  29.     }  
  30.   
  31.     /*** 
  32.      * 设置高度 
  33.      */  
  34.   
  35.     specMode = MeasureSpec.getMode(heightMeasureSpec);  
  36.     specSize = MeasureSpec.getSize(heightMeasureSpec);  
  37.     if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate  
  38.     {  
  39.         mHeight = specSize;  
  40.     } else  
  41.     {  
  42.         int desire = getPaddingTop() + getPaddingBottom() + mImage.getHeight() + mTextBound.height();  
  43.         if (specMode == MeasureSpec.AT_MOST)// wrap_content  
  44.         {  
  45.             mHeight = Math.min(desire, specSize);  
  46.         }  
  47.     }  
  48.     setMeasuredDimension(mWidth, mHeight);  
  49.   
  50. }  


4、重写onDraw

  1. @Override  
  2.     protected void onDraw(Canvas canvas)  
  3.     {  
  4.         // super.onDraw(canvas);  
  5.         /** 
  6.          * 边框 
  7.          */  
  8.         mPaint.setStrokeWidth(4);  
  9.         mPaint.setStyle(Paint.Style.STROKE);  
  10.         mPaint.setColor(Color.CYAN);  
  11.         canvas.drawRect(00, getMeasuredWidth(), getMeasuredHeight(), mPaint);  
  12.   
  13.         rect.left = getPaddingLeft();  
  14.         rect.right = mWidth - getPaddingRight();  
  15.         rect.top = getPaddingTop();  
  16.         rect.bottom = mHeight - getPaddingBottom();  
  17.   
  18.         mPaint.setColor(mTextColor);  
  19.         mPaint.setStyle(Style.FILL);  
  20.         /** 
  21.          * 当前设置的宽度小于字体需要的宽度,将字体改为xxx... 
  22.          */  
  23.         if (mTextBound.width() > mWidth)  
  24.         {  
  25.             TextPaint paint = new TextPaint(mPaint);  
  26.             String msg = TextUtils.ellipsize(mTitle, paint, (float) mWidth - getPaddingLeft() - getPaddingRight(),  
  27.                     TextUtils.TruncateAt.END).toString();  
  28.             canvas.drawText(msg, getPaddingLeft(), mHeight - getPaddingBottom(), mPaint);  
  29.   
  30.         } else  
  31.         {  
  32.             //正常情况,将字体居中  
  33.             canvas.drawText(mTitle, mWidth / 2 - mTextBound.width() * 1.0f / 2, mHeight - getPaddingBottom(), mPaint);  
  34.         }  
  35.   
  36.         //取消使用掉的快  
  37.         rect.bottom -= mTextBound.height();  
  38.   
  39.         if (mImageScale == IMAGE_SCALE_FITXY)  
  40.         {  
  41.             canvas.drawBitmap(mImage, null, rect, mPaint);  
  42.         } else  
  43.         {  
  44.             //计算居中的矩形范围  
  45.             rect.left = mWidth / 2 - mImage.getWidth() / 2;  
  46.             rect.right = mWidth / 2 + mImage.getWidth() / 2;  
  47.             rect.top = (mHeight - mTextBound.height()) / 2 - mImage.getHeight() / 2;  
  48.             rect.bottom = (mHeight - mTextBound.height()) / 2 + mImage.getHeight() / 2;  
  49.   
  50.             canvas.drawBitmap(mImage, null, rect, mPaint);  
  51.         }  
  52.   
  53.     }  


代码,结合注释和第一篇View的使用,应该可以看懂,不明白的留言。下面我们引入我们的自定义View:

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     xmlns:zhy="http://schemas.android.com/apk/res/com.zhy.customview02"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <com.zhy.customview02.view.CustomImageView  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_margin="10dp"  
  12.         android:padding="10dp"  
  13.         zhy:image="@drawable/ic_launcher"  
  14.         zhy:imageScaleType="center"  
  15.         zhy:titleText="hello andorid ! "  
  16.         zhy:titleTextColor="#ff0000"  
  17.         zhy:titleTextSize="30sp" />  
  18.   
  19.     <com.zhy.customview02.view.CustomImageView  
  20.         android:layout_width="100dp"  
  21.         android:layout_height="wrap_content"  
  22.         android:layout_margin="10dp"  
  23.         android:padding="10dp"  
  24.         zhy:image="@drawable/ic_launcher"  
  25.         zhy:imageScaleType="center"  
  26.         zhy:titleText="helloworldwelcome"  
  27.         zhy:titleTextColor="#00ff00"  
  28.         zhy:titleTextSize="20sp" />  
  29.   
  30.     <com.zhy.customview02.view.CustomImageView  
  31.         android:layout_width="wrap_content"  
  32.         android:layout_height="wrap_content"  
  33.         android:layout_margin="10dp"  
  34.         android:padding="10dp"  
  35.         zhy:image="@drawable/lmj"  
  36.         zhy:imageScaleType="center"  
  37.         zhy:titleText="妹子~"  
  38.         zhy:titleTextColor="#ff0000"  
  39.         zhy:titleTextSize="12sp" />  
  40.   
  41. </LinearLayout>  


我特意让显示出现3中情况:

1、字体的宽度大于图片,且View宽度设置为wrap_content

2、View宽度设置为精确值,字体的长度大于此宽度

3、图片的宽度大于字体,且View宽度设置为wrap_content

看看显示效果:


怎么样,对于这三种情况所展示的效果都还不错吧。


好了,就到这里,各位看官,没事留个言,顶一个呗~

源码下载
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 荣耀7c手机卡顿怎么办 华为6x手机卡顿怎么办 荣耀7c手机老卡怎么办 苹果6打王者卡怎么办 电脑玩游戏显示显卡不行怎么办 笔记本玩游戏显卡不行怎么办 笔记本玩英雄联盟有点卡怎么办 英语考试作文抄了阅读理解怎么办 qq账号被盗怎么办很久了 想玩线上德州没有渠道怎么办 手机玩久了头晕怎么办 玩3d游戏头晕恶心怎么办 win10打cf没声音怎么办 英雄联盟玩家尚未准备就绪怎么办 玩手机想吐应该怎么办 玩手机多了头晕怎么办 玩cf老是无响应怎么办 玩穿越火线好卡怎么办 绝地求生画质卡顿怎么办 手机热点玩lol卡怎么办 一加6直播触手黑屏怎么办 ipad应用商店密码忘记了怎么办 爱派忘记了密码怎么办 爱派id密码忘了怎么办 爱派密码忘了怎么办 爱派的密码忘了怎么办 苹果爱派密码忘了怎么办 鼠标无法识别的usb设备怎么办 电脑鼠标无法识别usb设备怎么办 win7电脑用户密码忘了怎么办 联想win7旗舰版开不了机怎么办 驱动都被卸载了怎么办 电脑密码忘了怎么办w7旗舰版 笔记本电脑密码忘了怎么办w7 windows一键还原了怎么办 戴尔笔记本电脑键盘没反应怎么办 win10电脑系统盘满了怎么办 win7玩dnf卡死怎么办 cf老是卡住闪退怎么办 w7系统帐户被停用怎么办 海康硬盘录像机密码忘了怎么办