![【移动应用开发技术】Android中怎么实现一个bilibili刷新按钮_第1页](http://file4.renrendoc.com/view/21a3ba8c50635576566cd6ab4d07f2cb/21a3ba8c50635576566cd6ab4d07f2cb1.gif)
![【移动应用开发技术】Android中怎么实现一个bilibili刷新按钮_第2页](http://file4.renrendoc.com/view/21a3ba8c50635576566cd6ab4d07f2cb/21a3ba8c50635576566cd6ab4d07f2cb2.gif)
![【移动应用开发技术】Android中怎么实现一个bilibili刷新按钮_第3页](http://file4.renrendoc.com/view/21a3ba8c50635576566cd6ab4d07f2cb/21a3ba8c50635576566cd6ab4d07f2cb3.gif)
![【移动应用开发技术】Android中怎么实现一个bilibili刷新按钮_第4页](http://file4.renrendoc.com/view/21a3ba8c50635576566cd6ab4d07f2cb/21a3ba8c50635576566cd6ab4d07f2cb4.gif)
![【移动应用开发技术】Android中怎么实现一个bilibili刷新按钮_第5页](http://file4.renrendoc.com/view/21a3ba8c50635576566cd6ab4d07f2cb/21a3ba8c50635576566cd6ab4d07f2cb5.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】Android中怎么实现一个bilibili刷新按钮
Android中怎么实现一个bilibili刷新按钮,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、分析先来看看原版效果:该按钮由3部分组成,分别是圆角矩形、文字、旋转图标。在点击按钮后,开始加载数据,旋转图标发生旋转,数据加载完成后,旋转图标复位并停止旋转。话不多说,开始敲代码。2、绘制这里,我们要绘制的部分有3个,分别是上面提到的圆角矩形、文字、旋转图标。那么这里就为这3部分分别声明了一些属性。要注意的一点是,这个类中有3个构造函数,因为有部分属性需要在构造函数中初始化(也为之后自定义属性做准备),所以,将第1个与第2个构造函数中的super修改为this。public
class
LQRRefreshButton
extends
View
{
//
圆角矩形属性
private
int
borderColor
=
Color.parseColor("#fb7299");
private
float
borderWidth
=
0;
private
float
borderRadius
=
120;
//
文字属性
private
String
text
=
"点击换一批";
private
int
textColor
=
Color.parseColor("#fb7299");
private
float
textSize
=
28;
//
旋转图标属性
private
int
iconSrc
=
R.mipmap.tag_center_refresh_icon;
private
float
iconSize
=
28;
private
Bitmap
iconBitmap;
private
float
space4TextAndIcon
=
20;
//
画笔
private
Paint
mPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG);
public
LQRRefreshButton(Context
context)
{
this(context,
null);
}
public
LQRRefreshButton(Context
context,
@Nullable
AttributeSet
attrs)
{
this(context,
attrs,
0);
}
public
LQRRefreshButton(Context
context,
@Nullable
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
//
将图标资源实例化为Bitmap
iconBitmap
=
BitmapFactory.decodeResource(getResources(),
R.mipmap.tag_center_refresh_icon);
}
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
//
1、画圆角矩形
//
2、画字
//
3、画刷新图标
}
}接下来着重完成onDraw()方法的实现:@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
//
1、画圆角矩形
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(borderColor);
mPaint.setStrokeWidth(borderWidth);
canvas.drawRoundRect(new
RectF(0,
0,
getWidth(),
getHeight()),
borderRadius,
borderRadius,
mPaint);
//
2、画字
mPaint.setTextSize(textSize);
mPaint.setColor(textColor);
mPaint.setStyle(Paint.Style.FILL);
float
measureText
=
mPaint.measureText(text);
float
measureAndIcon
=
measureText
+
space4TextAndIcon
+
iconSize;
float
textStartX
=
getWidth()
/
2
-
measureAndIcon
/
2;
float
textBaseY
=
getHeight()
/
2
+
(Math.abs(mPaint.ascent())
-
mPaint.descent())
/
2;
canvas.drawText(text,
textStartX,
textBaseY,
mPaint);
//
3、画刷新图标
float
iconStartX
=
textStartX
+
measureText
+
space4TextAndIcon;
canvas.drawBitmap(iconBitmap,
iconStartX,
getHeight()
/
2
-
iconSize
/
2,
mPaint);
}先来看看效果:我给该控件设置了宽为200dp,高为100dp。可以看到效果还不错,但还是有一点点问题的,下面就分别说说这3部分是怎么画的,及存在的小问题。1)画圆角矩形其实画圆角矩形很简单,设置好画笔的样式、颜色、线粗,再调用canvas的drawRoundRect()方法即可实现。因为我们要画的圆角矩形只需要画线,所以画笔的样式便设置为Paint.Style.STROKE。canvas的drawRoundRect()方法中,第一个参数是绘制范围,这里就直接按该控件的大小来设置即可。第二、三个参数是x轴和y轴的圆角半径,第三个参数是画笔(要画东西当然需要画笔~)。但你有没有发现,此时的线粗为0(borderWidth=0),矩形线怎么还有?这是因为画笔的样式为Paint.Style.STROKE,当线粗为0时,还要画出1px的线,因为对画笔来说,最小的线粗就是1px。所以,上面的代码需要做如下改动://
1、画圆角矩形
if
(borderWidth
>
0)
{
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(borderColor);
mPaint.setStrokeWidth(borderWidth);
canvas.drawRoundRect(new
RectF(0,
0,
getWidth(),
getHeight()),
borderRadius,
borderRadius,
mPaint);
}2)画字画字的一般步骤是设置文字大小、文字颜色、画笔样式,绘制起点。其中后2个最为重要。画笔样式对画出的字是有影响的,当画笔样式为Paint.Style.STROKE时,画出来的字是镂空的(不信你可以试试),我们需要的是实心的字,所以需要修改画笔的样式为Paint.Style.FILL。在安卓中,文字的绘制跟其它绘制是不同的,例如,圆角矩形和旋转图标的绘制起点是左上角,而文字则是按文字左下字为起点,也就是按基线(Baseline)来绘制,故需要得到基线起点的坐标。如上图中,现在要获得的就是文字左下角的点,这要怎么求呢?先说x,一般需要让文字居中显示(跟文字的对齐方式也有关系,这里以默认的左对齐为例),所以计算公式一般为:x=控件宽度/2-文字长度/2。但我们这个控件有点不同,它还需要考虑到旋转图标的位置问题,所以x应该这么求:x=控件宽度/2-(文字长度+空隙+旋转图标宽度)/2。//
得到文字长度
float
measureText
=
mPaint.measureText(text);
//
得到
文字长度+空隙+旋转图标宽度
float
measureAndIcon
=
measureText
+
space4TextAndIcon
+
iconSize;
//
得到文字绘制起点
float
textStartX
=
getWidth()
/
2
-
measureAndIcon
/
2;再说y,如图所示:如果直接用控件的高度的一半作为文字绘制的基线,那么绘制出来的文字肯定偏上,这是因为Ascent的高度比Descent的高度要高的多,我们在计算Baseline时,需要在Ascent中减去Descent的高度得到两者高度差,再让控件中心y坐标加上(下降)这个高度差的一半。故:float
textBaseY
=
getHeight()
/
2
+
(Math.abs(mPaint.ascent())
-
mPaint.descent())
/
2;3)画刷新图标最后就是画刷新图标了,它是以左上角为起点的,通过canvas的drawBitmap()方法进行绘制即可。但是,有一点需要注意,iconSize是我自己定的一个大小,并不是图标的实际大小,所以在往后做旋转动画时获取到的旋转中心会有误差,将导致图标旋转时不是按中心进行旋转。所以,这里需要对图标大小进行调整:public
class
LQRRefreshButton
extends
View
{
...
public
LQRRefreshButton(Context
context,
@Nullable
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
//
icon
iconBitmap
=
BitmapFactory.decodeResource(getResources(),
iconSrc);
iconBitmap
=
zoomImg(iconBitmap,
iconSize,
iconSize);
}
public
Bitmap
zoomImg(Bitmap
bm,
float
newWidth,
float
newHeight)
{
//
获得图片的宽高
int
width
=
bm.getWidth();
int
height
=
bm.getHeight();
//
计算缩放比例
float
scaleWidth
=
((float)
newWidth)
/
width;
float
scaleHeight
=
((float)
newHeight)
/
height;
//
取得想要缩放的matrix参数
Matrix
matrix
=
new
Matrix();
matrix.postScale(scaleWidth,
scaleHeight);
//
得到新的图片
Bitmap
newbm
=
Bitmap.createBitmap(bm,
0,
0,
width,
height,
matrix,
true);
return
newbm;
}
...
}3、动画现在,要实现旋转图标的旋转功能了。原理就是在canvas绘制图标时,将canvas进行旋转,canvas旋转着绘制图标也很简单,只需要4步:canvas.save();
canvas.rotate(degress,
centerX,
centerY);
canvas.drawBitmap(iconBitmap,
iconStartX,
getHeight()
/
2
-
iconSize
/
2,
mPaint);
canvas.restore();接下来要做的,就是计算出旋转中心,旋转角度,并不停止的去调用onDraw()编制图标,可以使用ValueAnimator或ObjectAnimator实现这个功能,这里选用ObjectAnimator。实现如下:public
class
LQRRefreshButton
extends
View
{
...
private
float
degress
=
0;
private
ObjectAnimator
mAnimator;
public
LQRRefreshButton(Context
context,
@Nullable
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
//
旋转动画
mAnimator
=
ObjectAnimator.ofObject(this,
"degress",
new
FloatEvaluator(),
360,
0);
mAnimator.setDuration(2000);
mAnimator.setRepeatMode(ObjectAnimator.RESTART);
mAnimator.setInterpolator(new
LinearInterpolator());
mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
}
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
...
//
3、画刷新图标
float
iconStartX
=
textStartX
+
measureText
+
space4TextAndIcon;
canvas.save();
float
centerX
=
iconStartX
+
iconSize
/
2;
int
centerY
=
getHeight()
/
2;
canvas.rotate(degress,
centerX,
centerY);
canvas.drawBitmap(iconBitmap,
iconStartX,
getHeight()
/
2
-
iconSize
/
2,
mPaint);
canvas.restore();
}
public
void
start()
{
mAnimator.start();
}
public
void
stop()
{
mAnimator.cancel();
setDegress(0);
}
public
float
getDegress()
{
return
degress;
}
public
void
setDegress(float
degress)
{
this.degress
=
degress;
invalidate();
}
}使用ObjectAnimator可以对任意属性值进行修改,所以需要在该控件中声明一个旋转角度变量(degress),并编写getter和setter方法,还需要在setter方法中调用invalidate(),这样才能在角度值发生变换时,让控件回调onDraw()进行图标的旋转绘制。ObjectAnimator的使用也不复杂,这里就不详细介绍了。来看下动画效果吧:4、自定义属性一个自定义控件,是不能把属性值写死在控件里的,所以我们需要自定义属性,从外界获取这些属性值。1)属性文件编写在attrs.xml中编写如下代码:<?xml
version="1.0"
encoding="utf-8"?>
<resources>
<declare-styleable
name="LQRRefreshButton">
<attr
name="refresh_btn_borderColor"
format="color"/>
<attr
name="refresh_btn_borderWidth"
format="dimension"/>
<attr
name="refresh_btn_borderRadius"
format="dimension"/>
<attr
name="refresh_btn_text"
format="string"/>
<attr
name="refresh_btn_textColor"
format="color"/>
<attr
name="refresh_btn_textSize"
format="dimension"/>
<attr
name="refresh_btn_iconSrc"
format="reference"/>
<attr
name="refresh_btn_iconSize"
format="dimension"/>
<attr
name="refresh_btn_space4TextAndIcon"
format="dimension"/>
</declare-styleable>
</resources>2)属性值获取在控件的第三个构造函数中获取这些属性值:public
class
LQRRefreshButton
extends
View
{
public
LQRRefreshButton(Context
context,
@Nullable
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
//
获取自定义属性值
TypedArray
ta
=
context.obtainStyledAttributes(attrs,
R.styleable.LQRRefreshButton);
borderColor
=
ta.getColor(R.styleable.LQRRefreshButton_refresh_btn_borderColor,
Color.parseColor("#fb7299"));
borderWidth
=
ta.getDimension(R.styleable.LQRRefreshButton_refresh_btn_borderWidth,
dipToPx(0));
borderRadius
=
ta.getDimension(R.styleable.LQRRefreshButton_refresh_btn_borderRadius,
dipToPx(60));
text
=
ta.getString(R.styleable.LQRRefreshButton_refresh_btn_text);
if
(text
==
null)
text
=
"";
textColor
=
ta.getColor(R.styleable.LQRRefreshButton_refresh_btn_textColor,
Color.parseColor("#fb7299"));
textSize
=
ta.getDimension(R.styleable.LQRRefreshButton_refresh_btn_textSize,
spToPx(14));
iconSrc
=
ta.getResourceId(R.styleable.LQRRefreshButton_refresh_btn_ic
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 养殖买卖的合同范本
- 2025企业年金基金托管合同范本
- 2025江苏省建设工程造价咨询合同(示范文本)
- 油罐安全合同范本
- 2025企业管理资料范本福建劳动合同范本
- 2025衢州市衢江区高家镇湖仁村物业用房及厂房租赁合同
- 汽车货物运输合同协议书
- 2025【合同范本】农村土地承包合同
- 2025“谁造谁有”林地使用合同书
- 货物运输合同协议书模板
- 工程造价咨询服务方案(技术方案)
- 整体租赁底商运营方案(技术方案)
- 常用药物作用及副作用课件
- 小学生作文方格纸A4纸直接打印版
- 老人心理特征和沟通技巧
- 幼儿阿拉伯数字描红(0-100)打印版
- 标杆地产集团 研发设计 工程管理 品质地库标准研发成果V1.0
- TMS开发业务需求文档
- 2023年1月浙江高考英语听力试题及答案(含MP3+录音原文)
- HI-IPDV10芯片产品开发流程V10宣课件
- 房产抵押注销申请表
评论
0/150
提交评论