濮阳网站,做网站 支付账号免费吗,婚纱网站设计目标,wordpress 媒体库代码先上效果图#xff08;如果感兴趣请看后面讲解#xff09;#xff1a;
1、登录效果展示 2、关注效果展示 1、【画圆角矩形】
画图首先是onDraw方法#xff08;我会把圆代码写上#xff0c;一步一步剖析#xff09;#xff1a; 首先在view中定义个属性#xff1a;priv…先上效果图如果感兴趣请看后面讲解
1、登录效果展示 2、关注效果展示 1、【画圆角矩形】
画图首先是onDraw方法我会把圆代码写上一步一步剖析 首先在view中定义个属性private RectF rectf new RectF();//可以理解为装载控件按钮的区域
rectf.left current_left;
rectf.top 0; //这2点确定空间区域左上角current_left,是为了后面动画矩形变成等边矩形准备的这里你可以看成0
rectf.right width - current_left;
rectf.bottom height; //通过改变current_left大小更新绘制就会实现了动画效果
//画圆角矩形
//参数1区域
//参数2,3圆角矩形的圆角其实就是矩形圆角的半径
//参数4画笔
canvas.drawRoundRect(rectf, circleAngle, circleAngle, paint)2、【确定控件的大小】
上面是画圆角那width和height怎么来呢当然是通过onMeasure
Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {height measuredHeight(heightMeasureSpec); //这里是测量控件大小width measureWidth(widthMeasureSpec); //我们经常可以看到我们设置控件wrap_contentmatch_content或者固定值setMeasuredDimension(width, height);
}下面以measureWidth为例
private int measureWidth(int widthMeasureSpec) {int result;int specMode MeasureSpec.getMode(widthMeasureSpec);int specSize MeasureSpec.getSize(widthMeasureSpec);//这里是精准模式比如match_content,或者是你控件里写明了控件大小if (specMode MeasureSpec.EXACTLY) {result specSize;} else {//这里是wrap_content模式其实这里就是给一个默认值//下面这段注销代码是最开始如果用户不设置大小给他一个默认固定值。这里以字体长度来决定更合理//result (int) getContext().getResources().getDimension(R.dimen.dp_150);//这里是我设置的长度当然你写自定义控件可以设置你想要的逻辑根据你的实际情况result buttonString.length() * textSize height * 5 / 3;if (specMode MeasureSpec.AT_MOST) {result Math.min(result, specSize);}}return result;}3、【绘制文字text】
这里我是用自己的方式实现当文字长度超过控件长度时文字需要来回滚动。所以自定义控件因为你需要什么样的功能可以自己去实现当然这个方法也是在onDraw里,为什么这么个顺序讲目的希望我希望你能循序渐进的理解如果你觉得onDraw方代码太杂你可以用个方法独立出去你可以跟作者一样用private void drawText(Canvas canvas) {} //绘制文字的路径文字过长时文字来回滚动需要用到
private Path textPath new Path()
textRect.left 0;
textRect.top 0;
textRect.right width;
textRect.bottom height; //这里确定文字绘制区域其实就是控件区域
Paint.FontMetricsInt fontMetrics textPaint.getFontMetricsInt();
//这里是获取文字绘制的y轴位置可以理解上下居中
int baseline (textRect.bottom textRect.top - fontMetrics.bottom - fontMetrics.top) / 2;
//这里判断文字长度是否大于控件长度当然我控件2边需要留文字的间距所以不是大于width这么说只是更好的理解
//这里是当文字内容大于控件长度启动回滚效果。建议先看下面else里的正常情况
if ((buttonString.length() * textSize) (width - height * 5 / 3)) {textPath.reset()//因为要留2遍间距以heigh/3为间距textPath.moveTo(height / 3, baseline);textPath.lineTo(width - height / 3, baseline);//这里的意思是文字从哪里开始写可以是居中这里是右边textPaint.setTextAlign(Paint.Align.RIGHT);//这里是以路径绘制文字scrollSize可以理解为文字在x轴上的便宜量同时我的混动效果就是通过改变scrollSize//刷新绘制来实现canvas.drawTextOnPath(buttonString, textPath, scrollSize, 0, textPaint);if (isShowLongText) {//这里是绘制遮挡物因为绘制路径没有间距这方法所以绘制遮挡物类似于间距方式canvas.drawRect(new Rect(width - height / 2 - textSize / 3, 0, width - height / 2, height),paintOval);canvas.drawRect(new Rect(height / 2, 0, height / 2 textSize / 3, height), paintOval);//这里有个bug 有个小点-5 因画笔粗细产生canvas.drawArc(new RectF(width - height, 0, width - 5, height), -90, 180, true, paintOval);canvas.drawArc(new RectF(0, 0, height, height), 90, 180, true, paintOval);}if (animator_text_scroll null) { //这里是计算混到最右边和最左边的距离范围animator_text_scroll ValueAnimator.ofInt(buttonString.length() * textSize - width height * 2 / 3,-textSize);//这里是动画的时间scrollSpeed可以理解为每个文字滚动控件外所需的时间可以做成控件属性提供出去 animator_text_scroll.setDuration(buttonString.length() * scrollSpeed);//设置动画的模式这里是来回滚动animator_text_scroll.setRepeatMode(ValueAnimator.REVERSE);//设置插值器让整个动画流畅animator_text_scroll.setInterpolator(new LinearInterpolator());//这里是滚动次数-1无限滚动animator_text_scroll.setRepeatCount(-1);animator_text_scroll.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {Overridepublic void onAnimationUpdate(ValueAnimator animation) {//改变文字路径x轴的偏移量scrollSize (int) animation.getAnimatedValue();postInvalidate();}});animator_text_scroll.start();}
} else {//这里是正常情况isShowLongText是我在启动控件动画的时候是否启动 文字有渐变效果的标识//如果是长文字启动渐变效果的话如果控件变小文字内容在当前控件外会显得很难看所以根据这个标识关闭这里你可以先忽略同时因为根据路径绘制text不能有间距效果这个标识还是判断是否在控件2遍绘制遮挡物这是作者的解决方式如果你有更好的方式可以在下方留言isShowLongText false;/*** 简单的绘制文字没有考虑文字长度超过控件长度* *///这里是居中显示textPaint.setTextAlign(Paint.Align.CENTER);//参数1文字//参数2,3绘制文字的中心点//参数4画笔canvas.drawText(buttonString, textRect.centerX(), baseline, textPaint);
}4、【自定义控件属性】
?xml version1.0 encodingutf-8?
resourcesdeclare-styleable nameSmartLoadingViewattr nametextStr formatstring /attr nameerrorStr formatstring /attr namecannotclickBg formatcolor /attr nameerrorBg formatcolor /attr namenormalBg formatcolor /attr namecornerRaius formatdimension /attr nametextColor formatcolor /attr nametextSize formatdimension /attr namescrollSpeed formatinteger //declare-styleable
/resources这里以文案为例 textStr。比如你再布局种用到app:txtStr“文案内容”。在自定义控件里获取如下
public SmartLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//自定义控件的3参方法的attrs就是我们设置自定义属性的关键//比如我们再attrs.xml里自定义了我们的属性TypedArray typedArray getContext().obtainStyledAttributes(attrs, R.styleable.SmartLoadingView);//这里是获取用户有没有设置整个属性//这里是从用户那里获取有没有设置文案String title typedArray.getString(R.styleable.SmartLoadingView_textStr);if (TextUtils.isEmpty(title)){//如果获取来的属性是空那么可以默认一个属性//作者忘记设置了!因为已经发布后期优化老尴尬了buttonString 默认文案;}else{//如果有设置文案buttonString title;}}5、【设置点击事件启动动画】
为了点击事件的直观也可以把处理防止重复点击事件封装在里面
//这是我自定义登录点击的接口
public interface LoginClickListener {void click();
}public void setLoginClickListener(final LoginClickListener loginClickListener) {this.setOnClickListener(new OnClickListener() {Overridepublic void onClick(View v) {if (loginClickListener ! null) {//防止重复点击if (!isAnimRuning) {start();loginClickListener.click();}}}});
}6、【动画讲解】
6.1、第一个动画矩形到正方形以及矩形到圆角矩形这里是2个动画只是同时进行
矩形到正方形为了简化我把源码一些其他属性去掉了这样方便理解
//其中 default_all_distance (w - h) / 2除以2是因为2遍都往中间缩短
private void set_rect_to_circle_animation() {//这是一个属性动画current_left 会在duration时间内从0到default_all_distance匀速变化//想添加多样化的话 还可以加入插值器。animator_rect_to_square ValueAnimator.ofInt(0, default_all_distance);animator_rect_to_square.setDuration(duration);animator_rect_to_square.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {Overridepublic void onAnimationUpdate(ValueAnimator animation) {//这里的current_left跟onDraw相关还记得吗//onDraw里的控件区域 //控件左边区域 rectf.left current_left;//控件右边区域 rectf.right width - current_left;current_left (int) animation.getAnimatedValue();//刷新绘制invalidate();}});矩形到圆角矩形。就是从一个没有圆角的变成完全圆角的矩形当然我展示的时候只有第三个图最后一个按钮才明显了。
其他的我直接设置成了圆角按钮因为我把圆角做成了一个属性。
还记得onDraw里的canvas.drawRoundRect(rectf, circleAngle, circleAngle, paint)circleAngle就是圆角的半径
可以想象一下如果全是圆角那么circleAngle会是多少当然是height/2;没错吧所以
因为我把圆角做成了属性obtainCircleAngle是从xml文件获取的属性如果不设置则为0就没有任何圆角效果
animator_rect_to_angle ValueAnimator.ofInt(obtainCircleAngle, height / 2);
animator_rect_to_angle.setDuration(duration);
animator_rect_to_angle.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {Overridepublic void onAnimationUpdate(ValueAnimator animation) {//这里试想下如果是一个正方形刚好是圆形的圆角那就是一个圆circleAngle (int) animation.getAnimatedValue();//刷新绘画invalidate();}
});2个属性动画做好后用 private AnimatorSet animatorSet new AnimatorSet();把属性动画加进去可以设置2个动画同时进行还是先后顺序 这里是同时进行所用用with
animatorSet.play(animator_rect_to_square).with(animator_rect_to_angle);6.2、变成圆形后有一个loading加载动画
这里就是画圆弧只是不断改变圆弧的起始点和终点最终呈现loading状态也是在onDraw里
//绘制加载进度
if (isLoading) {//参数1绘制圆弧区域//参数2,3绘制圆弧起始点和终点canvas.drawArc(new RectF(width / 2 - height / 2 height / 4, height / 4, width / 2 height / 2 - height / 4, height / 2 height / 2 - height / 4), startAngle, progAngle, false, okPaint);//这里是我通过实践实现最佳loading动画//当然这里有很多方式因为我自定义这个view想把所有东西都放在这个类里面你也可以有你的方式//如果有更好的方式欢迎留言告知我一下startAngle 6;if (progAngle 270) {progAngle - 2;isAdd false;} else if (progAngle 45) {progAngle 6;isAdd true;} else {if (isAdd) {progAngle 6;} else {progAngle - 2;}}//刷新绘制这里不用担心有那么多刷新绘制会不会影响性能//postInvalidate();
}6.3、loading状态到打勾动画
那么这里首先要把loading动画取消那么直接改变isLoadingfalse;不会只它同时启动打勾动画打勾动画的动画这里比较麻烦也是我在别人自定义动画里学习的通过PathMeasure实现路径动画
/*** 路径--用来获取对勾的路径*/
private Path path new Path();
/*** 取路径的长度*/
private PathMeasure pathMeasure;//初始化打勾动画路径
private void initOk() {//对勾的路径path.moveTo(default_all_distance height / 8 * 3, height / 2);path.lineTo(default_all_distance height / 2, height / 5 * 3);path.lineTo(default_all_distance height / 3 * 2, height / 5 * 2);pathMeasure new PathMeasure(path, true);
}//初始化打勾动画
private void set_draw_ok_animation() {animator_draw_ok ValueAnimator.ofFloat(1, 0);animator_draw_ok.setDuration(duration);animator_draw_ok.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {Overridepublic void onAnimationUpdate(ValueAnimator animation) {startDrawOk true;isLoading false;float value (Float) animation.getAnimatedValue();effect new DashPathEffect(new float[]{pathMeasure.getLength(), pathMeasure.getLength()}, value * pathMeasure.getLength());okPaint.setPathEffect(effect);invalidate();}});
}//启动打勾动画只需要调用
animator_draw_ok.start();onDraw里绘制打勾动画
//绘制打勾这是onDraw的startDrawOk是判断是否开启打勾动画的标识
if (startDrawOk) {canvas.drawPath(path, okPaint);
}6.4、loading状态下回到失败样子有点类似联网失败了
之前6.1提到了矩形到圆角矩形和矩形到正方形的动画
那么这里只是前面2个动画反过来再加上联网失败的文案和联网失败的背景图即刻
6.5、loading状态下启动扩散全屏动画重点
这里我通过loginSuccess里参数的类型启动不同效果
1、启动扩散全屏动画
public void loginSuccess(Animator.AnimatorListener endListener) {}2、启动打勾动画
public void loginSuccess(AnimationOKListener animationOKListener) {}启动扩散全屏是本文的重点里面还涉及到了一个自定义view
CirclBigView,这个控件是全屏的而且是从一个小圆不断改变半径变成大圆的动画那么有人会问全屏肯定不好啊会影响布局
但是这里我把它放在了activity的视图层
ViewGroup activityDecorView (ViewGroup) ((Activity) getContext()).getWindow().getDecorView();
ViewGroup.LayoutParams layoutParams new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
activityDecorView.addView(circlBigView, layoutParams);这个灵感也是前不久在学习微信拖拽退出的思路里发现的。全部代码如下
public void toBigCircle(Animator.AnimatorListener endListener) {//把缩小到圆的半径告诉circlBigViewcirclBigView.setRadius(this.getMeasuredHeight() / 2);//把当前背景颜色告诉circlBigViewcirclBigView.setColorBg(normal_color);int[] location new int[2];//测量当前控件所在的屏幕坐标x,ythis.getLocationOnScreen(location);//把当前坐标告诉circlBigView同时circlBigView会计算当前点到屏幕4个点的最大距离即是当前控件要扩散到的半径//具体建议读者看完本博客后去下载玩耍下。circlBigView.setXY(location[0] this.getMeasuredWidth() / 2, location[1]);if (circlBigView.getParent() null) {ViewGroup activityDecorView (ViewGroup) ((Activity) getContext()).getWindow().getDecorView();ViewGroup.LayoutParams layoutParams new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);activityDecorView.addView(circlBigView, layoutParams);}circlBigView.startShowAni(endListener);isAnimRuning false;
}结束语
因为项目是把之前的功能写成了控件所以有很多地方不完善。希望有建议的大牛和小伙伴提示提示我让我完善的更好。谢谢 更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》 1.Android车载应用开发系统学习指南附项目实战
2.Android Framework学习指南助力成为系统级开发高手
3.2023最新Android中高级面试题汇总解析告别零offer
4.企业级Android音视频开发学习路线项目实战附源码
5.Android Jetpack从入门到精通构建高质量UI界面
6.Flutter技术解析与实战跨平台首要之选
7.Kotlin从入门到实战全方面提升架构基础
8.高级Android插件化与组件化含实战教程和源码
9.Android 性能优化实战360°全方面性能调优
10.Android零基础入门到精通高手进阶之路
敲代码不易关注一下吧。ღ( ´ᴗ ) 文章转载自: http://www.morning.hous-e.com.gov.cn.hous-e.com http://www.morning.rlfr.cn.gov.cn.rlfr.cn http://www.morning.xhgcr.cn.gov.cn.xhgcr.cn http://www.morning.mgbcf.cn.gov.cn.mgbcf.cn http://www.morning.dqkrf.cn.gov.cn.dqkrf.cn http://www.morning.bnpn.cn.gov.cn.bnpn.cn http://www.morning.qzpw.cn.gov.cn.qzpw.cn http://www.morning.hmmnb.cn.gov.cn.hmmnb.cn http://www.morning.brnwc.cn.gov.cn.brnwc.cn http://www.morning.tpyjr.cn.gov.cn.tpyjr.cn http://www.morning.lmhcy.cn.gov.cn.lmhcy.cn http://www.morning.nqbkb.cn.gov.cn.nqbkb.cn http://www.morning.dmzmy.cn.gov.cn.dmzmy.cn http://www.morning.gjlxn.cn.gov.cn.gjlxn.cn http://www.morning.trnl.cn.gov.cn.trnl.cn http://www.morning.bpmtx.cn.gov.cn.bpmtx.cn http://www.morning.dxxnq.cn.gov.cn.dxxnq.cn http://www.morning.osshjj.cn.gov.cn.osshjj.cn http://www.morning.dsgdt.cn.gov.cn.dsgdt.cn http://www.morning.nqwz.cn.gov.cn.nqwz.cn http://www.morning.fhrt.cn.gov.cn.fhrt.cn http://www.morning.nyzmm.cn.gov.cn.nyzmm.cn http://www.morning.mrlls.cn.gov.cn.mrlls.cn http://www.morning.pctsq.cn.gov.cn.pctsq.cn http://www.morning.mqwnz.cn.gov.cn.mqwnz.cn http://www.morning.flfdm.cn.gov.cn.flfdm.cn http://www.morning.zphlb.cn.gov.cn.zphlb.cn http://www.morning.wyppp.cn.gov.cn.wyppp.cn http://www.morning.qbwmz.cn.gov.cn.qbwmz.cn http://www.morning.tkchm.cn.gov.cn.tkchm.cn http://www.morning.wbqt.cn.gov.cn.wbqt.cn http://www.morning.smszt.com.gov.cn.smszt.com http://www.morning.xpgwz.cn.gov.cn.xpgwz.cn http://www.morning.chongzhanggui.cn.gov.cn.chongzhanggui.cn http://www.morning.gqtzb.cn.gov.cn.gqtzb.cn http://www.morning.tfzjl.cn.gov.cn.tfzjl.cn http://www.morning.ryysc.cn.gov.cn.ryysc.cn http://www.morning.snlxb.cn.gov.cn.snlxb.cn http://www.morning.scjtr.cn.gov.cn.scjtr.cn http://www.morning.srwny.cn.gov.cn.srwny.cn http://www.morning.zlff.cn.gov.cn.zlff.cn http://www.morning.nrftd.cn.gov.cn.nrftd.cn http://www.morning.xsymm.cn.gov.cn.xsymm.cn http://www.morning.crhd.cn.gov.cn.crhd.cn http://www.morning.pjyrl.cn.gov.cn.pjyrl.cn http://www.morning.dybth.cn.gov.cn.dybth.cn http://www.morning.cwznh.cn.gov.cn.cwznh.cn http://www.morning.nkqnn.cn.gov.cn.nkqnn.cn http://www.morning.zpyxl.cn.gov.cn.zpyxl.cn http://www.morning.lgcqj.cn.gov.cn.lgcqj.cn http://www.morning.qbwmz.cn.gov.cn.qbwmz.cn http://www.morning.tqrjj.cn.gov.cn.tqrjj.cn http://www.morning.qpsdq.cn.gov.cn.qpsdq.cn http://www.morning.bhwll.cn.gov.cn.bhwll.cn http://www.morning.kuaijili.cn.gov.cn.kuaijili.cn http://www.morning.wrkhf.cn.gov.cn.wrkhf.cn http://www.morning.xrwsg.cn.gov.cn.xrwsg.cn http://www.morning.fndfn.cn.gov.cn.fndfn.cn http://www.morning.dljujia.com.gov.cn.dljujia.com http://www.morning.tcxzn.cn.gov.cn.tcxzn.cn http://www.morning.wqhlj.cn.gov.cn.wqhlj.cn http://www.morning.pflpb.cn.gov.cn.pflpb.cn http://www.morning.ndxmn.cn.gov.cn.ndxmn.cn http://www.morning.zpstm.cn.gov.cn.zpstm.cn http://www.morning.plqqp.cn.gov.cn.plqqp.cn http://www.morning.ldynr.cn.gov.cn.ldynr.cn http://www.morning.czzpm.cn.gov.cn.czzpm.cn http://www.morning.zbjfq.cn.gov.cn.zbjfq.cn http://www.morning.ttcmdsg.cn.gov.cn.ttcmdsg.cn http://www.morning.lrmts.cn.gov.cn.lrmts.cn http://www.morning.hqbnx.cn.gov.cn.hqbnx.cn http://www.morning.ttvtv.cn.gov.cn.ttvtv.cn http://www.morning.bpmtx.cn.gov.cn.bpmtx.cn http://www.morning.cfccp.cn.gov.cn.cfccp.cn http://www.morning.tnhmp.cn.gov.cn.tnhmp.cn http://www.morning.syfty.cn.gov.cn.syfty.cn http://www.morning.nrqnj.cn.gov.cn.nrqnj.cn http://www.morning.yrlfy.cn.gov.cn.yrlfy.cn http://www.morning.zlxkp.cn.gov.cn.zlxkp.cn http://www.morning.qgmwt.cn.gov.cn.qgmwt.cn