-
Android 自定义View (一)
2014-04-21 15:20:04很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章。先总结下自定义View的步骤: 1、自定义View的属性 2、...转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901
很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章。先总结下自定义View的步骤:
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
[ 3、重写onMesure ]
4、重写onDraw
我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的。
1、自定义View的属性,首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。
我们定义了字体,字体颜色,字体大小3个属性,format是值该属性的取值类型:<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" format="string" /> <attr name="titleTextColor" format="color" /> <attr name="titleTextSize" format="dimension" /> <declare-styleable name="CustomTitleView"> <attr name="titleText" /> <attr name="titleTextColor" /> <attr name="titleTextSize" /> </declare-styleable> </resources>
一共有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;不清楚的可以google一把。
然后在布局中声明我们的自定义View
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.customview01.view.CustomTitleView android:layout_width="200dp" android:layout_height="100dp" custom:titleText="3712" custom:titleTextColor="#ff0000" custom:titleTextSize="40sp" /> </RelativeLayout>
一定要引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"我们的命名空间,后面的包路径指的是项目的package2、在View的构造方法中,获得我们的自定义的样式
/** * 文本 */ private String mTitleText; /** * 文本的颜色 */ private int mTitleTextColor; /** * 文本的大小 */ private int mTitleTextSize; /** * 绘制时控制文本绘制的范围 */ private Rect mBound; private Paint mPaint; public CustomTitleView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomTitleView(Context context) { this(context, null); } /** * 获得我自定义的样式属性 * * @param context * @param attrs * @param defStyle */ public CustomTitleView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); /** * 获得我们所定义的自定义样式属性 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.CustomTitleView_titleText: mTitleText = a.getString(attr); break; case R.styleable.CustomTitleView_titleTextColor: // 默认颜色设置为黑色 mTitleTextColor = a.getColor(attr, Color.BLACK); break; case R.styleable.CustomTitleView_titleTextSize: // 默认设置为16sp,TypeValue也可以把sp转化为px mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } a.recycle(); /** * 获得绘制文本的宽和高 */ mPaint = new Paint(); mPaint.setTextSize(mTitleTextSize); // mPaint.setColor(mTitleTextColor); mBound = new Rect(); mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound); }
我们重写了3个构造方法,默认的布局文件调用的是两个参数的构造方法,所以记得让所有的构造调用我们的三个参数的构造,我们在三个参数的构造中获得自定义属性。3、我们重写onDraw,onMesure调用系统提供的:
此时的效果是:@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { mPaint.setColor(Color.YELLOW); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(mTitleTextColor); canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint); }
是不是觉得还不错,基本已经实现了自定义View。但是此时如果我们把布局文件的宽和高写成wrap_content,会发现效果并不是我们的预期:
系统帮我们测量的高度和宽度都是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。
所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法”:
重写之前先了解MeasureSpec的specMode,一共三种类型:
EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
UNSPECIFIED:表示子布局想要多大就多大,很少使用
下面是我们重写onMeasure代码:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width; int height ; if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds); float textWidth = mBounds.width(); int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight()); width = desired; } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { mPaint.setTextSize(mTitleTextSize); mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds); float textHeight = mBounds.height(); int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom()); height = desired; } setMeasuredDimension(width, height); }
现在我们修改下布局文件:<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.customview01.view.CustomTitleView android:layout_width="wrap_content" android:layout_height="wrap_content" custom:titleText="3712" android:padding="10dp" custom:titleTextColor="#ff0000" android:layout_centerInParent="true" custom:titleTextSize="40sp" /> </RelativeLayout>
现在的效果是:完全复合我们的预期,现在我们可以对高度、宽度进行随便的设置了,基本可以满足我们的需求。
当然了,这样下来我们这个自定义View与TextView相比岂不是没什么优势,所有我们觉得给自定义View添加一个事件:
在构造中添加:
this.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mTitleText = randomText(); postInvalidate(); } });
private String randomText() { Random random = new Random(); Set<Integer> set = new HashSet<Integer>(); while (set.size() < 4) { int randomInt = random.nextInt(10); set.add(randomInt); } StringBuffer sb = new StringBuffer(); for (Integer i : set) { sb.append("" + i); } return sb.toString(); }
下面再来运行:我们添加了一个点击事件,每次让它随机生成一个4位的随机数,有兴趣的可以在onDraw中添加一点噪点,然后改写为验证码,是不是感觉很不错。
好了,各位学习的,打酱油的留个言,顶个呗~
源码点击此处下载
-
Android自定义控件三部曲文章索引
2016-11-25 17:39:06前言:在我从C++转到Android时,就被Android里炫彩斑斓的自定义控件深深折服,想知道如果想利用C++实现这些功能,那是相当困难的。从那时候起,我就想,等我学会了自定义控件,一定要写一篇系列出来,方便后来者能更...前言:在我从C++转到Android时,就被Android里炫彩斑斓的自定义控件深深折服,想知道如果想利用C++实现这些功能,那是相当困难的。从那时候起,我就想,等我学会了自定义控件,一定要写一篇系列出来,方便后来者能更系统完善地掌握它。今天,这个系列就这样默默地诞生了,希望它能够完成它的使命,在你读完这系列博客时,发现定自义控件也不过如此!如果,顺便能给个评论,加个关注,我将不胜感激——启舰
我的新书《Android自定义控件入门与实战》出版啦:https://blog.csdn.net/harvic880925/article/details/81455073
一、自定义控件三部曲之动画篇
1、《自定义控件三部曲之动画篇(一)——alpha、scale、translate、rotate、set的xml属性及用法》
2、《自定义控件三部曲之动画篇(二)——Interpolator插值器》
3、《自定义控件三部曲之动画篇(三)—— 代码生成alpha、scale、translate、rotate、set及插值器动画》
4、《自定义控件三部曲之动画篇(四)——ValueAnimator基本使用》- 初识ValueAnimator:ofInt,ofFloat以及监听器用法
5、《自定义控件三部曲之动画篇(五)——ValueAnimator高级进阶(一)》
- 这一节非常重要,讲解了插值器与Evaluator的使用与如何自定义知识
- 这节中有如何做到背景色渐变的特效
6、《自定义控件三部曲之动画篇(六)——ValueAnimator高级进阶(二)》
- 这节着重讲解了ValueAnimator的ofObject函数用法
- 可以看到自定义弹性圆的伸缩特效
- 如何给A-Z字母变化添加上插值器效果
7、《自定义控件三部曲之动画篇(七)——ObjectAnimator基本使用》
- 这节讲了ObjectAnimator的用法及如何利用ObjectAnimator来实现前几节的效果
8、《自定义控件三部曲之动画篇(八)——PropertyValuesHolder与Keyframe》
- 这节主要讲了如何自定义关键帧的知识
- 使用关键帧实现电话振铃效果
9、《自定义控件三部曲之动画篇(九)——联合动画的代码实现》
- 这节讲解了如何实现组合动画的知识包括顺序播放、同时播放和自由定义顺序播放以及动画监听器相关的知识
10、《自定义控件三部曲之动画篇(十)——联合动画的XML实现与使用示例》
- 利用XML来实现组合动画的知识
- 实现了路径菜单动画
11、《 自定义控件三部曲之动画篇(十一)——layoutAnimation与gridLayoutAnimation》
- 讲解了容器类中控件的进入动画的实现方式
12、《自定义控件三部曲之动画篇(十二)——animateLayoutChanges与LayoutTransition》
- 自定义容器类中控件进入、退出等相关动画的实现方式
13、《自定义控件三部曲之动画篇(十三)——实现ListView Item进入动画》- 讲解了一个实例:如何实现listview中各个item进场时的动画
在动画篇中,从一到十篇是必须要掌握的,11-13篇不是必须掌握的,有个印象就行
二、自定义控件三部曲之绘图篇
1、《自定义控件三部曲之绘图篇(一):概述及基本几何图形绘制》
2、《自定义控件三部曲之绘图篇(二):路径及文字》
3、《自定义控件三部曲之绘图篇(三):区域(Range)》
4、《自定义控件三部曲之绘图篇(四):canvas变换与操作》
5、《自定义控件三部曲之绘图篇( 五):drawText()详解》
6、《 自定义控件三部曲之绘图篇(六)——Path之贝赛尔曲线和手势轨迹、水波纹效果》- 本篇将讲述手势轨迹捕捉、波浪纹效果实现的几种方法
7、《 自定义控件三部曲之绘图篇(七)——Paint之函数大汇总》
- 本篇将讲述路径的各种效果,比如铁锈路径、自定义图形路径、虚线路径等
8、《自定义控件三部曲之绘图篇(八)——Paint之ColorMatrix与滤镜效果》
- 本篇将讲述各种滤镜效果的实现方法:包括黑白滤镜、反古滤镜、色彩增强滤镜、色彩替换等
9、《自定义控件三部曲之绘图篇(九)——Paint之setColorFilter》
- 按钮点击时,动态加深图片色彩(简易方法)
- 可以学到针对不同主题动态设置不同色彩图片的方法(setTint())
10、《自定义控件三部曲之绘图篇(十)——Paint之setXfermode(一)》
- 硬件加速的原理与禁用方法
- 选区颜色替换、溶合图片、反向选区颜色替换
11、《自定义控件三部曲之绘图篇(十一)——Paint之setXfermode(二)》
- 书架中书本选中灯光效果
- Twiter标识中空效果实现
- 图片圆角实现
- 图片倒影实现
- 橡皮擦效果实现
- 刮刮卡效果实现
12、《自定义控件三部曲之绘图篇(十二)——Paint之setXfermode(三)》
- 区域波纹动画效果
- 心电图动画
- 不规则波纹
- 刷刷卡、图片倒影等另种实现方式
13、《自定义控件三部曲之绘图篇(十三)——Canvas与图层(一)》
- 这篇文章中没有任何特效,但这是绘图篇中非常重要的一篇,对于理解Canvas绘图起着重要作用
14、《自定义控件三部曲之绘图篇(十四)——Canvas与图层(二)》
- 上一篇的续篇,讲解了save、saveLayer、saveLayerAlpha中所使用的FLAG的具体意义
15、《自定义控件三部曲之绘图篇(十五)——QQ红点拖动删除效果实现(基本原理篇)》
- 对以往知识点进行总结复习,涉及有Canvas绘图、SaveLayer图层、贝赛尔曲线、手势监听和逐帧动画等
- 初步实现了QQ红点拖动效果
16、《自定义控件三部曲之绘图篇(十六)——给控件添加阴影效果与发光效果》
- 传统地给按钮添加阴影的方法
- 如何给已有控件添加阴影
- 如何给控件添加发光效果
17、《自定义控件三部曲之绘图篇(十七)——为Bitmap添加阴影并封装控件》
- 如何给图片添加阴影
- 如何自定义控件属性
- 控件如何自测量
- 如何最终封装成控件
18、《自定义控件三部曲之绘图篇(十八)——BitmapShader与望远镜效果》
- 实现望远镜效果
- 封装不规则头像控件
19、《自定义控件三部曲之绘图篇(十九)——LinearGradient与闪动文字效果》
- 讲解了LinearGradient的意义
- 实现了闪动文字效果控件
20、《自定义控件三部曲之绘图篇(二十)——RadialGradient与水波纹按钮效果》
- 讲解了RradialGradient知识
- 实现了按钮水波纹效果
三、自定义控件三部曲之视图篇
- 讲解onMeasure、onLayout的区别与用法
- 讲解margin的计算方法
2、《自定义控件三部曲视图篇(二)——FlowLayout自适应容器实现》
- 实现了自适应的派生自ViewGroup的容器FlowLayout
3、《自定义控件三部曲视图篇(三)——瀑布流容器WaterFallLayout实现》
- 讲解了自定义LayoutParams并使用的方法
- 能够了解派生自ViewGroup的控件如何定义与使用的方法
4、《自定义控件三部曲视图篇(四)——RecyclerView系列之一简单使用》
- 讲解了RecyclerView的基本使用方法,为下篇深入讲解做准备
5、《自定义控件三部曲视图篇(五)——RecyclerView系列之二ItemDecoration》
- 讲解了ItemDecoration与Item的关系
- ItemDecoration的用法
- 自定义ItemDecoration与蒙版效果
6、《自定义控件三部曲视图篇(六)——RecyclerView系列之三自定义LayoutManager》
- 讲解了自定义LayoutManager的方法
- 讲解了如何初始化Item布局,如何实现Item的滚动
7、《自定义控件三部曲视图篇(七)——RecyclerView系列之四实现回收复用》
- 讲解了RecyclerView的回收复用原理
- 讲解了为自定义LayoutManager添加回收复用的实现方法
8、《自定义控件三部曲视图篇(八)——RecyclerView系统之五回收复用实现方式二》
- 讲解了另一种实现回收复用的方法
- 实现了针对每个Item布局,同时在布局后更改每个Item的属性的方法
9、《自定义控件三部曲视图篇(九)——RecycerView系列之六实现滚动画廊控件》
- 实现2D画廊
- 实现fling校正的方法
- 实现3D画廊的方法
如果你喜欢我的文章,你可能更喜欢我的公众号
-
Android高手进阶之自定义View,自定义属性(带进度的圆形进度条)源码
2013-08-25 15:29:44自定义android进度条,带有进度指示,项目详情:http://blog.csdn.net/xiaanming/article/details/10298163 -
钉钉自定义机器人开发
2020-10-22 09:40:03关于钉钉自定义机器人的开发流程,其官网有全面的解释,就不作赘述,我仅说明一下我发信的问题。章节地址如下: https://ding-doc.dingtalk.com/document#/org-dev-guide/qf2nxq 测试机器人发送消息 其官网中...前言
关于钉钉自定义机器人的开发流程,其官网有全面的解释,就不作赘述。章节地址如下:
https://ding-doc.dingtalk.com/document#/org-dev-guide/qf2nxq
本篇博客主要目的就是补充一下前端通过AJAX()发送请求数据的方法,对curl发送消息的方式进行整理。
测试机器人发送消息
其官网中详细介绍了三种测试发送消息的方法,分别是curl 、Java程序、PHP程序。在SDK环境配置章节(SDK请求示例)中对Python程序、.NET程序发送消息的方法也有简要的说明。
上述方法都需要添加对应的依赖,添加SDK环境配置章节(SDK请求示例)地址如下:https://ding-doc.dingtalk.com/doc#/faquestions/vzbp02
其中,curl的请求方式似乎并没有用,我尝试过修改但都没有成功,希望有请求成功的大佬发表一下看法。
AJAX测试发送消息
前端通过AJAX发送钉钉消息的方式在官网中并没有提及,因此,写本篇博客补充一下。
需要说明,该方法需要浏览器是跨域的,不然会报错。完整的HTML页面代码如下。
<!DOCTYPE html> <html> <head> <title>ajax发送钉钉消息</title> <script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.3.1/jquery.min.js"></script> <script> $(function(){ console.log("=== start ==="); $.ajax({ url:'https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxx', type:"POST", beforeSend:function (xhr){ xhr.setRequestHeader('Content-Type', 'application/json'); }, data:JSON.stringify({"msgtype": "text","text": {"content": "Hello World! ---大话家"}}), success:function (res){ console.log("=== success ==="); console.log(res); }, error:function (err){ console.log("=== error ==="); console.log(err); } }); }); console.log("=== end ==="); </script> </head> <body> <h1>钉钉机器人消息发送中。。。</h1> </body> </html>
-
C#自定义控件库
2013-01-22 23:17:46C#自定义控件库 -
Android 自定义View (二) 进阶
2014-04-22 11:39:25继续自定义View之旅,前面已经介绍过一个自定义View的基础的例子,Android 自定义View (一),如果你还对自定义View不了解可以去看看。今天给大家带来一个稍微复杂点的例子。 自定义View显示一张图片,下面包含图片...转载请标明出处: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
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" format="string" /> <attr name="titleTextSize" format="dimension" /> <attr name="titleTextColor" format="color" /> <attr name="image" format="reference" /> <attr name="imageScaleType"> <enum name="fillXY" value="0" /> <enum name="center" value="1" /> </attr> <declare-styleable name="CustomImageView"> <attr name="titleText" /> <attr name="titleTextSize" /> <attr name="titleTextColor" /> <attr name="image" /> <attr name="imageScaleType" /> </declare-styleable> </resources>
2、在构造中获得我们的自定义属性:/** * 初始化所特有自定义类型 * * @param context * @param attrs * @param defStyle */ public CustomImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.CustomImageView_image: mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0)); break; case R.styleable.CustomImageView_imageScaleType: mImageScale = a.getInt(attr, 0); break; case R.styleable.CustomImageView_titleText: mTitle = a.getString(attr); break; case R.styleable.CustomImageView_titleTextColor: mTextColor = a.getColor(attr, Color.BLACK); break; case R.styleable.CustomImageView_titleTextSize: mTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; } } a.recycle(); rect = new Rect(); mPaint = new Paint(); mTextBound = new Rect(); mPaint.setTextSize(mTextSize); // 计算了描绘字体需要的范围 mPaint.getTextBounds(mTitle, 0, mTitle.length(), mTextBound); }
3、重写onMeasure@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); /** * 设置宽度 */ int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate { Log.e("xxx", "EXACTLY"); mWidth = specSize; } else { // 由图片决定的宽 int desireByImg = getPaddingLeft() + getPaddingRight() + mImage.getWidth(); // 由字体决定的宽 int desireByTitle = getPaddingLeft() + getPaddingRight() + mTextBound.width(); if (specMode == MeasureSpec.AT_MOST)// wrap_content { int desire = Math.max(desireByImg, desireByTitle); mWidth = Math.min(desire, specSize); Log.e("xxx", "AT_MOST"); } } /*** * 设置高度 */ specMode = MeasureSpec.getMode(heightMeasureSpec); specSize = MeasureSpec.getSize(heightMeasureSpec); if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate { mHeight = specSize; } else { int desire = getPaddingTop() + getPaddingBottom() + mImage.getHeight() + mTextBound.height(); if (specMode == MeasureSpec.AT_MOST)// wrap_content { mHeight = Math.min(desire, specSize); } } setMeasuredDimension(mWidth, mHeight); }
4、重写onDraw@Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); /** * 边框 */ mPaint.setStrokeWidth(4); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.CYAN); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); rect.left = getPaddingLeft(); rect.right = mWidth - getPaddingRight(); rect.top = getPaddingTop(); rect.bottom = mHeight - getPaddingBottom(); mPaint.setColor(mTextColor); mPaint.setStyle(Style.FILL); /** * 当前设置的宽度小于字体需要的宽度,将字体改为xxx... */ if (mTextBound.width() > mWidth) { TextPaint paint = new TextPaint(mPaint); String msg = TextUtils.ellipsize(mTitle, paint, (float) mWidth - getPaddingLeft() - getPaddingRight(), TextUtils.TruncateAt.END).toString(); canvas.drawText(msg, getPaddingLeft(), mHeight - getPaddingBottom(), mPaint); } else { //正常情况,将字体居中 canvas.drawText(mTitle, mWidth / 2 - mTextBound.width() * 1.0f / 2, mHeight - getPaddingBottom(), mPaint); } //取消使用掉的快 rect.bottom -= mTextBound.height(); if (mImageScale == IMAGE_SCALE_FITXY) { canvas.drawBitmap(mImage, null, rect, mPaint); } else { //计算居中的矩形范围 rect.left = mWidth / 2 - mImage.getWidth() / 2; rect.right = mWidth / 2 + mImage.getWidth() / 2; rect.top = (mHeight - mTextBound.height()) / 2 - mImage.getHeight() / 2; rect.bottom = (mHeight - mTextBound.height()) / 2 + mImage.getHeight() / 2; canvas.drawBitmap(mImage, null, rect, mPaint); } }
代码,结合注释和第一篇View的使用,应该可以看懂,不明白的留言。下面我们引入我们的自定义View:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:zhy="http://schemas.android.com/apk/res/com.zhy.customview02" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.zhy.customview02.view.CustomImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:padding="10dp" zhy:image="@drawable/ic_launcher" zhy:imageScaleType="center" zhy:titleText="hello andorid ! " zhy:titleTextColor="#ff0000" zhy:titleTextSize="30sp" /> <com.zhy.customview02.view.CustomImageView android:layout_width="100dp" android:layout_height="wrap_content" android:layout_margin="10dp" android:padding="10dp" zhy:image="@drawable/ic_launcher" zhy:imageScaleType="center" zhy:titleText="helloworldwelcome" zhy:titleTextColor="#00ff00" zhy:titleTextSize="20sp" /> <com.zhy.customview02.view.CustomImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:padding="10dp" zhy:image="@drawable/lmj" zhy:imageScaleType="center" zhy:titleText="妹子~" zhy:titleTextColor="#ff0000" zhy:titleTextSize="12sp" /> </LinearLayout>
我特意让显示出现3中情况:1、字体的宽度大于图片,且View宽度设置为wrap_content
2、View宽度设置为精确值,字体的长度大于此宽度
3、图片的宽度大于字体,且View宽度设置为wrap_content
看看显示效果:
怎么样,对于这三种情况所展示的效果都还不错吧。
好了,就到这里,各位看官,没事留个言,顶一个呗~
源码点击下载
-
vue中如何创建自定义组件并引入组件【详细教程】
2019-04-25 15:49:42今日,怂怂就为带来一篇前端vue干货,如何在vue中创建自定义组件,并且在项目中引入自定义的组件;具有很好的参考价值,一起跟怂怂过来吧,如若对您有所帮助,别忘了在文章右上角点个赞哦。 1,在你的项目中专门... -
android 自定义progressdialog
2012-04-27 17:55:03有时我们在项目执行某些耗时的操作是需要在界面上给出等待之类的信息,在android里面可以使用progressbar或者progressdialog,但是...所以需要自定义一个progressdialog,这个小例子试下了简单的自定义progressdialog -
Android自定义软键盘
2012-08-29 15:09:21Android自定义软键盘 -
自定义 UIAlertView
2012-05-09 23:21:22自定义 UIAlertView -
自定义spinner
2012-10-11 10:09:21自定义spinner的一个小列子 有缺陷 -
-
Android自定义PopupWindow
2014-05-12 21:40:49Android自定义PopupWindow,很实用 -
tensorflow 2.1 自定义训练
2020-11-07 13:49:18常常会遇到自定义网络结构的情况,自定结构后往往会有多个输入,或者还需要自定义loss或者accuracy函数,那么keras的fit就无法使用了, 因此需要自定义训练步骤 下面则自定义一次batch的训练步骤,包含了计算loss... -
IntelliJ IDEA 自定义方法注解模板
2017-08-02 18:04:36刚上手大概有一天,就知道它为啥取名为 intelli(智能化)了,确实很智能,这还是一些小小的细节,当然idea也有它不足之处,就是我们今天要讲的“自定义方法注解模板”,类注解模板可以很简单的设置,这里我就不重复... -
MySql创建自定义函数(Function)
2018-09-27 17:44:151.创建自定义函数 DELIMITER $$ DROP FUNCTION IF EXISTS genPerson$$ CREATE FUNCTION genPerson(name varchar(20)) RETURNS varchar(50) BEGIN DECLARE str VARCHAR(50) DEFAULT ''; SET @tableName=name; ... -
flink自定义source与自定义sink
2019-05-06 23:39:36flink自定义source与自定义sink -
Android 深入理解Android中的自定义属性
2015-04-13 10:42:00对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现: 自定义一个CustomView(extends View )类 编写values/attrs.xml,在其中编写styleable和item等标签元素 在布局文件中CustomView使用自定义的属性... -
C# 自定义控件,自定义属性,自定义事件
2016-05-17 18:15:33C# 自定义控件,自定义属性,自定义事件 -
JAVA线程池总结及自定义线程池
2020-06-30 16:17:51引言 在前几年小编写过一篇关于线程池的总结:《线程总结》,现在回过头来看,总结的 还是比较详细的,不过当时并没有在项目中有过真实刺激的 体验,最近项目中偶然遇到了一次任务丢失的问题,我追踪了一下 代码, ... -
Maven之自定义archetype生成项目骨架(一)
2015-07-15 16:40:45,通过该插件可以自定义符合我们自己需求的archetype。 一:什么是Archetype 总之,原型是一个Maven项目模板工具包。一个原型被定义为从其中相同类型的所有其它事情是由一个原始图案或模型。名称配合,因为我们... -
自定义Android对话框样式示例
2012-11-07 01:20:05完全自定义Android对话框AlertDialog的实现,在Android2.1下编译通过 -
Pytorch自定义加载数据--自定义Dataset
2019-09-22 08:52:16Pytorch自定义Dataset1. 自定义加载数据1.1. 第一种 Dataset class1.2. 第二种 torchvision 1. 自定义加载数据 在学习Pytorch的教程时,加载数据许多时候都是直接调用torchvision.datasets里面集成的数据集,直接... -
PHP7自定义函数
2017-08-20 09:57:29King老师精心打造的PHP7自定义函数课程,在PHP中提供了强大的系统函数来帮我们完成功能,但有时候只用系统函数往往还是不够的,还需要根据业务来封装自定义函数,本课程讲解了如何自定义函数,以及自定义函数中常见... -
学习如何自定义异常并且使用自定义异常
2019-05-06 14:09:46学习如何自定义异常并且使用自定义异常 -
Android自定义控件(十二)——自定义属性及应用
2019-12-03 12:16:46本文目录如何自定义属性format取值类型引入自定义属性代码中获取自定义属性自定义属性画圆 如何自定义属性 我们经常使用XML引入各种控件,比如TextView,Button等,使用过程中,我们通过设置各种属性值,让控件变... -
C#自定义按钮、自定义WinForm无边框窗体、自定义MessageBox窗体
2018-07-06 15:56:15C#自定义按钮、自定义WinForm无边框窗体、自定义MessageBox窗体C#自定义Button按钮控件效果展示C#自定义Winform无边框窗体效果展示 C#自定义无边框MessageBox窗体效果展示 工程源程序CSDN下载工程原程序下载更多... -
linux 常用自定义命令、自定义执行脚本
2020-12-14 22:23:30以下自定义命令维护在~/bin目录下 新建了自定义命令之后,给该文件夹下的全部自定义命令添加执行权限,参考如下 chmod u+x ./* 自定义命令创建示例 自定义log命令,用于查看日志文件等 vi /bin/log 内容如下: #!/... -
自定义ActionProvider ToolBar 自定义Menu小红点
2016-07-14 00:19:09自定义ActionProvider ToolBar 自定义Menu小红点 1. 自定义ActionProvider。2. Toolbar ActionBar自定义Menu。3. Toolbar ActionBar 右侧Menu添加角标(Toolbar ActionBar Menu添加小红点)。提供源代码。 -
Java实现自定义注解
2019-08-25 17:37:33上一篇文章介绍了注解的一些基本知识,这次来介绍下如何实现自定义注解及注解如何使用。 正文 注解是一种能被添加到java源代码中的元数据,方法、类、参数和包都可以用注解来修饰。注解...
-
MFC开发简单聊天程序
-
python办公自动化技巧
-
elasticsearch-7.10.2-darwin-x86_64.tar.gz MAC版本免费下载
-
拥抱信创 砥砺前行——操作系统HopeEdge官网正式上线
-
基于HMOPSO的数控切削参数优化模型的建立与仿真
-
软件测试基础
-
《因子投资》读书笔记:单因子模型之规模因子
-
云计算基础-Linux系统管理员
-
浅析丰富的代理IP节点的优势
-
易语言开发通达信DLL公式接口
-
SubstancePainter插件开发-基础入门
-
仿真钢琴-javascript实战
-
python自学做题记录之吃苹果
-
SQL常见用法及函数
-
Selenium3分布式与虚拟化
-
ATM技术在MSTP中的应用
-
NCL 错误 fatal:Loop end must be scalar, can‘t execute loop
-
HT32_STD_5xxxx_FWLib_v017_5137.zip
-
第3章 入门程序、常量、变量
-
lbn-test.zip