先看看知乎日报开屏页的效果,非常漂亮的开屏效果

ezgif.com-resize (2).gif
然后我来一个
ezgif.com-resize (1).gif
也不错~感觉可以以假乱真了~
很简单,直接开始。
实现这个效果先制定个三步走策略
底部布局上滑展示
直接上代码吧,属性动画基本使用
private void startAnimation() {
//位移动画,从底部滑出,Y方向移动,mHeight是底部布局的高度
ObjectAnimator translationAnimator= ObjectAnimator.ofFloat(rv_bottom, "translationY", mHeight, 0f);
//设置时长
translationAnimator.setDuration(1000);
//透明度渐变动画
ObjectAnimator alphaAnimatorator = ObjectAnimator.ofFloat(rv_bottom, "alpha", 0f,1f);
//设置时长
alphaAnimatorator.setDuration(2500);
//添加监听器,位移结束后,画圆弧开始
translationAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
zhview.startAnimation();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
AnimatorSet set = new AnimatorSet();
//两个动画一起执行
set.play(translationAnimator).with(alphaAnimatorator);
//go
set.start();
}
在位移动画结束的时候,调用了自定义的view的方法,开始了画弧的操作。
画个知弧
接下来开始画画~ 自定义一个view,重写ondraw方法,开画之前先初始化一个合适的画笔。
private void initPaint() {
mPaint1 = new Paint();
//设置画笔颜色
mPaint1.setColor(Color.WHITE);
// 设置画笔的样式为圆形
mPaint1.setStrokeCap(Paint.Cap.ROUND);
// 设置画笔的填充样式为描边
mPaint1.setStyle(Paint.Style.STROKE);
//抗锯齿
mPaint1.setAntiAlias(true);
//设置画笔宽度
mPaint1.setStrokeWidth(mBorderWidth1);
mPaint2 = new Paint();
mPaint2.setColor(Color.WHITE);
mPaint2.setStyle(Paint.Style.STROKE);
mPaint2.setAntiAlias(true);
mPaint2.setStrokeWidth(mBorderWidth2);
}
mPaint1用来画弧,设置填充样式为描边,这样起码我们就能轻松画一个圆环了。其实要画的知弧就是一个圆环被啃去了一块的感觉~ 但被啃的地方很光滑,所以需要一个圆头的画笔 。
mPaint2用来画外面的圆角矩形环,设置也差不多。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLACK);
//矩形轮廓,圆弧在内部,给予一定的内边距
RectF rectF1 = new RectF(mBorderWidth1/2+dipToPx(8), mBorderWidth1/2+dipToPx(8), getWidth() -mBorderWidth1/2-dipToPx(8),getWidth()-mBorderWidth1/2-dipToPx(8) );
//画圆弧 参数1:矩形轮廓 参数2:起始位置 参数3:扫过的范围,初始为0 参数4:是否连接圆心
canvas.drawArc(rectF1, 90, mCurrentRadian, false, mPaint1);
//矩形轮廓
RectF rectF2 = new RectF(mBorderWidth2/2,mBorderWidth2/2,getWidth()-mBorderWidth2/2,getWidth()-mBorderWidth2/2);
//画圆角矩形边框 参数2 3设置x,y方向的圆角corner 都要设置
canvas.drawRoundRect(rectF2,dipToPx(8),dipToPx(8),mPaint2);
}
代码量很少,但要明确环的画法,不论是画圆环还是圆角矩形环,需要先确定一个基准矩形。基准矩形的位置和大小确定环的位置和大小。画弧的方法canvas.drawArc中的参数2 3设置了开始画弧的位置和画弧的范围。看一下运行效果,圆弧的起始画点在圆心的正下方,X轴正方向为0度,所以起始画点为90度。
接下来就使用不断增大画弧的范围的方式来完成动画的实现。上代码
private void startAnimationDraw() {
//圆弧扫过范围为270度
ValueAnimator valueAnimator=new ValueAnimator().ofFloat(0,270);
//动画持续时间
valueAnimator.setDuration(mDuration);
//设置插值器,中间快两头慢
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
//添加状态监听器
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//不断增大圆弧扫过的范围,并重绘来实现动画效果
mCurrentRadian= (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
}
使用ValueAnimator.ofFloat创建一个值为0-270的动画,添加状态监听,在动画执行的过程中不断增大扫过的范围并重绘视图从而实现了画弧的动画效果。
整个过程就是canvas配合属性动画的方式完成了动态绘图,一点也不复杂。
显示图片
这里我使用的是Glide加载的本地图片,设置了延迟加载把握图片加载时机,获得更好的开屏效果
//延时加载图片
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Glide.with(MainActivity.this).
load(R.drawable.timg).
centerCrop().
skipMemoryCache(true).
diskCacheStrategy(DiskCacheStrategy.NONE).
crossFade(500).
into(image)
;
}
},2000);
这里个人认为知乎也是用某种方式预先把图片下载到本地完成来把握精确地加载时机,不知道是不是这样。。
最后贴一下代码
activity
public class MainActivity extends AppCompatActivity {
private RelativeLayout rv_bottom;
private Zhview zhview;
private float mHeight;
private ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rv_bottom= (RelativeLayout) this.findViewById(R.id.rv_bottom);
zhview= (Zhview) this.findViewById(R.id.zhview);
image= (ImageView) this.findViewById(R.id.image);
rv_bottom.post(new Runnable() {
@Override
public void run() {
//获得底部的高度
mHeight=rv_bottom.getHeight();
//开始动画
startAnimation();
//延时加载图片
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Glide.with(MainActivity.this).
load(R.drawable.timg).
centerCrop().
skipMemoryCache(true).
diskCacheStrategy(DiskCacheStrategy.NONE).
crossFade(500).
into(image)
;
}
},2000);
}
});
}
private void startAnimation() {
//位移动画,从底部滑出,Y方向移动
ObjectAnimator translationAnimator= ObjectAnimator.ofFloat(rv_bottom, "translationY", mHeight, 0f);
//设置时长
translationAnimator.setDuration(1000);
//透明度渐变动画
ObjectAnimator alphaAnimatorator = ObjectAnimator.ofFloat(rv_bottom, "alpha", 0f,1f);
//设置时长
alphaAnimatorator.setDuration(2500);
//添加监听器,位移结束后,画圆弧开始
translationAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
zhview.startAnimation();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
AnimatorSet set = new AnimatorSet();
//两个动画一起执行
set.play(translationAnimator).with(alphaAnimatorator);
//go
set.start();
}
}
自定义view
public class Zhview extends View {
private Paint mPaint1; //圆弧画笔
private Paint mPaint2; //外框画笔
//圆弧宽度
private int mBorderWidth1=dipToPx(5);
//外框宽度
private int mBorderWidth2=dipToPx(1.5f);
//扫过的范围
private float mCurrentRadian=0;
//动画持续时长
private int mDuration=1500;
public Zhview(Context context) {
this(context,null);
}
public Zhview(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public Zhview(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//初始化画笔
initPaint();
}
private void initPaint() {
mPaint1 = new Paint();
//设置画笔颜色
mPaint1.setColor(Color.WHITE);
// 设置画笔的样式为圆形
mPaint1.setStrokeCap(Paint.Cap.ROUND);
// 设置画笔的填充样式为描边
mPaint1.setStyle(Paint.Style.STROKE);
//抗锯齿
mPaint1.setAntiAlias(true);
//设置画笔宽度
mPaint1.setStrokeWidth(mBorderWidth1);
mPaint2 = new Paint();
mPaint2.setColor(Color.WHITE);
mPaint2.setStyle(Paint.Style.STROKE);
mPaint2.setAntiAlias(true);
mPaint2.setStrokeWidth(mBorderWidth2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLACK);
//矩形轮廓,圆弧在内部,给予一定的内边距
RectF rectF1 = new RectF(mBorderWidth1/2+dipToPx(8), mBorderWidth1/2+dipToPx(8), getWidth() -mBorderWidth1/2-dipToPx(8),getWidth()-mBorderWidth1/2-dipToPx(8) );
//画圆弧 参数1:矩形轮廓 参数2:起始位置 参数3:扫过的范围,初始为0 参数4:是否连接圆心
canvas.drawArc(rectF1, 90, mCurrentRadian, false, mPaint1);
//矩形轮廓
RectF rectF2 = new RectF(mBorderWidth2/2,mBorderWidth2/2,getWidth()-mBorderWidth2/2,getWidth()-mBorderWidth2/2);
//画圆角矩形边框 参数2 3设置x,y方向的圆角corner 都要设置
canvas.drawRoundRect(rectF2,dipToPx(8),dipToPx(8),mPaint2);
}
private void startAnimationDraw() {
//圆弧扫过范围为270度
ValueAnimator valueAnimator=new ValueAnimator().ofFloat(0,270);
//动画持续时间
valueAnimator.setDuration(mDuration);
//设置插值器,中间快两头慢
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
//添加状态监听器
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//不断增大圆弧扫过的范围,并重绘来实现动画效果
mCurrentRadian= (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
}
//开始动画
public void startAnimation(){
startAnimationDraw();
}
private int dipToPx(float dip) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
tools:context="com.zhview.MainActivity">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/rv_bottom" />
<RelativeLayout
android:id="@+id/rv_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:padding="20dp">
<com.zhview.Zhview
android:id="@+id/zhview"
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@+id/zhview"
android:text="知乎日报"
android:textColor="@android:color/white"
android:textSize="19sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/zhview"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@+id/zhview"
android:text="每天三次,每次七分钟"
android:textColor="@android:color/darker_gray"
android:textSize="13sp" />
</RelativeLayout>
</RelativeLayout>
我个人挺喜欢这些实现起来不复杂但体验非常好的设计,见到了就努力实现一下,然后边学边分享,要是跟我一样感兴趣的话可以关注我一下哦~
完整代码地址https://github.com/yanyiqun001/zhview
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android
# 知乎日报
# 开屏页
# Android 逆向学习详解及实例
# 使用android-apktool来逆向(反编译)APK包方法介绍
# 通过FancyView提供 Android 酷炫的开屏动画实例代码
# Android开屏页倒计时功能实现的详细教程
# Android 监听锁屏、解锁、开屏 功能代码
# Android实现加载广告图片和倒计时的开屏布局
# Android使用ViewPager实现滚动广告
# Android实现自适应屏幕的弹窗广告
# Android Viewpager实现轮播广告图
# Android 知乎广告效果实现代码
# Android逆向技巧——去除开屏广告
# 扫过
# 时长
# 圆角
# 加载
# 自定义
# 都要
# 开屏
# 来实现
# 持续时间
# 画一
# 的是
# 在内部
# 滑出
# 插值
# 结束后
# 抗锯齿
# 去了
# 就能
# 以假乱真
# 我来
相关文章:
小建面朝正北,A点实际方位是否存在偏差?
安徽网站建设与外贸建站服务专业定制方案
建站之星如何防范黑客攻击与数据泄露?
制作网站的过程怎么写,用凡科建站如何制作自己的网站?
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
唐山网站制作公司有哪些,唐山找工作哪个网站最靠谱?
如何通过虚拟机搭建网站?详细步骤解析
宝塔面板创建网站无法访问?如何快速排查修复?
如何在Windows环境下新建FTP站点并设置权限?
香港服务器建站指南:免备案优势与SEO优化技巧全解析
建站之星在线版空间:自助建站+智能模板一键生成方案
如何批量查询域名的建站时间记录?
制作证书网站有哪些,全国城建培训中心证书查询官网?
制作网页的网站有哪些,电脑上怎么做网页?
网站制作中优化长尾关键字挖掘的技巧,建一个视频网站需要多少钱?
制作网站外包平台,自动化接单网站有哪些?
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
MySQL查询结果复制到新表的方法(更新、插入)
建站10G流量真的够用吗?如何应对访问高峰?
如何在搬瓦工VPS快速搭建网站?
浅谈Javascript中的Label语句
建站一年半SEO优化实战指南:核心词挖掘与长尾流量提升策略
如何用搬瓦工VPS快速搭建个人网站?
公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?
公众号网站制作网页,微信公众号怎么制作?
如何在橙子建站上传落地页?操作指南详解
建站之星微信建站一键生成小程序+多端营销系统
大学网站设计制作软件有哪些,如何将网站制作成自己app?
如何确保FTP站点访问权限与数据传输安全?
在线教育网站制作平台,山西立德教育官网?
网站制作和推广的区别,想自己建立一个网站做推广,有什么快捷方法马上做好一个网站?
ppt制作免费网站有哪些,ppt模板免费下载网站?
成都响应式网站开发,dw怎么把手机适应页面变成网页?
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?
微信推文制作网站有哪些,怎么做微信推文,急?
高端网站建设与定制开发一站式解决方案 中企动力
如何选择适合PHP云建站的开源框架?
智能起名网站制作软件有哪些,制作logo的软件?
如何续费美橙建站之星域名及服务?
网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?
青浦网站制作公司有哪些,苹果官网发货地是哪里?
平台云上自主建站:模板化设计与智能工具打造高效网站
如何选择服务器才能高效搭建专属网站?
三星网站视频制作教程下载,三星w23网页如何全屏?
宝华建站服务条款解析:五站合一功能与SEO优化设置指南
用v-html解决Vue.js渲染中html标签不被解析的问题
名字制作网站免费,所有小说网站的名字?
中山网站推广排名,中山信息港登录入口?
如何彻底卸载建站之星软件?
*请认真填写需求信息,我们会在24小时内与您取得联系。