Android_水瓶loading和圆环loading
来源:互联网 发布:安利云服务软件 编辑:程序博客网 时间:2024/05/02 19:36
自定义Loading套路
一般自定义loading都是重写dialog,修改dialog内部的contentview,
先看下效果图,
demo里面包含了两个小loading,今天的目标就是实现这个两个小玩意,
- 描写自定义类,继承dialog,
- 在oncreat中设置外面传递过来的自定义view,
- 在builder属性中,给外面的dialog设置属性
- 这里我们模仿Android系统的做法用建造者模式来配置属性
下面看下dialog的代码,
public class ATWaterDialog extends Dialog {// 提供配置dialog的一些属性 private Context mContext; private int mLoadingViewLayout; private String mLoadingDesc; private boolean mCancelable; private boolean mOutsideCancelable; private TextView mTextView;// 因为我们要用建造者模式,构造函数需要私有化 private ATWaterDialog(Context context) { this(context, 0); }// 提供接受建造者的,构造函数,不对外公开,给builder用的 private ATWaterDialog(Builder builder) { this(builder.mContext, 0); mContext = builder.mContext; mLoadingViewLayout = builder.mLoadingViewLayout; mLoadingDesc = builder.mLoadingDesc; mCancelable = builder.mCancelable; mOutsideCancelable = builder.mOutsideCancelable; } private ATWaterDialog(Context context, int themeResId) { super(context, R.style.Translucent_NoTitle); }
下面是建造者的代码
public static class Builder { private Context mContext; private int mLoadingViewLayout; private String mLoadingDesc; private boolean mCancelable; private boolean mOutsideCancelable;// 构造函数中传入必传参数,这里我们dialog需要拿到context和外面的view布局 public Builder(Context context, int loadingViewLayout) { mContext = context; mLoadingViewLayout = loadingViewLayout; } public Builder loadingDesc(String loadingDesc) { this.mLoadingDesc = loadingDesc; return this; } public Builder cancelable(boolean cancelable) { this.mCancelable = cancelable; return this; } public Builder outsideCancelable(boolean outsideCancelable) { this.mOutsideCancelable = outsideCancelable; return this; }// 建造者用dialog接受他自己的方法,构造出来一个dialog public ATWaterDialog build() { return new ATWaterDialog(this); } }
下面就是给dialog设置样子,就是我们外面传递过来的layout
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 这里很简单就是在dialog onCreate中设置布局填充dialog setContentView(mLoadingViewLayout); mTextView = (TextView) findViewById(R.id.tv_gif_oading_desc); if (null != mTextView) { mTextView.setText(mLoadingDesc); } setCancelable(mCancelable); setCanceledOnTouchOutside(mOutsideCancelable); }
最后使用的我们的dialog
//有没有很简单像造房子一样,建造各种门,床,窗户,最后show就行了 atWaterDialog = new ATWaterDialog.Builder(this, R.layout.dialog_water_loading) .cancelable(true) .outsideCancelable(true) .loadingDesc("我擦,加载....") .build();
所以自定义dialog的时候,其实还是自定义view,
下面我们看下水瓶子的View如何实现
自定义view的过程都老生常谈的话题了,套路就不写了,
- 自定义属性
- 获取属性
- 测量
- 绘制
这里用的一个知识点就是画笔的绘制模式,那张景点的图大家都不陌生我就不copy了,我们把外面传递过来的水瓶子bitmap绘制到画布上,
在绘制之前,先把画布用橡皮擦,擦成透明的,然后把水瓶画上去,
这个时候就是一个透明的画布上面有一个空瓶子,
这时候我们绘制水流,用贝塞尔曲线绘制path,
然后画笔的图层模式设置成SRC_IN,就是绘制的水波和瓶子相交的时候,我们取上层,这样就留下了瓶子样式的水流,并且根据水波的Y值一直变动
private void drawTargetBitmap() { path.reset(); bg.eraseColor(getResources().getColor(android.R.color.transparent)); // 当控制点的x坐标大于或等于终点x坐标时更改标识值 if (controlX >= defW) { isIncrease = false; } // 当控制点的x坐标小于或等于起点x坐标时更改标识值 else if (controlX <= 0) { isIncrease = true; } // 根据标识值判断当前的控制点x坐标是该加还是减 controlX = isIncrease ? controlX + 10 : controlX - 10; if (controlY >= 0) { // 波浪上移 controlY -= 1; waveY -= 1; } else { // 超出则重置位置 waveY = WAVEY_SCALE * defH; controlY = CONTROLY_SCALE * defH; } // 贝塞尔曲线的生成 path.moveTo(0, waveY); // 两个控制点通过controlX,controlY生成 path.cubicTo(controlX / 2, waveY - (controlY - waveY), (controlX + defW) / 2, controlY, defW, waveY); // 与下下边界闭合 path.lineTo(defW, defH); path.lineTo(0, defH); // 进行闭合 path.close(); mCanvas.drawBitmap(mBitmap, 0, 0, paint); paint.setXfermode(porterDuffXfermode); mCanvas.drawPath(path, paint); paint.setXfermode(null); }
然后在onDraw里面,把我们绘制的水流画布放到系统的canvas里面
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawTargetBitmap(); //这里直接把我们自己创建的bitmap放到系统的canvas里面,因为变化都在这里 canvas.drawBitmap(bg, getPaddingLeft(), getPaddingTop(), null); if (isReflesh) { invalidate(); } }
主要的就是画笔模式的使用,和一个path的使用
圆环的view就更简单了,
- 提供自定义属性圆环宽度
- 距离view的外边距距离
绘制圆环
OK完成了
圆环的知识点就一个画笔的阴影模式,以及如何让绘制的圆环动起来
- 阴影模式
// 这里有四种模式有兴趣的可以看下源代码继承结构树 circlePaint.setShader(new SweepGradient(viewWidth, viewHeight, doughnutColors, null));
- 圆环的旋转,这里因为我们背景是圆角矩形,圆形都是我们绘制了,
- 所以我们作用动画的时候不能给view设置,因为那样圆形的矩形也会旋转,
- 所以我们在绘制圆角背景后,旋转画布,然后绘制圆环这样圆环就东西来了—哈哈
代码如下:
//绘制背景 canvas.drawRoundRect(rectBg, circleCorner, circleCorner, bgPaint); //旋转画布 canvas.rotate(rotateDegree, viewWidth / 2, viewHeight / 2); //绘制圆环 canvas.drawArc(oval, 90, 360, false, circlePaint);
属性动画提供画布旋转的偏移量
private void getValAniamtion() { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.F); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { rotateDegree = 360 * Float.valueOf(valueAnimator.getAnimatedValue().toString()); invalidate(); } }); valueAnimator.setDuration(800); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.setRepeatMode(ValueAnimator.RESTART); valueAnimator.setRepeatCount(ValueAnimator.INFINITE); valueAnimator.start(); }
到此我们的dialog就自定义完毕了,荆轲刺秦王_end
源码下载地址,多多star谢谢https://github.com/GuoFeilong/ATLoading
1 0
- Android_水瓶loading和圆环loading
- Android 水瓶动画,贝塞尔Loading
- android_自定义Loading框
- Android_仿爱奇艺Loading效果
- Android自定义圆环Loading效果
- Loading动画--加载成功--圆环
- Loading.....
- loading...
- Loading
- loading
- loading
- loading
- Loading...
- Loading
- loading
- loading
- loading
- Loading...
- DeerResume:在线MarkDown简历工具
- leetcode/292. Nim Game
- form 中Enctype=multipart/form-data 的作用1、
- bzoj 1497: [NOI2006]最大获利(网络流)
- 动画部分的累计(一)翻转动画的实现
- Android_水瓶loading和圆环loading
- 变量 'F' 无法保存到 7.3 以前版本的 MAT 文件
- NDK lseek大文件无法正常seek
- spring+springmvc+mybatis整合
- 简单百度地图集成
- BZOJ 3809 Gty的二逼妹子序列
- HDU 5753 Permutation Bo(水~)
- hdu 1401/poj 1198 Solitaire(BFS,剪枝)
- iOS之沙盒机制和如何获取沙盒路径